-
Notifications
You must be signed in to change notification settings - Fork 231
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Propose HTTP APIs for delegated naming system that enables offloading of naming system to other processes or servers. Relates to: - #377 Fixes #343
- Loading branch information
Showing
3 changed files
with
274 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
--- | ||
title: "IPIP-379: 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 | ||
order: 379 | ||
tags: ['ipips'] | ||
--- | ||
|
||
- Start Date: 2023-02-13 | ||
- Related Issues: | ||
|
||
## Summary | ||
|
||
This IPIP specifies a set of HTTP APIs to offload naming system onto another process or server. | ||
|
||
## Motivation | ||
|
||
Expanding on the motivations of :cite[ipip-0337], the work here concentrates on delegation of _naming system_ over HTTP APIs. 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. | ||
|
||
## HTTP API Specification | ||
|
||
See :cite[http-ipns-routing] 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: | ||
- Use of HTTP semantics for publication and resolution of naming records. | ||
- Preference for human-readable request and response encoding, such as JSON format | ||
- Optional backward compatibility support for the existing ProtocolBuffer format using `Content-Type: application/vnd.ipfs.ipns-record` | ||
- Use of extra headers in `OPTIONS` response to communicate the supported capabilities and limitations, namely: | ||
- `X-Ipns-Allow-Max-Size` -- to signal maximum supported IPNS record size | ||
- `X-Ipns-Allow-Protobuf` -- to signal whether the server supports ProtocolBuffer formatted records. | ||
- Streaming interaction is not supported. | ||
|
||
### User benefit | ||
|
||
The ability of offload naming onto another process or server via an idiomatic and simple HTTP API opens up an opportunity to not only reduce the burden of naming system management, but also introduce alternative naming systems across other routing systems, namely IPNI. | ||
|
||
### Compatibility | ||
|
||
#### Backwards Compatibility | ||
|
||
##### Serialization Format | ||
|
||
:cite[ipns-record] use ProtocolBuffer serialisation format. | ||
This format is widely in use in IPNS over PubSub and DHT routing systems. | ||
One of the motivations of this document is to introduce simple to use HTTP APIs and ultimately reduce barrier for interaction across alternative 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. | ||
|
||
The specification here maintains backwards compatibility in terms of record serialisation, with preference for human-readable formats such as JSON. | ||
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`. | ||
|
||
##### Reframe | ||
|
||
See "Backwards Compatibility" section of :cite[ipip-0337]. | ||
|
||
#### Forwards Compatibility | ||
|
||
See "Forwards Compatibility" section of :cite[ipip-0337]. | ||
|
||
### Security | ||
|
||
All interaction over the APIs should use TLS to protect against third-party observation and tampering. | ||
Additionally, the IPNS records are signed by the publisher's identity and contain sequence number to avoid replay attacks. | ||
|
||
To avoid Denial of Service attack, maximum IPNS record size of `10 KiB` applies. | ||
Implements are permitted to set a lower limit. If lower than the default maximum, the limit should be discoverable via `OPTIONS` request with header key `X-Ipns-Allow-Max-Size` with value specified as the number of bytes. | ||
|
||
Similarly, a client may check if a server supports ProtocolBuffer formatted records by checking the `X-Ipns-Allow-Protobuf` header key in response to `OPTIONS` request. If present the header value must be either `true` or `false` the absence of the header indicates that ProtocolBuffer formatted records are not supported. | ||
|
||
Privacy in delegated IPNS is out of scope for this work. | ||
- The usual JSON parsing rules apply. To prevent potential Denial of Service (DoS) attack, clients should ignore responses larger than 100 providers and introduce a byte size limit that is applicable to their use case. | ||
|
||
### Alternatives | ||
|
||
See: | ||
- [Libp2p-based IPNS](https://github.com/ipfs/go-ipns). | ||
- Reframe; find out more on "Design Rationale" section of :cite[ipip-0337]. | ||
|
||
### Copyright | ||
|
||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
--- | ||
title: Delegated IPNS HTTP API | ||
description: > | ||
Delegated IPNS is a mechanism for IPFS implementations to offload naming system to another process | ||
or server. This includes naming resolution as well as publication of new naming records. This | ||
document describes an HTTP API through which such functionality is facilitated. | ||
date: 2023-03-22 | ||
maturity: wip | ||
editors: | ||
- name: Masih H. Derkani | ||
github: masih | ||
order: 0 | ||
tags: ['routing'] | ||
--- | ||
|
||
Delegated IPNS is a mechanism for IPFS implementations to offload naming system to another process | ||
or server. This includes naming resolution as well as publication of new naming records. This | ||
document describes an HTTP API through which such functionality is facilitated. | ||
|
||
## API Specification | ||
|
||
The Delegated IPNS HTTP API uses the `application/json` content type by default. | ||
|
||
As such, human-readable encodings of types are preferred. This spec may be updated in the future | ||
with a compact `application/cbor` encoding, in which case compact encodings of the various types | ||
would be used. | ||
|
||
## Common Data Types | ||
|
||
### IPNS Record | ||
|
||
The following snippet outlines the JSON schema of IPNS records: | ||
|
||
```json | ||
{ | ||
"Signature": "<signature>", | ||
"Payload": { | ||
"Value": "<value>", | ||
"Sequence": 0, | ||
"Validity": { | ||
"EOL": { | ||
"Timestamp": 0, | ||
"AdvisoryTTL": 0 | ||
} | ||
}, | ||
"PublicKey": "<optional-public-key>", | ||
"ExtendedData": {} | ||
} | ||
} | ||
``` | ||
|
||
Where: | ||
|
||
- `Signature` is the multibase-encoded signature of the sha256 hash of the `Payload` field, signed | ||
using the private key that corresponds to the `PublicKey` in the `Payload` if present. And | ||
Otherwise, the private key associcated to the IPNS record key. Signing details for specific key | ||
types should | ||
follow [libp2p/peerid specs](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#key-types), | ||
unless stated otherwise. | ||
- `Payload` is the content of the IPNS record as specified | ||
by :cite[ipns-record] specification: | ||
- `Value` is the string representation of the IPNS path, | ||
e.g. `ipns/{ipns-key}`, `/ipns/example.com`, `/ipfs/baf...`, etc. | ||
- `Sequence` represents the current version of the record starting from `0`. | ||
- `Validity` captures the mechanism by which the record is validated. Each validity type reserves a | ||
field key under this object. | ||
- `EOL` donates that the validity type is EOL, containing: | ||
- `Timestamp` represents the time in the future at which the record expires with nanoseconds | ||
precision represented as an ASCII string that follows notation | ||
from :cite[rfc3339]. | ||
- `AdvisoryTTL` represents an optional field that hints at how long the record should be | ||
cached. | ||
- `PublicKey` represents the optional public key used to sign the record. This field is only | ||
required if it cannot be extracted from the IPNS name, e.g. in the case of legacy RSA keys. | ||
- `ExtendedData` represents the extensible data as arbitrary JSON object. | ||
|
||
## Versioning | ||
|
||
The path predix `/v1` donates the version number of the HTTP API. Backwards-incompatible change must | ||
increment the version number. | ||
|
||
## API | ||
|
||
### `GET /naming/v1/records/{ipns-name}` | ||
|
||
**Path Parameters** | ||
|
||
- `ipns-name` the IPNS name to resolve. | ||
|
||
**Response Status Codes** | ||
|
||
- `200` (OK): indicates that the response body containing the IPNS record that corresponds to the | ||
IPNS name. | ||
- `404` (Not Found): indicates that no matching records are found. | ||
- `400` (Bad Request): indicates that the given IPNS name is not valid. | ||
- `429` (Too Many Requests): indicates that the caller is issuing requests too many request and may | ||
retry after the time specified | ||
at [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) response | ||
header has elapsed. | ||
- `501` (Not Implemented): indicates that the server does not support resolution of IPNS records | ||
|
||
**Response Body** | ||
|
||
The response body contains the [IPNS record](#ipns-record). | ||
|
||
```json | ||
{ | ||
"Signature": "<signature>", | ||
"Payload": { | ||
"Value": "<value>", | ||
"Sequence": 0, | ||
"Validity": { | ||
"EOL": { | ||
"Timestamp": 0, | ||
"AdvisoryTTL": 0 | ||
} | ||
}, | ||
"PublicKey": "<optional-public-key>", | ||
"ExtendedData": {} | ||
} | ||
} | ||
``` | ||
|
||
### `PUT /naming/v1/records/{ipns-name}` | ||
|
||
**Path Parameters** | ||
|
||
- `ipns-name` the IPNS name to publish. The name must match `Value` in request body. | ||
|
||
**Request Body** | ||
|
||
```json | ||
{ | ||
"Signature": "<signature>", | ||
"Payload": { | ||
"Value": "<value>", | ||
"Sequence": 0, | ||
"Validity": { | ||
"EOL": { | ||
"Timestamp": 0, | ||
"AdvisoryTTL": 0 | ||
} | ||
}, | ||
"PublicKey": "<optional-public-key>", | ||
"ExtendedData": {} | ||
} | ||
} | ||
``` | ||
|
||
**Response Status Codes** | ||
|
||
- `200` (OK): indicates that the response body containing the IPNS record that corresponds to the | ||
IPNS name. | ||
- `404` (Not Found): indicates that no matching records are found. | ||
- `400` (Bad Request): indicates that the given IPNS record is not valid. | ||
- `429` (Too Many Requests): indicates that the caller is issuing requests too many request and may | ||
retry after the time specified | ||
at [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) response | ||
header has elapsed. | ||
- `501` (Not Implemented): indicates that the server does not support publication of IPNS records | ||
|
||
## CORS and Web Browsers | ||
|
||
Browser interoperability requires implementations to support | ||
[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). | ||
|
||
JavaScript client running on a third-party Origin must be able to send HTTP request to the endpoints | ||
defined in this specification, and read the received values. This means HTTP server implementing | ||
this API must: | ||
|
||
1. support [CORS preflight requests](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request) sent as HTTP OPTIONS, and | ||
2. always respond with headers that remove CORS limits, allowing every site to query the API for results: | ||
|
||
```plaintext | ||
Access-Control-Allow-Origin: * | ||
Access-Control-Allow-Methods: GET, PUT, OPTIONS | ||
``` |