-
Notifications
You must be signed in to change notification settings - Fork 237
IPIP-293: Add /ipld Gateway Specs #293
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
base: main
Are you sure you want to change the base?
Changes from 6 commits
b9d46c4
2488113
8a07dcc
5cc59f2
3674381
8e59a2b
4c9e3ad
a471eb4
b7e48a3
c96abcd
0372363
5723b06
447118c
c447f90
b140bdd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,196 @@ | ||||||||||
| # IPLD Gateway Specification | ||||||||||
|
|
||||||||||
| **Authors**: | ||||||||||
|
|
||||||||||
| - Mauve Signweaver ([@RangerMauve](https://github.com/RangerMauve)) | ||||||||||
|
|
||||||||||
| ---- | ||||||||||
|
|
||||||||||
| **Abstract** | ||||||||||
|
|
||||||||||
| IPLD Gateway is an extension of [PATH_GATEWAY.md](./PATH_GATEWAY.md) that enables lower level interaction with IPLD data structures under a specific path. | ||||||||||
|
|
||||||||||
| This document describes the delta between [PATH_GATEWAY.md](./PATH_GATEWAY.md) and this gateway type. | ||||||||||
|
|
||||||||||
| Summary: | ||||||||||
|
|
||||||||||
| - Adds a new `/ipld/{cid}[/{segments}][?{params}]` subpath to the gateway | ||||||||||
| - Defines a specification for parsing out extra parameters for individual path segments. | ||||||||||
| - Describes how to map to and from `ipld://` URLs | ||||||||||
|
|
||||||||||
| ## HTTP API | ||||||||||
|
|
||||||||||
| ### `GET /ipld/{cid}[/{segments}][?{params}]` | ||||||||||
|
|
||||||||||
| Resolve IPLD paths to some data. | ||||||||||
|
|
||||||||||
| The path segments will be traversed with any parameters used to transform data along the way. | ||||||||||
|
|
||||||||||
| The `format` query string parameter, or the `Accept` request header can be used to control the format which will be used to return the data. | ||||||||||
|
|
||||||||||
| By default, data will be returned as `dag-json` | ||||||||||
RangerMauve marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
|
|
||||||||||
| <!-- | ||||||||||
| TODO: Cache control semantics? | ||||||||||
| TODO: Add more details on how the traversal works? | ||||||||||
| --> | ||||||||||
|
|
||||||||||
| ### `HEAD /ipld/{cid}[/{segments}][?{params}]` | ||||||||||
|
|
||||||||||
| Resolves IPLD paths, and yields the same status code and headers as `GET`. | ||||||||||
|
|
||||||||||
| ### `POST /ipld/` and `POST /ipld/localhost/` | ||||||||||
|
|
||||||||||
| Upload raw data to IPLD. | ||||||||||
| The `body` of the request shall be parsed according to the `Content-Type` as IPLD data via standard encodings. | ||||||||||
| `/localhost/` is used to support `POST ipld://localhost/` for uploading IPLD data to local nodes in web browsers that support it. | ||||||||||
|
|
||||||||||
| The response will contain an `ipld://{cid}/` URL pointing at your data. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spec should remove any ambiguity:
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is something I'd like to clarify with @fabricedesre since we had a bit of a disagreement. Right now the precendent within Kubo and Agregore's protocol handlers is that there will be a 201 response with a Fabrice was into having a 200 response and the URL inside the response body, which is something I was originally doing in Agregore, but switch when we started extending the writable gateway functionality in Kubo. Ideally we should settle on the best course of action here during Lisbon. 😅
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally, I'd like to use this to inform all the other protocol handlers too. |
||||||||||
|
|
||||||||||
| <!-- | ||||||||||
| TODO: Only allow `/localhost/`? Get rid of `/localhost` from the spec if light clients with protocol handlers don't matter/ | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have use cases where things other than
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've been using |
||||||||||
| --> | ||||||||||
|
|
||||||||||
| ### `PATCH /ipld/{cid}[/{segments}][?{params}]` | ||||||||||
|
|
||||||||||
| This endpoint enables you to apply a [patch set](https://ipld.io/specs/patch/) to existing IPLD data. | ||||||||||
RangerMauve marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
|
|
||||||||||
| <!-- | ||||||||||
| TODO: Talk about content encoding | ||||||||||
| TODO: Mention interaction with ADLs/Schemeas/Selectors | ||||||||||
| --> | ||||||||||
|
|
||||||||||
| The response will be an `ipld://` URL with your updated data. | ||||||||||
|
|
||||||||||
| Note that the CID in the response URL will contain the same `segments` as in the request URL. | ||||||||||
| e.g. if you patch data at `ipld://{cid1}/some/path/`, you will get back a URL that looks like `ipld://{updated cid}/some/path/` | ||||||||||
| This enables you to make complex changes to a subtree in a dataset and get back a new root CID to use in your application. | ||||||||||
|
|
||||||||||
| ## HTTP Request | ||||||||||
|
|
||||||||||
| ### Request Headers | ||||||||||
|
|
||||||||||
| #### `Accept` (request header) | ||||||||||
|
|
||||||||||
| For `/ipld/{cid}/*` paths, the `Accept` header is used to indicate the encoding that should be used to return the data. | ||||||||||
| This means that data initially encoded as `dag-json` will be transcoded to `dag-cbor` if the `application/vnd.ipld.dag-cbor` Accept header is used. | ||||||||||
|
|
||||||||||
| - `application/json`: Interpret in the same way as `application/vnd.ipld.dag-json`. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if data is a valid JSON (and not DAG-JSON) added to ipfs with @hacdias and I discussed this edge case and ended up with requirement to check codec from CID, and if it is
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting. Do you have text written up somewhere that I can copy paste here?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @RangerMauve we have some wording here, but it may not be definitive: specs/http-gateways/PATH_GATEWAY.md Lines 184 to 187 in 67fab21
|
||||||||||
| - `application/vnd.ipld.dag-json`: Return the block specified by the path encoded in `dag-json`. | ||||||||||
| - `application/vnd.ipld.dag-cbor`: Return the block specified by the path ecnoded in `dag-cbor`. | ||||||||||
|
|
||||||||||
| If no `Accept` header is present in the request, it will be assumed to be `application/vnd.ipld.dag-json`. | ||||||||||
|
|
||||||||||
| #### `Content-Type` (request header) | ||||||||||
|
|
||||||||||
| This header applies to `PUT/POST/PATCH` requests for `/ipld/*` paths on IPLD gateways which also support the [writable gateways spec](./WRITABLE_GATEWAY.md). | ||||||||||
| Including it will hint to the writable IPLD gateway which encoding to use to parse the request body into the IPLD Data Model. | ||||||||||
|
|
||||||||||
| - `application/json`: Interpret in the same way as `application/vnd.ipld.dag-json`. | ||||||||||
| - `application/vnd.ipld.dag-json`: Return the block specified by the path encoded in `dag-json`. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: link to IANA when ipfs/in-web-browsers#202 is resolved |
||||||||||
| - `application/vnd.ipld.dag-cbor`: Return the block specified by the path ecnoded in `dag-cbor`. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: link to IANA when ipfs/in-web-browsers#201 is resolved |
||||||||||
|
|
||||||||||
| ### Request Query Parameters | ||||||||||
|
|
||||||||||
| #### `format` (request query parameter) | ||||||||||
|
|
||||||||||
| Optional, `format=<format>` can be used to request specific encodings. | ||||||||||
|
|
||||||||||
| This is a URL-friendly alternative to sending `Accept: application/vnd.ipld.<format>` header, see [Accept](#accept-request-header) for more details. | ||||||||||
|
|
||||||||||
| ### Path Segments and Path Segment Parameters | ||||||||||
|
|
||||||||||
| Path segments are used for IPLD data model [traversal](https://ipld.io/docs/data-model/traversal/). | ||||||||||
| Each segment is separated by a `/` and contains a utf8 `name` followed by an optional set of parameters using the [Matrix URI format](https://www.w3.org/DesignIssues/MatrixURIs.html). | ||||||||||
|
|
||||||||||
| Example: | ||||||||||
|
|
||||||||||
| ``` | ||||||||||
| /ipld/bafywhatever/foo/bar;extra=thing;whatever=here/ | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| Path segments can have additional parameters added to them by separating them using semicolons (`;`) and having key-value pairs separated by an `=`. | ||||||||||
| This format is based on the [Matrix URI proposal from the w3c](https://www.w3.org/DesignIssues/MatrixURIs.html). | ||||||||||
RangerMauve marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| Note that these parameters are stripped from the segment name when passed to any underlying traversal code. | ||||||||||
|
|
||||||||||
| This spec only perscribes two reserved parameter names: `ADL` for specifying [Advanced Data Layouts](https://ipld.io/docs/advanced-data-layouts/) to process the data with, and `schema` to specify an [IPLD schema](https://ipld.io/docs/schemas/intro/) to use to interpret the data. | ||||||||||
RangerMauve marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| Other names may be specified in future specs that build upon this one. | ||||||||||
|
|
||||||||||
| #### ADL (segment parameter) | ||||||||||
|
|
||||||||||
| Segments may contain an `adl` key which points to a name of an [Advanced Data Layout](https://ipld.io/docs/advanced-data-layouts/intro/) to process the node with. | ||||||||||
|
|
||||||||||
| The supported ADL names will vary based on gateway. | ||||||||||
RangerMauve marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
|
||||||||||
| An example value would be `;adl=hamt` to specify the [HAMT](https://ipld.io/specs/advanced-data-layouts/hamt/) ADL that's used to represent large maps. | ||||||||||
|
|
||||||||||
| For example `/ipld/bafyreic672jz6huur4c2yekd3uycswe2xfqhjlmtmm5dorb6yoytgflova;adl=hamt/yes` (taken from the HAMT examples), should resolve to the following: | ||||||||||
RangerMauve marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
|
||||||||||
| ``` | ||||||||||
RangerMauve marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| [ | ||||||||||
| { | ||||||||||
| "line": 9, | ||||||||||
| "column": 501 | ||||||||||
| } | ||||||||||
| ] | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| #### Schema (segment parameter) | ||||||||||
|
|
||||||||||
| Segments may contain a `schema` key which points to the `CID` of an [IPLD Schema](https://ipld.io/docs/schemas/) in its [DMT](https://ipld.io/specs/schemas/#dsl-vs-dmt) form. | ||||||||||
| If a `schema` key is provided, there must also be a `type` parameter which references one of the named Types within the IPLD Schema. | ||||||||||
|
|
||||||||||
| The node at that point in the traversal will then be transformed by the schema, and any typed nodes it links to will also be transformed by their respective schemas. | ||||||||||
|
|
||||||||||
| For example, given the following schema (note it is written in DSL form, but must be converted to the DMT in order to be refernced): | ||||||||||
|
|
||||||||||
| ```ipldschema | ||||||||||
| type Example struct { | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: I've read this section and tbh have no idea what is the value to end user – CBOR traversal and field resolution with extra steps so the output looks a certain way? In ADL section we have good use case "ADL that's used to represent large maps" – we need similar real world example for schemas. What would a schema be useful for irl? I feel the spec here needs better
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One use case for schemas is to use the e.g. some things might be using a I'm gonna be doing stuff along this line for the Prolly Tree work where we'll be encoding tree nodes more efficiently, but having a way to put them through a schema before the application code starts working with them. |
||||||||||
| Hello String | ||||||||||
| Goodbye &NestedExample | ||||||||||
| } representation tuple | ||||||||||
|
|
||||||||||
| type NestedExample struct { | ||||||||||
| region String | ||||||||||
| } representation tuple | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| The CID for the DMT of this schema is `bafyreibvheoym4avfsjfw63yhsymovm7o54ftcnxwxovqf5xxcbjddanze` | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: was unable to inspec this via As a rule of thumb, CIDs used in IPIP should be publicly available and pinned (e.g. to https://estuary.tech and https://web3.storage, do not use Pinata as afaik it does not announce CIDs on DHT). We will have automation for this, btu for now it is up to IPIP author to handle.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should I maybe include some CBOR files with the fixtures that are relevant to the spec? |
||||||||||
|
|
||||||||||
| A raw node of type `NestedExample`, whose CID is `bafyreia5mssvef4owvyols2bduwxl6csvlb35oigyj4gc7wm6wzg44udtq`: | ||||||||||
|
|
||||||||||
| ```json | ||||||||||
| ['Cyberspace'] | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| A raw node of type `Example` which references the first node and whose CID is `bafyreifuyjaq3u3izc7qaf4shh76lk6565e72njgjxtava7q4s7bxheyxa`: | ||||||||||
|
|
||||||||||
| ```json | ||||||||||
| ['Hello', {'/': 'bafyreia5mssvef4owvyols2bduwxl6csvlb35oigyj4gc7wm6wzg44udtq'}] | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| We can construct the path `/ipld/bafyreifuyjaq3u3izc7qaf4shh76lk6565e72njgjxtava7q4s7bxheyxa/Goodbye?schema=bafyreibvheoym4avfsjfw63yhsymovm7o54ftcnxwxovqf5xxcbjddanze&type=Example`, or more succinctly `ipld://${cid2}/Goodbye?schema=${schemaCID}&type=Example`. | ||||||||||
|
|
||||||||||
| The resolved node should look like: | ||||||||||
|
|
||||||||||
| ```JSON | ||||||||||
| { | ||||||||||
| "region": "Cyberspace" | ||||||||||
| } | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| #### Escaping / Encoding | ||||||||||
|
|
||||||||||
| IPLD path segments and path segment keys/values may use [escape sequences that follow RFC1738](https://www.rfc-editor.org/rfc/rfc1738) to represent raw values like `/` which would otherwise be interpreted by URL parsers as being structurally significant. | ||||||||||
|
|
||||||||||
| Specifically, any values in path segments that are part of the "reserved" list of characters `";" | "/" | "?" | ":" | "@" | "&" | "="`, or are non-ascii characters, must be escaped when encoding to the path. | ||||||||||
|
|
||||||||||
| For example, path segment name `escape;this` should be escaped to `escape%3Bthis` so that `this` doesn't get accidentally parsed as a parameter. | ||||||||||
|
|
||||||||||
| Similarly, the path segment name `😁` should be escaped to `%F0%9F%98%81`. | ||||||||||
|
|
||||||||||
| ## Interaction with URLs | ||||||||||
|
|
||||||||||
| `/ipld/` HTTP paths map directly to `ipld://` URLs. | ||||||||||
RangerMauve marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| Similarly, `ipld://` URLs can be mapped back to `/ipld/` paths on the gateway. | ||||||||||
| This gives us an easy way to convert between URLs within applications and paths on gateways running either locally or remotely. | ||||||||||
Uh oh!
There was an error while loading. Please reload this page.