-
Notifications
You must be signed in to change notification settings - Fork 237
IPIP-0523: Prefer format request param over Accept header #523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| --- | ||
| title: "IPIP-0523: Prefer format param over Accept header" | ||
| date: 2025-11-26 | ||
| ipip: proposal | ||
| editors: | ||
| - name: Alex Potsides | ||
| github: achingbrain | ||
| url: https://achingbrain.net | ||
| affiliation: | ||
| name: Shipyard | ||
| url: https://ipshipyard.com | ||
| - name: Marcin Rataj | ||
| github: lidel | ||
| affiliation: | ||
| name: Shipyard | ||
| url: https://ipshipyard.com | ||
| relatedIssues: | ||
| - https://github.com/ipfs/specs/issues/521 | ||
| order: 523 | ||
| tags: ['ipips'] | ||
| --- | ||
|
|
||
| ## Summary | ||
|
|
||
| Prefer the `?format=` URL query parameter over the `Accept:` HTTP request header. | ||
|
|
||
| ## Motivation | ||
|
|
||
| The [`Accept`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept) | ||
| HTTP request header can be sent with an HTTP request to provide a prioritized | ||
| list of response formats the client will accept for a given resource. | ||
|
|
||
| The [`format`](https://specs.ipfs.tech/http-gateways/path-gateway/#format-request-query-parameter) | ||
| URL query parameter can also be sent to an IPFS HTTP Gateway to provide the | ||
| same information, and is typically done when sending an HTTP header is difficult | ||
| or impractical, for example when using a browser address bar. | ||
|
|
||
| The existing [Path Gateway](https://specs.ipfs.tech/http-gateways/path-gateway/#format-request-query-parameter) and [Trustless Gateway](https://specs.ipfs.tech/http-gateways/trustless-gateway/#format-request-query-parameter) specs say: | ||
|
|
||
| > When both the Accept header and format parameter are present, a specific Accept value (e.g., application/vnd.ipld.raw) SHOULD take precedence over format. | ||
|
|
||
| This makes it impossible for browsers to use the `format` URL query parameter, | ||
| since they will always send an `Accept` HTTP header which would then cause | ||
| the `format` URL query parameter to be ignored. | ||
|
|
||
| ## Detailed design | ||
|
|
||
| The priority of the `format` URL query parameter vs the `Accept` HTTP header is | ||
| reversed in both :cite[path-gateway] and :cite[trustless-gateway] specs: the | ||
| `format` URL query parameter SHOULD always take precedence over the `Accept` | ||
| HTTP header when both are present. | ||
|
|
||
| This simplifies the specification by removing the previous wildcard exception | ||
| logic. Implementations no longer need to distinguish between specific `Accept` | ||
| header values (e.g., `application/vnd.ipld.raw`) and wildcards (e.g., `*/*`) | ||
| when determining precedence. | ||
|
|
||
| ## Design rationale | ||
|
|
||
| Browsers will always send an `Accept` HTTP header that contains specific values | ||
| so it cannot be allowed to take priority over the `format` URL query parameter. | ||
|
|
||
| ### User benefit | ||
|
|
||
| Users will be able to use the `format` URL query parameter to control the | ||
| response type of requests made from browser address bars. | ||
|
|
||
| ### Compatibility | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ @achingbrain fyi I've expanded the Compatibility section. While formally this is a breaking change, in practice (imo this is good news, means IPIP is actually cleaning up and formalizing real world behavior in browsers) |
||
|
|
||
| This change simplifies precedence rules by making the `format` URL query | ||
| parameter always take priority over the `Accept` HTTP header when both are | ||
| present. | ||
|
|
||
| In practice, this is largely compatible with existing web browser use cases. | ||
| Browsers send `Accept` HTTP headers with wildcards (e.g., `*/*` or | ||
| `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`), and | ||
| the previous spec already treated wildcards as non-specific, allowing `format` | ||
| to take precedence. This means browser address bar usage with `?format=` was | ||
| already working as expected. | ||
|
|
||
| In recent years we also realized that HTTP cache implementations are often | ||
| flawed, and virtually all HTTP clients add explicit `?format=` anyway to ensure | ||
| a unique HTTP cache key is used for each URL. This provides extra protection | ||
| from poorly written or configured software and CDNs that comingle different | ||
| response types under the same cache key (e.g., deserialized response, raw block, | ||
| and CAR being cached and returned based on what was requested and cached first). | ||
| By prioritizing `?format=` we ensure deterministic HTTP caching behavior across | ||
| the ecosystem, making it easier to deploy and reason about HTTP trustless | ||
| gateways. | ||
|
|
||
| The actual breakage is limited to edge cases where a client sends both a | ||
| specific `Accept` HTTP header (e.g., `Accept: application/vnd.ipld.raw`) and a | ||
| different `format` URL query parameter (e.g., `?format=car`). Previously, the | ||
| specific `Accept` header value would win; now `format` wins. This scenario is | ||
| rare in practice and arguably represents a client misconfiguration. | ||
|
|
||
| The primary impact is on [gateway-conformance](https://github.com/ipfs/gateway-conformance/) | ||
| tests, which explicitly test the old precedence behavior. A minor version bump | ||
| of gateway-conformance is required to update these tests. | ||
|
|
||
| ### Security | ||
|
|
||
| This change has no security implications. It only affects which response format | ||
| is returned when a client sends conflicting format preferences, and does not | ||
| change authentication, authorization, or data integrity behaviors. | ||
|
|
||
| ### Alternatives | ||
|
|
||
| **Keep status quo with wildcard exception**: The previous spec already had a | ||
| carve-out where wildcards (e.g., `*/*`, `application/*`) in the `Accept` HTTP | ||
| header did not take precedence over the `format` URL query parameter. This meant | ||
|
Comment on lines
+109
to
+111
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe also a bad alternative since there's still a need to handle wildcard complexity, but it seems like it'd be helpful if implementations rejected as invalid conflicting requests (e.g. request for a block in the header, but a CAR in the query parameter). i.e. the rule becomes:
|
||
| browser use cases were effectively supported, since browsers include wildcards | ||
| in their default `Accept` HTTP headers. | ||
|
|
||
| This alternative was rejected because: | ||
|
|
||
| 1. The wildcard exception adds implementation complexity | ||
| 2. The resulting behavior is harder to reason about and document | ||
| 3. The simpler rule ("format always wins") is easier to understand and implement | ||
| 4. Real-world browser use cases work identically under both rules | ||
|
|
||
| ## Test fixtures | ||
|
|
||
| Implementers can either write own test that prefers the `format` URL query | ||
| parameter over any present `Accept` HTTP header, or run the | ||
| [gateway-conformance](https://github.com/ipfs/gateway-conformance/) test suite, | ||
| which includes tests for this scenario since | ||
| [gateway-conformance/pull/252](https://github.com/ipfs/gateway-conformance/pull/252). | ||
|
|
||
| ### Copyright | ||
|
|
||
| Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this change imply there's also an exception around
format=carsince there's no way to express particular parameters about the requested CAR (e.g. DFS, skipping duplicates, etc.)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so because you can use the
car-dups,car-order, etc params.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops sorry clumsy question 🤦. Thanks for the correction