IPIP-0523: Prefer format param over Accept header

Related Issue
ipfs/specs/issues/521
History
Commit History
Feedback
GitHub ipfs/specs (inspect source, open issue)

1. Summary

Prefer the ?format= URL query parameter over the Accept: HTTP request header.

2. Motivation

The 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 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 and Trustless Gateway 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.

3. Detailed design

The priority of the format URL query parameter vs the Accept HTTP header is reversed in both [path-gateway] and [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.

4. 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.

4.1 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.

4.2 Compatibility

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 tests, which explicitly test the old precedence behavior. A minor version bump of gateway-conformance is required to update these tests.

4.3 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.

4.4 Alternatives

4.4.1 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

4.4.2 Return HTTP 400 on conflicting format preferences

Require gateways to return HTTP 400 when the Accept header and format parameter specify different formats, signaling client misconfiguration.

This was rejected as impractical:

  1. Reintroduces complexity: Detecting "conflicts" requires fully parsing Accept headers, handling wildcards and quality values - the very complexity this IPIP eliminates.

  2. Incompatible with real-world HTTP infrastructure: CDNs and reverse proxies (Nginx, Cloudflare, etc.) routinely strip, transform, or ignore Accept headers. When requests traverse multiple hops, each with different behaviors, the Accept header often doesn't reach the gateway intact. The URL is the only reliable cache key across the entire stack.

  3. Untestable in practice: Conformance tests expecting HTTP 400 would spuriously pass or fail depending on whether upstream infrastructure forwarded the Accept header. This creates a specification that cannot be reliably verified.

The chosen approach - format always takes precedence, no error on disagreement - is a pragmatic choice that minimizes implementation complexity and maximizes interoperability with real-world HTTP clients, CDNs, reverse proxies, and caches.

5. 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 test suite, which includes tests for this scenario since gateway-conformance/pull/252.

A. References

[path-gateway]
Path Gateway Specification. Henrique Dias; Marcin Rataj. 2026-03-05. URL: https://specs.ipfs.tech/http-gateways/path-gateway/
[rfc2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[trustless-gateway]
Trustless Gateway Specification. Henrique Dias; Marcin Rataj; Héctor Sanjuán; Adin Schmahmann. 2026-03-05. URL: https://specs.ipfs.tech/http-gateways/trustless-gateway/

B. Acknowledgments

We gratefully acknowledge the following individuals for their valuable contributions, ranging from minor suggestions to major insights, which have shaped and improved this specification.

Editors
Alex Potsides (Shipyard) GitHub
Marcin Rataj (Shipyard) GitHub
Special Thanks
Adin Schmahmann (Shipyard) GitHub