Skip to content

Normalize away websocket response change in dropshot 0.17#87

Merged
sunshowers merged 7 commits intomainfrom
normalize-ws-responses
Apr 15, 2026
Merged

Normalize away websocket response change in dropshot 0.17#87
sunshowers merged 7 commits intomainfrom
normalize-ws-responses

Conversation

@david-crespo
Copy link
Copy Markdown
Contributor

@david-crespo david-crespo commented Apr 14, 2026

Problem

While trying to bump Dropshot to 0.17 in oxidecomputer/omicron#9995 in order to turn on gzipped responses, I ran into a problem where dropshot-api-manager doesn't know how to deal with the schema change introduced by oxidecomputer/dropshot#1554.

Bumping the API version on the affected crates does not help because the problem is when it tries to verify the existing blessed version, not the new version.

image

Solution

The fix is to convert any existing schema using the old pattern (on websocket endpoints specifically) to the new pattern before the comparison, so the change is effectively ignored.

@sunshowers and I talked about putting this in drift, but looking at drift, it felt wrong to me to put something so specific in there. Drift is quite abstract. Initially I thought this would involve changing drift to take a normalizer function to apply to the schema before doing the comparison, but the function was like two lines — we just do it here before calling compare. In order for putting something like that in drift to buy us something, it would have to be more constrained than a function that just takes the whole schema and returns a new one.

Dropshot 0.17 changed websocket endpoint representation in OpenAPI
(oxidecomputer/dropshot#1554): from a default response with */* content
to explicit 101/4XX/5XX responses. This is a spec-generation change,
not a wire-format change, but drift reports it as incompatible.

Uses the new drift::compare_with_normalizer to rewrite old-format
websocket responses in blessed specs before comparison. The normalizer
detects operations with x-dropshot-websocket that have a default
response and replaces their responses with those from the generated
spec.

Also adds a versioned_ws test fixture with a #[channel] endpoint and
integration tests proving the normalization works (including a test
that verifies drift fails without it).
@david-crespo david-crespo requested a review from sunshowers April 14, 2026 20:10
}

#[test]
fn test_normalize_missing_generated_path_leaves_blessed_unchanged() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good test.

Comment thread crates/integration-tests/tests/integration/versioned.rs Outdated
Comment thread crates/integration-tests/tests/integration/versioned.rs Outdated

/// Rewrite a versioned API document to old websocket format and rename the
/// file to match the new content hash. Returns the new relative path.
fn rewrite_versioned_doc_ws_format(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I have a suggestion for a better way to do this -- can you write a custom extractor that produces the old response type?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea, done in e19835c. Let me know if that's what you had in mind.

Comment thread crates/dropshot-api-manager/src/compatibility.rs Outdated
Comment thread crates/integration-tests/src/fixtures.rs
Comment thread crates/integration-tests/src/fixtures.rs Outdated
blessed: &mut serde_json::Value,
generated: &serde_json::Value,
) {
// Exact JSON for the old and new websocket response formats. We only
Copy link
Copy Markdown
Collaborator

@sunshowers sunshowers Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will re-initialize these objects for each blessed API, but I think that's fine (this is parallelized + also there are many things that are much more time-consuming).

The alternative would be to put these in a OnceLock.

@sunshowers sunshowers merged commit 7b393ad into main Apr 15, 2026
6 checks passed
@sunshowers sunshowers deleted the normalize-ws-responses branch April 15, 2026 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants