Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IPIP-379: Delegated IPNS HTTP API #379

Merged
merged 4 commits into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 2 additions & 2 deletions src/ipips/ipip-0337.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
89 changes: 89 additions & 0 deletions src/ipips/ipip-0379.md
Original file line number Diff line number Diff line change
@@ -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/).
112 changes: 80 additions & 32 deletions src/routing/http-routing-v1.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -63,34 +67,77 @@ 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": "<protocol_name>",
"Schema": "<schema>",
...
}
]
"Providers": [
{
"Protocol": "<protocol_name>",
"Schema": "<schema>",
...
}
]
}
```

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.
Expand All @@ -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

Expand Down Expand Up @@ -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/..."]
}
```

Expand All @@ -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": "<cid>",
"VerifiedDeal": true,
"FastRetrieval": true
"Protocol": "transport-graphsync-filecoinv1",
"Schema": "graphsync-filecoinv1",
"ID": "12D3K...",
"Addrs": ["/ip4/..."],
"PieceCID": "<cid>",
"VerifiedDeal": true,
"FastRetrieval": true
}
```

Expand All @@ -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