Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 41 additions & 10 deletions src/http-gateways/path-gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: >
The comprehensive low-level HTTP Gateway enables the integration of IPFS
resources into the HTTP stack through /ipfs and /ipns namespaces, supporting
both deserialized and verifiable response types.
date: 2026-03-05
date: 2026-06-15
maturity: reliable
editors:
- name: Marcin Rataj
Expand Down Expand Up @@ -496,17 +496,48 @@ in caches.
Returned directive depends on requested content path and format:

- `Cache-Control: public, max-age=29030400, immutable` MUST be returned for
every immutable resource under `/ipfs/` namespace.
every immutable resource under the `/ipfs/` namespace.
- Generated `/ipfs/` responses, such as UnixFS directory listings, are not
byte-for-byte stable: their markup can change between implementations and
versions, so they MUST NOT be marked `immutable`. Give them an expiration
that lets caches pick up regenerated markup. The underlying data is
content-addressed and never expires, so a stale response can only show
outdated markup, never invalid data, and a fixed stale window is safe. A
floor of one week works well:
`public, max-age=604800, stale-while-revalidate=2678400`. This fixed window
applies only under the immutable `/ipfs/` namespace. The same listing
reached through `/ipns/` is mutable and follows the rules below.

- `Cache-Control: public, max-age=<ttl>` SHOULD be returned for mutable
resources under `/ipns/{id-with-ttl}/` namespace; `max-age=<ttl>` SHOULD
indicate remaining TTL of the mutable pointer such as :cite[ipns-record] or DNSLink
TXT record.
- Implementations MAY place an upper bound on any TTL received, as
noted in Section 8 of :cite[rfc2181].
- If TTL value is unknown, implementations SHOULD not send a `Cache-Control`
- No matter if TTL value is known or not, implementations SHOULD always
send a [`Last-Modified`](#last-modified-response-header) header with the timestamp of the record resolution.
resources under the `/ipns/{id-with-ttl}/` namespace, where `<ttl>` is the
remaining TTL of the mutable pointer: the :cite[ipns-record] `TTL` field or
the DNSLink TXT record TTL.
- Implementations MAY place an upper bound on any TTL received, as noted in
Section 8 of :cite[rfc2181].
- A `stale-while-revalidate` or `stale-if-error` window MAY be added to
improve CDN and offline behavior, but it MUST respect the pointer's
expiration. An :cite[ipns-record] with `ValidityType=0` is cryptographically
valid only until its `Validity` (EOL) timestamp, and a validating client
rejects it once that timestamp passes. Cap `max-age` to the remaining
validity, and size the stale window so that `max-age` plus the stale window
still ends before the EOL; a fixed stale window is unsafe because it can
push reuse past the EOL. Return `Cache-Control: no-store` for a response
backed by an already-expired record. This bound is mandatory for the raw
record response (`format=ipns-record`), whose body is the signed record
itself. A DNSLink pointer carries no signature EOL and MAY use a bounded
best-effort stale window.
- A generated response reached through `/ipns/`, such as a directory listing,
is mutable even though its body is regenerated markup. Apply the `/ipns/`
`max-age` and stale-window rules above, not the fixed window for generated
`/ipfs/` responses: the pointer it renders can move and, for an
:cite[ipns-record], expire, so the response MUST NOT be cached past the
record's EOL.
- If the TTL is unknown, implementations MAY send a best-effort
`Cache-Control` telling caches and CDNs how long a stale response is
acceptable.
- Whether or not the TTL is known, implementations SHOULD always send a
[`Last-Modified`](#last-modified-response-header) header with the timestamp
of the record resolution.

### `Last-Modified` (response header)

Expand Down
10 changes: 6 additions & 4 deletions src/routing/http-routing-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: >
Delegated routing is a mechanism for IPFS implementations to use for offloading
content routing, peer routing and naming to another process/server. This specification describes
an HTTP API for delegated routing of content, peers, and IPNS.
date: 2025-12-17
date: 2026-06-15
maturity: reliable
editors:
- name: Marcin Rataj
Expand Down Expand Up @@ -232,9 +232,11 @@ Each object in the `Peers` list is a record conforming to the [Peer Schema](#pee
#### Response Headers

- `Etag`: a globally unique opaque string used for HTTP caching. MUST be derived from the protobuf record returned in the body.
- `Cache-Control: public, max-age={ttl}, public, stale-while-revalidate={sig-ttl}, stale-if-error={sig-ttl}`: meaningful cache TTL returned with :ref[IPNS Record]
- The `max-age` value in seconds SHOULD match duration from `IpnsEntry.data[TTL]`, if present and bigger than `0`. Otherwise, implementation SHOULD default to `max-age=60`.
- Implementations SHOULD include `sig-ttl`, set to the remaining number of seconds the returned IPNS Record is valid.
- `Cache-Control: public, max-age={ttl}, stale-while-revalidate={stale}, stale-if-error={stale}`: cache lifetime for the returned :ref[IPNS Record].
- An IPNS Record with `ValidityType=0` is valid only until its EOL, the `Validity` timestamp. A cache that reuses the record past the EOL serves a record that fails validation, so the entire cache lifetime MUST stay within the remaining validity.
- `{ttl}` (the `max-age`) SHOULD match `IpnsEntry.data[TTL]` in seconds, or default to `60` when `TTL` is absent or `0`. Either way, cap it to the remaining validity.
- `{stale}` SHOULD be the remaining validity minus `max-age`, so `max-age` plus the stale window ends at the EOL and never crosses it.
- Return `Cache-Control: no-store` instead when the record is already expired, or when its `ValidityType` is unrecognized and the EOL is therefore unknown.
- `Expires:`: an HTTP-date timestamp ([RFC9110, Section 5.6.7](https://www.rfc-editor.org/rfc/rfc9110#section-5.6.7)) when the validity of IPNS Record expires (if `ValidityType=0`, when signature expires)
- `Last-Modified`: an HTTP-date timestamp of when cacheable resolution occurred: allows HTTP proxies and CDNs to support inexpensive update checks via `If-Modified-Since`
- `Vary: Accept`: allows intermediate caches to play nicely with the different possible content types.
Expand Down
Loading