IPIP-0548: Sunset X-Ipfs-Path header

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

1. Summary

Replace X-Ipfs-Path header with Ipfs-Uri version that can correctly encode any special characters likely to be found in an IPFS Path.

2. Motivation

HTTP header values can only include characters from a limited set.

There is a gap in the existing gateway specification in that it does not say how characters from outside this set are to be treated.

Values already arrive broken: browser fetch() garbles raw UTF-8, and Go's net/http replaces CR and LF with spaces.

The spec is implemented and consumed widely so retrospectively adding encoding rules would be disruptive, and we would have to agree on an encoding format.

URIs already have a well-defined encoding format (percent encoding, defined in RFC 3986), so introduce an Ipfs-Uri header to be used in preference to X-Ipfs-Path which can handle any and all characters found in an IPFS path, and can be losslessly converted back into an IPFS Path if the client desires it.

3. Detailed design

The Ipfs-Uri header should be added which contains the IPFS/IPNS path as a URI (e.g. ipfs://... or ipns://...) with any special characters percent-encoded as per RFC 3986.

The URI schemes are defined by [ipfs-uri] and [ipns-uri]; the Ipfs-Uri section of [path-gateway] defines the exact serialization.

This IPIP also updates [unixfs]: names containing / join the restricted names list, and the path escaping section defines the HTTP gateway and URI behavior while leaving other contexts unspecified.

Ipfs-Uri deprecates X-Ipfs-Path, and clients SHOULD prefer Ipfs-Uri when both are present. The X-Ipfs-Path section says when the legacy header MUST be omitted to avoid issues with unsafe byte ranges.

4. Design rationale

Retroactively adding encoding rules to X-Ipfs-Path would be too disruptive to existing clients so adding a new header and deprecating the old one seems like the least worst way forward.

Path escaping was previously undefined across the stack: the UnixFS spec explicitly declared it out of scope, and nothing said how gateways decode request paths or how a content path becomes a header-safe string. This IPIP locks that behavior down: request path components are percent-decoded once (so %2F is a component separator), Ipfs-Uri is the canonical encoded form, and names containing / are formally not path-addressable.

4.1 User benefit

Ipfs-Uri correctly encodes otherwise illegal characters so users can determine the original IPFS Path of a resource without data corruption.

4.2 Compatibility

Since we are adding a new header this is a non-breaking change.

Existing deployments can keep returning both headers; new implementations return only Ipfs-Uri.

4.3 Security

Percent-encoding keeps raw control bytes such as CR and LF out of Ipfs-Uri values.

5. Test fixtures

A UnixFS directory under bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae (dir-with-tricky-filenames.car in ipip-0548-test-fixtures.zip), and the header returned for each file in it:

UnixFS file name Response header
plain.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/plain.txt
with space.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/with%20space.txt
100% sure.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/100%25%20sure.txt
a#b?c.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/a%23b%3Fc.txt
łódź.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/%C5%82%C3%B3d%C5%BA.txt
emoji🚀.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/emoji%F0%9F%9A%80.txt
αρχείο.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/%CE%B1%CF%81%CF%87%CE%B5%CE%AF%CE%BF.txt
файл.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/%D1%84%D0%B0%D0%B9%D0%BB.txt
קובץ.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/%D7%A7%D7%95%D7%91%D7%A5.txt
ملف.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/%D9%85%D9%84%D9%81.txt
नमस्ते.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/%E0%A4%A8%E0%A4%AE%E0%A4%B8%E0%A5%8D%E0%A4%A4%E0%A5%87.txt
ไฟล์.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/%E0%B9%84%E0%B8%9F%E0%B8%A5%E0%B9%8C.txt
ファイル.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.txt
你好.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/%E4%BD%A0%E5%A5%BD.txt
파일.txt Ipfs-Uri: ipfs://bafybeiflhd5aimv4xavauidbetge3v3uadbqfibu5lfo4b26yyieqvnvae/%ED%8C%8C%EC%9D%BC.txt

A second fixture, the preexisting dir-with-percent-encoded-filename.car directory under bafybeig675grnxcmshiuzdaz2xalm6ef4thxxds6o6ypakpghm5kghpc34, holds a name that already looks percent-encoded. The literal %2C is encoded again (%252C), never decoded into a comma, and + and = do not pass through raw:

UnixFS file name Response header
Portugal%2C+España=Peninsula Ibérica.txt Ipfs-Uri: ipfs://bafybeig675grnxcmshiuzdaz2xalm6ef4thxxds6o6ypakpghm5kghpc34/Portugal%252C%2BEspa%C3%B1a%3DPeninsula%20Ib%C3%A9rica.txt

A third fixture, dir-with-slash-in-filename.car under bafybeihuqitp4tzukehqfyaozl6zexd7szyzeywojuynfxopnn7dqjepv4, holds a real subdirectory a with b.txt inside, plus a sibling link literally named a/b.txt. Such a link is legal in dag-pb but not addressable by any content path: %2F decodes to a separator, so every spelling resolves to the nested file:

Request path Response header
/ipfs/{cid}/a/b.txt Ipfs-Uri: ipfs://bafybeihuqitp4tzukehqfyaozl6zexd7szyzeywojuynfxopnn7dqjepv4/a/b.txt
/ipfs/{cid}/a%2Fb.txt Ipfs-Uri: ipfs://bafybeihuqitp4tzukehqfyaozl6zexd7szyzeywojuynfxopnn7dqjepv4/a/b.txt

The gateway-conformance test suite uses these directories to test Ipfs-Uri and the legacy X-Ipfs-Path behavior.

A. References

[ipfs-uri]
IPFS URI (ipfs://). Marcin Rataj. 2026-08-03. URL: https://specs.ipfs.tech/ipfs-uri/
[ipns-uri]
IPNS URI (ipns://). Marcin Rataj. 2026-08-03. URL: https://specs.ipfs.tech/ipns-uri/
[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
[unixfs]
UnixFS. Hugo Valtier; Marcin Rataj. 2026-03-05. URL: https://specs.ipfs.tech/unixfs/

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