diff --git a/src/ipips/ipip-0337.md b/src/ipips/ipip-0337.md index 4438ef74c..d7ba81d25 100644 --- a/src/ipips/ipip-0337.md +++ b/src/ipips/ipip-0337.md @@ -70,7 +70,7 @@ To understand the design rationale, it is important to consider the concrete Ref So this API proposal makes the following changes: - The Delegated Content Routing API is defined using HTTP semantics, and can be implemented without introducing Reframe concepts nor IPLD -- There is a clear distinction between the RPC protocol (HTTP) and the API (Deleged Content Routing) +- There is a clear distinction between the [Kubo RPC](https://docs.ipfs.tech/reference/kubo/rpc/) and the vendor-agnostic Routing V1 HTTP API (introduced in :cite[ipip-0377]). - "Method names" and cache-relevant parameters are pushed into the URL path - Streaming support is removed, and default response size limits are added. - We will add streaming support in a subsequent IPIP, but we are trying to minimize the scope of this IPIP to what is immediately useful @@ -80,7 +80,7 @@ So this API proposal makes the following changes: - Multiaddrs use the [human-readable format](https://github.com/multiformats/multiaddr#specification) that is used in existing tools and Kubo CLI commands such as `ipfs id` or `ipfs swarm peers` - Byte array values, such as signatures, are multibase-encoded strings (with an `m` prefix indicating Base64) - The "Identify" method and "message groups" are not included -- The "GetIPNS" and "PutIPNS" methods are not included +- The "GetIPNS" and "PutIPNS" methods are not included. Instead, a separate Delegated IPNS HTTP API aims to firstly facilitate naming system delegation, and secondly, pave the way for future iterations of IPNS with less interdependency with content routing. For more information, see Delegated IPNS HTTP API (:cite[ipip-0379]). ### User benefit diff --git a/src/ipips/ipip-0379.md b/src/ipips/ipip-0379.md new file mode 100644 index 000000000..6cc550f31 --- /dev/null +++ b/src/ipips/ipip-0379.md @@ -0,0 +1,89 @@ +--- +title: "IPIP-0379: Delegated IPNS HTTP API" +date: 2023-02-13 +ipip: proposal +editors: + - name: Masih H. Derkani + github: masih + - name: Marcin Rataj + github: lidel + url: https://lidel.org/ +relatedIssues: + - https://github.com/ipfs/specs/issues/343 + - https://github.com/ipfs/specs/pull/337 + - https://github.com/ipfs/specs/pull/377 +xref: + - ipns-record +order: 379 +tags: ['ipips'] +--- + +## Summary + +This IPIP specifies `/routing/v1/ipns` HTTP API to offload naming system onto another process or server. + +## Motivation + +One of the motivations of this document is to introduce simple to use HTTP APIs and ultimately reduce barrier for interaction across alternative systems. + +Expanding on the motivations of :cite[ipip-0337], the work here concentrates on delegation of IPNS over HTTP API. Naming is part of the core IPFS DHT functionality. +The performance of naming system over the IPFS DHT can suffer from long delays due to churn of records and quorum requirements. + +## Detailed design + +Add `/routing/v1/ipns` to the existing :cite[http-routing-v1] specification. + +## Design rationale + +The rationale for delegated IPNS over HTTP APIs closely follows the reasoning listed in :cite[ipip-0337]. + +The document proposes the following: +- HTTP `GET` and `PUT` semantics for publication and resolution of IPNS records. +- Use of existing :ref[IPNS Record] serialization format as HTTP `Content-Type` [`application/vnd.ipfs.ipns-record`](https://www.iana.org/assignments/media-types/application/vnd.ipfs.ipns-record). + +### User benefit + +The ability to offload naming to another process or server using a simple HTTP +API brings several benefits: + +- It reduces the resource drain on light clients such as JavaScript running on + a web page, mobile devices, IoT devices, and gateway HTTP services. +- It enables scaling of IPNS resolution separately from retrieval and + deserialization/verification services. +- Expands the utility of IPNS beyond IPFS nodes, contributes to its broader + adoption and impact by reducing integration costs. + +### Compatibility + +See the "Compatibility" section of :cite[ipip-0337]. + +#### Serialization Format + +Standard IPNS record serialization format is used, making it fully compatible with the existing IPNS ecosystem. + +:cite[ipns-record] uses [`application/vnd.ipfs.ipns-record`](https://www.iana.org/assignments/media-types/application/vnd.ipfs.ipns-record) protobuf serialization format. +This format is widely in use in IPNS over PubSub and DHT routing systems. +Further, interoperability across the existing and HTTP APIs is also desirable in order to reduce the barrier for adoption of the delegated HTTP APIs. + +To maximize interoperability with existing ecosystem, the canonical IPNS record serialization format :cite[ipns-record] (`0x0300`) can be requested with content type `application/vnd.ipfs.ipns-record`. + +### Security + +All interaction over the APIs should use TLS to protect against third-party observation and tampering. +Additionally, the IPNS records must be validated according to the rules stated in :cite[ipns-record] before further processing. + +To avoid Denial of Service attack, maximum IPNS record size defined in :cite[ipns-record] applies. + +Privacy in delegated IPNS is out of scope for this IPIP. + +### Alternatives + +See: +- IPNS over (libp2p over HTTP). While it may be possible in the future, it has more narrow utility and way bigger implementation complexity than libp2p-agnostic HTTP API with protobuf GET/PUT. +- Reframe; it was deprecated and now removed. Historical reasons can be found in :cite[ipip-0337]. +- JSON IPNS Record representation was descoped due to open question how signing should work and unclear use case ([discussion](https://github.com/ipfs/specs/pull/379#discussion_r1107898543)). +- API-specific max record size was descoped, as it would introduce interop problems harmful to the IPNS ecosystem. + +### Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/src/ipns/ipns-record.md b/src/ipns/ipns-record.md index 6ac3eba49..a9132f9a9 100644 --- a/src/ipns/ipns-record.md +++ b/src/ipns/ipns-record.md @@ -159,6 +159,8 @@ IPNS records are stored locally, as well as spread across the network, in order For storing this structured data at rest and on the wire, we use `IpnsEntry` encoded as [protobuf](https://github.com/google/protobuf), which is a language-neutral, platform neutral extensible mechanism for serializing structured data. The extensible part of IPNS Record is placed in `IpnsEntry.data` field, which itself is encoded using a strict and deterministic subset of CBOR named [DAG-CBOR](https://ipld.io/specs/codecs/dag-cbor/spec/). +This canonical serialization format uses the [`application/vnd.ipfs.ipns-record`](https://www.iana.org/assignments/media-types/application/vnd.ipfs.ipns-record) content type. + ```protobuf message IpnsEntry { enum ValidityType { @@ -196,10 +198,14 @@ message IpnsEntry { } ``` -Notes: +:::issue + +For legacy reasons, some values must be stored in both `IpnsEntry` protobuf **and** `IpnsEntry.data` CBOR. +This should not be ignored, as it impacts interoperability with old software. + +Opt-in lean IPNS Records are discussed in [ipfs/specs#376](https://github.com/ipfs/specs/issues/376). -- For legacy reasons, some values must be stored in both `IpnsEntry` protobuf and `IpnsEntry.data` CBOR. - This should not be ignored, as it impacts interoperability with old software. +::: ### Record Size Limit diff --git a/src/routing/http-routing-v1.md b/src/routing/http-routing-v1.md index 3015d66b3..5e6e9e412 100644 --- a/src/routing/http-routing-v1.md +++ b/src/routing/http-routing-v1.md @@ -1,23 +1,27 @@ --- title: Routing V1 HTTP API description: > - Delegated content routing is a mechanism for IPFS implementations to use for - offloading content routing to another process. This specification describes + Delegated routing is a mechanism for IPFS implementations to use for offloading + content routing and naming to another process/server. This specification describes an HTTP API for delegated content routing. date: 2023-03-22 maturity: reliable editors: - name: Gus Eggert - github: guseggert + github: guseggert + - name: Masih H. Derkani + github: masih +xref: + - ipns-record order: 0 tags: ['routing'] --- -"Delegated content routing" is a mechanism for IPFS implementations to use for offloading content routing to another process/server. This specification describes an HTTP API for delegated content routing. +Delegated routing is a mechanism for IPFS implementations to use for offloading content routing and naming to another process/server. This specification describes an HTTP API for delegated content routing. ## API Specification -The Delegated Content Routing Routing HTTP API uses the `application/json` content type by default. +The Routing HTTP API uses the `application/json` content type by default. For :ref[IPNS Names], the verifiable [`application/vnd.ipfs.ipns-record`][application/vnd.ipfs.ipns-record] content type is used. As such, human-readable encodings of types are preferred. This specification may be updated in the future with a compact `application/cbor` encoding, in which case compact encodings of the various types would be used. @@ -63,27 +67,31 @@ Where: Specifications for some transfer protocols are provided in the "Transfer Protocols" section. -## API +## Content Providers API -### `GET /routing/v1/providers/{CID}` +### `GET /routing/v1/providers/{cid}` -#### Response codes +#### Path Parameters -- `200` (OK): the response body contains 0 or more records -- `404` (Not Found): must be returned if no matching records are found -- `422` (Unprocessable Entity): request does not conform to schema or semantic constraints +- `cid` is the [CID](https://github.com/multiformats/cid) to fetch provider records for. + +#### Response Status Codes + +- `200` (OK): the response body contains 0 or more records. +- `404` (Not Found): must be returned if no matching records are found. +- `422` (Unprocessable Entity): request does not conform to schema or semantic constraints. #### Response Body ```json { - "Providers": [ - { - "Protocol": "", - "Schema": "", - ... - } - ] + "Providers": [ + { + "Protocol": "", + "Schema": "", + ... + } + ] } ``` @@ -91,6 +99,45 @@ Response limit: 100 providers Each object in the `Providers` list is a *read provider record*. +## IPNS API + +### `GET /routing/v1/ipns/{name}` + +#### Path Parameters + +- `name` is the :ref[IPNS Name] to resolve, encoded as CIDv1. + +#### Response Status Codes + +- `200` (OK): the response body contains the :ref[IPNS Record] for the given :ref[IPNS Name]. +- `404` (Not Found): must be returned if no matching records are found. +- `406` (Not Acceptable): requested content type is missing or not supported. Error message returned in body should inform the user to retry with `Accept: application/vnd.ipfs.ipns-record`. + +#### 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: max-age={TTL}`: cache TTL returned with :ref[IPNS Record] that has `IpnsEntry.data[TTL] > 0`. When present, SHOULD match the TTL value from the record. When record was not found (HTTP 404) or has no TTL (value is `0`), implementation SHOULD default to `max-age=60`. + +#### Response Body + +The response body contains a :ref[IPNS Record] serialized using the verifiable [`application/vnd.ipfs.ipns-record`](https://www.iana.org/assignments/media-types/application/vnd.ipfs.ipns-record) protobuf format. + +### `PUT /routing/v1/ipns/{name}` + +#### Path Parameters + +- `name` is the :ref[IPNS Name] to publish, encoded as CIDv1. + +#### Request Body + +The content body must be a [`application/vnd.ipfs.ipns-record`][application/vnd.ipfs.ipns-record] serialized :ref[IPNS Record], with a valid signature matching the `name` path parameter. + +#### Response Status Codes + +- `200` (OK): the provided :ref[IPNS Record] was published. +- `400` (Bad Request): the provided :ref[IPNS Record] or :ref[IPNS Name] are not valid. +- `406` (Not Acceptable): submitted content type is not supported. Error message returned in body should inform the user to retry with `Content-Type: application/vnd.ipfs.ipns-record`. + ## Pagination This API does not support pagination, but optional pagination can be added in a backwards-compatible spec update. @@ -101,9 +148,9 @@ This API does not currently support streaming, however it can be added in the fu ## Error Codes -- `501` (Not Implemented): must be returned if a method/path is not supported -- `429` (Too Many Requests): may be returned along with optional [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header to indicate to the caller that it is issuing requests too quickly -- `400` (Bad Request): must be returned if an unknown path is requested +- `400` (Bad Request): must be returned if an unknown path is requested. +- `429` (Too Many Requests): may be returned along with optional [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header to indicate to the caller that it is issuing requests too quickly. +- `501` (Not Implemented): must be returned if a method/path is not supported. ## CORS and Web Browsers @@ -136,10 +183,10 @@ Specification: [ipfs/specs/BITSWAP.md](https://github.com/ipfs/specs/blob/main/B ```json { - "Protocol": "transport-bitswap", - "Schema": "bitswap", - "ID": "12D3K...", - "Addrs": ["/ip4/..."] + "Protocol": "transport-bitswap", + "Schema": "bitswap", + "ID": "12D3K...", + "Addrs": ["/ip4/..."] } ``` @@ -159,13 +206,13 @@ Specification: [ipfs/go-graphsync/blob/main/docs/architecture.md](https://github ```json { - "Protocol": "transport-graphsync-filecoinv1", - "Schema": "graphsync-filecoinv1", - "ID": "12D3K...", - "Addrs": ["/ip4/..."], - "PieceCID": "", - "VerifiedDeal": true, - "FastRetrieval": true + "Protocol": "transport-graphsync-filecoinv1", + "Schema": "graphsync-filecoinv1", + "ID": "12D3K...", + "Addrs": ["/ip4/..."], + "PieceCID": "", + "VerifiedDeal": true, + "FastRetrieval": true } ``` @@ -180,3 +227,4 @@ Specification: [ipfs/go-graphsync/blob/main/docs/architecture.md](https://github [multiaddr]: https://github.com/multiformats/multiaddr#specification [peer-id]: https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md [peer-id-representation]: https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#string-representation +[application/vnd.ipfs.ipns-record]: https://www.iana.org/assignments/media-types/application/vnd.ipfs.ipns-record