From 824cf89c921cb344563c138d4c9577c6b5c891bc Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 26 Nov 2025 18:26:18 +0200 Subject: [PATCH 1/3] IPIP-0523: Prefer format request param over Accept header Browsers will always send an Accept header so if present the format request param should take priority, not the other way round as the spec currently says. --- src/http-gateways/path-gateway.md | 2 +- src/ipips/ipip-0523.md | 68 +++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/ipips/ipip-0523.md diff --git a/src/http-gateways/path-gateway.md b/src/http-gateways/path-gateway.md index c207ae6d..8f9e12cb 100644 --- a/src/http-gateways/path-gateway.md +++ b/src/http-gateways/path-gateway.md @@ -256,7 +256,7 @@ These are the equivalents: - `format=ipns-record` → `Accept: application/vnd.ipfs.ipns-record` When both `Accept` HTTP header and `format` query parameter are present, -`Accept` SHOULD take precedence. +`format` SHOULD take precedence. :::note diff --git a/src/ipips/ipip-0523.md b/src/ipips/ipip-0523.md new file mode 100644 index 00000000..ce731e3a --- /dev/null +++ b/src/ipips/ipip-0523.md @@ -0,0 +1,68 @@ +--- +title: "IPIP-0523: Prefer format request 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 +relatedIssues: + - https://github.com/ipfs/specs/issues/521 +order: 523 +tags: ['ipips'] +--- + +## Summary + +Prefer the `format` request param over the Accept header + +## Motivation + +The [Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept) +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) +request 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 in a browser. + +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` request query +parameter, since they will always send an `Accept` header which would then cause +the `format` request query parameter to be ignored. + +## Detailed design + +The priority of `format` vs `Accept` should be reversed, so as to always prefer +`format` over `Accept` if it is present. + +## Design rationale + +Browsers will always send an `Accept` header that contains specific values so it +cannot be allowed to take priority over the `format` request query parameter. + +### User benefit + +Users will be able to use the `format` request query parameter to control the +response type of requests made from browser address bars. + +### Compatibility + +This is a breaking change. + +## Test fixtures + +Implementers can either write own test that prefers the format query param over +any present Accept 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/). From 8330f4045e4b092d530180d048ba6f0e0a43e370 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Mon, 1 Dec 2025 21:31:37 +0100 Subject: [PATCH 2/3] fix(IPIP-0523): expand rationale and update specs - clarify format is URL query param, Accept is HTTP header - expand Compatibility with HTTP caching rationale - add Security and Alternatives sections - update precedence rule in both path-gateway and trustless-gateway --- src/http-gateways/trustless-gateway.md | 8 +- src/ipips/ipip-0523.md | 108 ++++++++++++++++++++----- 2 files changed, 89 insertions(+), 27 deletions(-) diff --git a/src/http-gateways/trustless-gateway.md b/src/http-gateways/trustless-gateway.md index e892d915..2b76e157 100644 --- a/src/http-gateways/trustless-gateway.md +++ b/src/http-gateways/trustless-gateway.md @@ -128,17 +128,15 @@ Same as [`format`](https://specs.ipfs.tech/http-gateways/path-gateway/#format-re - `format=car` → `application/vnd.ipld.car` - `format=ipns-record` → `application/vnd.ipfs.ipns-record` +When both `Accept` HTTP header and `format` query parameter are present, +`format` SHOULD take precedence. + :::note A Client SHOULD include the `format` query parameter in the request URL, in addition to the `Accept` header. This provides the best interoperability and ensures consistent HTTP cache behavior across various gateway implementations. -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`. Wildcards (e.g., `*/*`, `application/*`) are not specific and do not -take precedence (as specified in :cite[path-gateway]). - ::: ### :dfn[`dag-scope`] (request query parameter) diff --git a/src/ipips/ipip-0523.md b/src/ipips/ipip-0523.md index ce731e3a..5092df9d 100644 --- a/src/ipips/ipip-0523.md +++ b/src/ipips/ipip-0523.md @@ -1,5 +1,5 @@ --- -title: "IPIP-0523: Prefer format request param over Accept header" +title: "IPIP-0523: Prefer format param over Accept header" date: 2025-11-26 ipip: proposal editors: @@ -7,8 +7,13 @@ editors: github: achingbrain url: https://achingbrain.net affiliation: - name: Shipyard - url: https://ipshipyard.com + 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 @@ -17,51 +22,110 @@ tags: ['ipips'] ## Summary -Prefer the `format` request param over the Accept header +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) -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 [`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) -request query parameter can also be sent to an IPFS HTTP Gateway to provide the +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 in a browser. +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` request query -parameter, since they will always send an `Accept` header which would then cause -the `format` request query parameter to be ignored. +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 `format` vs `Accept` should be reversed, so as to always prefer -`format` over `Accept` if it is present. +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` header that contains specific values so it -cannot be allowed to take priority over the `format` request query parameter. +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` request query parameter to control the +Users will be able to use the `format` URL query parameter to control the response type of requests made from browser address bars. ### Compatibility -This is a breaking change. +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 +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 query param over -any present Accept 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). +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 From 1c8d369c3b64292f1f243a4cd56348e8452542e6 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Mon, 1 Dec 2025 22:54:13 +0100 Subject: [PATCH 3/3] fix(trustless-gateway): URL query param priority for CAR options update car-version, car-order, car-dups to match IPIP-0523: URL query parameter SHOULD take precedence over Accept header --- src/http-gateways/trustless-gateway.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/http-gateways/trustless-gateway.md b/src/http-gateways/trustless-gateway.md index 2b76e157..a8bd5a0f 100644 --- a/src/http-gateways/trustless-gateway.md +++ b/src/http-gateways/trustless-gateway.md @@ -237,7 +237,7 @@ Optional, only used on CAR requests. Serves same purpose as [CAR `version` content type parameter](#car-version-content-type-parameter). -In case both are present in the request, the value from the [`Accept`](#accept-request-header) HTTP Header has priority and a matching [`Content-Location`](#content-location-response-header) SHOULD be returned with the response. +In case both are present in the request, the URL query parameter SHOULD take precedence and a matching [`Content-Location`](#content-location-response-header) SHOULD be returned with the response. ### :dfn[`car-order`] (request query parameter) @@ -245,7 +245,7 @@ Optional, only used on CAR requests. Serves same purpose as [CAR `order` content type parameter](#car-order-content-type-parameter). -In case both are present in the request, the value from the [`Accept`](#accept-request-header) HTTP Header has priority and a matching [`Content-Location`](#content-location-response-header) SHOULD be returned with the response. +In case both are present in the request, the URL query parameter SHOULD take precedence and a matching [`Content-Location`](#content-location-response-header) SHOULD be returned with the response. ### :dfn[`car-dups`] (request query parameter) @@ -253,7 +253,7 @@ Optional, only used on CAR requests. Serves same purpose as [CAR `dups` content type parameter](#car-dups-content-type-parameter). -In case both are present in the request, the value from the [`Accept`](#accept-request-header) HTTP Header has priority and a matching [`Content-Location`](#content-location-response-header) SHOULD be returned with the response. +In case both are present in the request, the URL query parameter SHOULD take precedence and a matching [`Content-Location`](#content-location-response-header) SHOULD be returned with the response. # HTTP Response