Skip to content

feat(gateway): IPIP-548 Ipfs-Uri response header - #1209

Open
lidel wants to merge 4 commits into
mainfrom
ipip-548-ipfs-uri
Open

feat(gateway): IPIP-548 Ipfs-Uri response header#1209
lidel wants to merge 4 commits into
mainfrom
ipip-548-ipfs-uri

Conversation

@lidel

@lidel lidel commented Aug 21, 2026

Copy link
Copy Markdown
Member

Problem

X-Ipfs-Path cannot carry every UnixFS file name: bytes outside visible ASCII are invalid in HTTP field values1, so a path like /ipfs/{cid}/łódź.txt reaches clients garbled or silently altered. ipfs/specs#548 deprecates the header in favor of Ipfs-Uri, a percent-encoded ipfs:// / ipns:// URI that survives any file name.

Fix

  • emit Ipfs-Uri per IPIP-548: Sunset x-ipfs-path header specs#548: canonical authority (base32 CIDv1, base36 IPNS name, A-label DNSLink), strict percent-encoding of every path segment, sent on deserialized, redirect, and error responses, exposed for CORS
  • stop sending X-Ipfs-Path by default; Config.DeprecatedXIpfsPath plus Headers.WithDeprecatedXIpfsPath restore it for legacy consumers, still omitted when the path has unsafe bytes
  • covered by feat: tests for IPIP-548 Ipfs-Uri header gateway-conformance#301; CI pins that branch until a release ships (TODO in the workflow)

Tests

All pass, Sharness can be ignored here, it pass in Kubo using conformance and boxo/gateway from this PR:

Footnotes

  1. RFC 9110, section 5.5: field values are limited to HTAB, SP, and visible ASCII.

@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.00000% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.28%. Comparing base (25b1db8) to head (6f8fbc6).

Files with missing lines Patch % Lines
gateway/handler.go 90.32% 3 Missing and 3 partials ⚠️

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1209      +/-   ##
==========================================
+ Coverage   64.18%   64.28%   +0.09%     
==========================================
  Files         269      269              
  Lines       27193    27258      +65     
==========================================
+ Hits        17455    17522      +67     
+ Misses       8024     8017       -7     
- Partials     1714     1719       +5     
Files with missing lines Coverage Δ
gateway/gateway.go 79.22% <ø> (ø)
gateway/headers.go 100.00% <100.00%> (ø)
gateway/handler.go 82.65% <90.32%> (+2.17%) ⬆️

... and 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Implement the Ipfs-Uri response header from ipfs/specs#548: a
canonical ipfs:// or ipns:// URI for the requested content path,
safe in an HTTP field value for any UnixFS file name.

- authority in canonical form: base32 CIDv1, base36 IPNS name
  keeping its multicodec, lowercase A-label DNSLink; header omitted
  when the root cannot be normalized
- every path segment percent-encoded over the RFC 3986 unreserved
  set with uppercase hex; "." and ".." emitted as %2E / %2E%2E
- sent on deserialized, redirect, and error responses up to 8192
  bytes, and exposed via default Access-Control-Expose-Headers
- X-Ipfs-Path no longer sent by default; restore via
  Config.DeprecatedXIpfsPath + Headers.WithDeprecatedXIpfsPath,
  still omitted for bytes invalid in a field value
- CI runs gateway-conformance from ipfs/gateway-conformance#301
  until a release with the IPIP-548 tests ships
@lidel
lidel force-pushed the ipip-548-ipfs-uri branch from fd861e7 to 37cbbdd Compare August 22, 2026 12:35
lidel added 2 commits August 24, 2026 01:20
Per IPIP-548 only dotted DNSLink names become an ipns:// authority:
example.local works, examplenodot never does.

Refs ipfs/helia-verified-fetch#376 (comment)
Use the conformance tests from ipfs/gateway-conformance#301 at its
latest commit, which adds the dot-less DNSLink Ipfs-Uri tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant