|
| 1 | +--- |
| 2 | +title: "IPIP-0524: Remove cross-codec conversion from HTTP Gateways" |
| 3 | +date: 2026-03-05 |
| 4 | +ipip: ratified |
| 5 | +editors: |
| 6 | + - name: Alex Potsides |
| 7 | + github: achingbrain |
| 8 | + url: https://achingbrain.net |
| 9 | + affiliation: |
| 10 | + name: Shipyard |
| 11 | + url: https://ipshipyard.com |
| 12 | + - name: Marcin Rataj |
| 13 | + github: lidel |
| 14 | + url: https://lidel.org |
| 15 | + affiliation: |
| 16 | + name: Shipyard |
| 17 | + url: https://ipshipyard.com |
| 18 | +relatedIssues: |
| 19 | + - https://github.com/ipfs/gateway-conformance/issues/200 |
| 20 | +order: 524 |
| 21 | +tags: ['ipips'] |
| 22 | +--- |
| 23 | + |
| 24 | +## Summary |
| 25 | + |
| 26 | +Make IPFS HTTP Gateway responses easier to reason about by not requiring IPLD |
| 27 | +Data Model translations |
| 28 | + |
| 29 | +## Motivation |
| 30 | + |
| 31 | +When sending an [Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept) |
| 32 | +header or [format](https://specs.ipfs.tech/http-gateways/path-gateway/#format-request-query-parameter) |
| 33 | +query parameter to specify the response format of a request, the IPFS HTTP |
| 34 | +Gateway specs [allow translation](https://specs.ipfs.tech/http-gateways/path-gateway/#accept-request-header) |
| 35 | +of the requested content into the [IPLD Data Model](https://ipld.io/docs/data-model/). |
| 36 | + |
| 37 | +This adds significant complexity to HTTP Gateway implementations, since they |
| 38 | +need to be able to translate between arbitrary data types and handle all the |
| 39 | +various failure states. |
| 40 | + |
| 41 | +The conversions are also lossy due to differences in supported data types across |
| 42 | +different formats so lack general-purpose utility and are ultimately something |
| 43 | +that could be done on an interested client if required. |
| 44 | + |
| 45 | +## Detailed design |
| 46 | + |
| 47 | +When the block's CID codec matches the requested response format, |
| 48 | +implementations MAY return the block as-is without parsing or validating it. |
| 49 | +This is effectively equivalent to requesting `?format=raw` but with a |
| 50 | +codec-specific `Content-Type` header. |
| 51 | + |
| 52 | +When the CID codec does not match the requested format, the gateway SHOULD |
| 53 | +return a [406 Not Acceptable](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/406) |
| 54 | +unless the server provides cross-codec conversion as an extra feature outside |
| 55 | +of this specification. |
| 56 | + |
| 57 | +For example, requesting a DAG-JSON block with the `application/cbor` format |
| 58 | +would result in a 406 response. |
| 59 | + |
| 60 | +Where a human-readable rendering of the data is desired, the `text/html` format |
| 61 | +can be requested. This would allow browsing DAG-PB data, for example. |
| 62 | + |
| 63 | +A [400](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/400) |
| 64 | +may be returned if the request was invalid (for example an unsupported format |
| 65 | +was requested). |
| 66 | + |
| 67 | +A [500](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/500) |
| 68 | +may be returned in other circumstances. |
| 69 | + |
| 70 | +## Design rationale |
| 71 | + |
| 72 | +Simplifying the HTTP Gateway spec to remove these format translations and the |
| 73 | +additional logic required makes it more straightforward to create new |
| 74 | +implementations, and makes the returned data more transparent and so easier to |
| 75 | +understand since the data is not modified to fit the output format. |
| 76 | + |
| 77 | +Clients that wish to translate between different data formats may request raw |
| 78 | +blocks and do the translation themselves. |
| 79 | + |
| 80 | +### User benefit |
| 81 | + |
| 82 | +For gateway operators and implementers, removing the requirement to perform |
| 83 | +codec conversions server-side significantly reduces implementation complexity. |
| 84 | + |
| 85 | +For end users and application developers, the change makes gateway behavior |
| 86 | +easier to reason about: a request either returns data deserialized according |
| 87 | +to the rules of the CID's original codec, or fails with 406. This moves |
| 88 | +conversion to userland, encouraging users to fetch raw blocks with |
| 89 | +`?format=raw` and convert client-side, putting the application in full control |
| 90 | +and producing deterministic results regardless of which gateway is used. |
| 91 | + |
| 92 | +This matters in practice because codec libraries do not behave identically. |
| 93 | +[Cross-library dag-cbor tests (2026)](https://hyphacoop.github.io/dasl-testing/?group=tests-by-file&tag=dag-cbor) |
| 94 | +show each implementation differs on edge cases like float handling, map key |
| 95 | +ordering, and encoding strictness. Relying on server-side conversion means |
| 96 | +the output depends on whichever library the gateway happens to use, which is |
| 97 | +not a foundation for robust software. |
| 98 | + |
| 99 | +### Compatibility |
| 100 | + |
| 101 | +Formally this is a breaking change: server-side IPLD Data Model translations |
| 102 | +between codecs are removed. |
| 103 | + |
| 104 | +In practice, nobody could build reliable software |
| 105 | +on top of conversion logic that behaved non-deterministically across gateways |
| 106 | +written in different languages. Clients that needed data in a different |
| 107 | +format often chose to fetch `?format=raw` and convert client-side already. |
| 108 | + |
| 109 | +This IPIP standardizes that robust real-world pattern and removes an |
| 110 | +unreliable niche feature that has seen limited use. |
| 111 | + |
| 112 | +#### Real-world `?format=` usage on `ipfs.io` and `dweb.link` |
| 113 | + |
| 114 | +A 24-hour sample of traffic on the `ipfs.io` and `dweb.link` public gateways |
| 115 | +(Feb 2026) shows that only 4.5% of all requests use the `?format=` query |
| 116 | +parameter, and the vast majority ask for `json`: |
| 117 | + |
| 118 | +| `?format=` value | % of requests with `format=` | |
| 119 | +|------------------|------------------------------| |
| 120 | +| `json` | 99.11% | |
| 121 | +| `raw` | 0.86% | |
| 122 | +| `dag-json` | 0.02% | |
| 123 | +| `car` | 0.01% | |
| 124 | +| other | <0.01% | |
| 125 | + |
| 126 | +Note: `ipfs.io` and `dweb.link` serve deserialized responses. Trustless |
| 127 | +verifiable requests (`?format=raw`, `?format=car`) are redirected to |
| 128 | +`trustless-gateway.link`, which is why those formats appear so rarely here. |
| 129 | + |
| 130 | +Looking at what those `?format=json` requests actually point at tells the |
| 131 | +real story. The CID codec of the requested blocks breaks down as follows: |
| 132 | + |
| 133 | +| CID codec of requested block | % of `?format=json` | |
| 134 | +|------------------------------|---------------------| |
| 135 | +| `dag-pb` (CIDv0 `Qm...`) | 60.0% | |
| 136 | +| `dag-pb` (CIDv1 `bafy...`) | 21.4% | |
| 137 | +| `raw` (`bafk...`) | 18.6% | |
| 138 | + |
| 139 | +100% of `?format=json` requests are for blocks with `dag-pb` or `raw` codec. |
| 140 | +None target the `json` codec (0x0200). In other words, these clients are |
| 141 | +reading regular JSON files stored as UnixFS, not asking the gateway to convert |
| 142 | +between IPLD codecs. The gateway serves them as plain HTTP file responses, |
| 143 | +which is covered by the UnixFS interop exception described later in this IPIP. |
| 144 | + |
| 145 | +The remaining formats (`dag-json` and `car`) together account for less than |
| 146 | +0.04% of `?format=` requests and do not depend on cross-codec conversion |
| 147 | +either, since they request data in the block's native codec. |
| 148 | + |
| 149 | +#### `json` and `dag-json` independence |
| 150 | + |
| 151 | +`application/json` and `application/vnd.ipld.dag-json` are now treated as |
| 152 | +independent formats, each matching only their respective CID codec (`json` |
| 153 | +0x0200 and `dag-json` 0x0129). The old behavior where `application/json` was |
| 154 | +an alias for `application/vnd.ipld.dag-json` (falling back to dag-json |
| 155 | +conversion) no longer applies. |
| 156 | + |
| 157 | +#### UnixFS interop exception for `Accept: application/json` |
| 158 | + |
| 159 | +Note: the codec match requirement and 406 behavior described above do not |
| 160 | +apply to deserialized UnixFS file responses. Users commonly store valid JSON |
| 161 | +as UnixFS files (with `dag-pb` or `raw` codec), and serving those files with |
| 162 | +`Accept: application/json` is regular HTTP content serving, not codec |
| 163 | +conversion. See the `application/json` entry in the |
| 164 | +[Accept request header](https://specs.ipfs.tech/http-gateways/path-gateway/#accept-request-header) |
| 165 | +section of the Path Gateway spec for normative requirements. |
| 166 | + |
| 167 | +#### Opt-in backward compatibility |
| 168 | + |
| 169 | +Implementations MAY offer an opt-in configuration flag to restore the old |
| 170 | +codec conversion behavior for backward compatibility. |
| 171 | + |
| 172 | +#### Implementation-defined behavior |
| 173 | + |
| 174 | +- The content of the 406 error response body (e.g. actionable hints). |
| 175 | +- Handling of `?format=json` / `Accept: application/json` on non-json-codec |
| 176 | + content (like `dag-pb` UnixFS files). |
| 177 | +- Whether to offer an opt-in flag for restoring codec conversion. |
| 178 | +- Validation of block data when the CID codec matches the requested format. |
| 179 | + |
| 180 | +### Security |
| 181 | + |
| 182 | +No security implications. This change restricts gateway behavior (returning |
| 183 | +406 instead of converting), which reduces attack surface. |
| 184 | + |
| 185 | +## Test fixtures |
| 186 | + |
| 187 | +Implementers can run the [gateway-conformance](https://github.com/ipfs/gateway-conformance/) |
| 188 | +test suite v0.10 or later. The following behaviors are verified by the test suite: |
| 189 | + |
| 190 | +- Requesting a block in a format that differs from its CID codec (e.g. |
| 191 | + `dag-pb` block with `?format=dag-json`) returns HTTP 406. |
| 192 | +- Requesting a block in its native codec returns HTTP 200. |
| 193 | +- `?format=raw` works for any codec. |
| 194 | +- HTML rendering (`Accept: text/html`) of DAG-JSON/DAG-CBOR blocks is not |
| 195 | + codec conversion and remains part of the spec. |
| 196 | + |
| 197 | +### Copyright |
| 198 | + |
| 199 | +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
0 commit comments