IPFS API 实现文档
这篇简短的文档旨在为任何想知道 api-绑定的实现,特别是 go-ipfs{ipfs 的主要实现软件}的人们.
章节:
IPFS 类型
IPFS 使用一组 set值类型,可用于预先枚举:
<ipfs-path>是 unix 风格 的路径,从一开始/ipfs/<cid>/...要么/ipns/<hash>/...要么/ipns/<domain>/....<hash>是 base58 编码multihashcid是一个Multibase编码CID- 自描述内容寻址标识符
有关流的说明: IPFS 是一种流协议. 关于它的一切都可以流式传输. 导入文件时,API 请求,应旨在流入数据,并正确处理背压-back-pressure,以便 IPFS 节点可以顺序处理它而不会有太大的内存压力. (如果使用 HTTP,通常会,通过写入请求主体堵塞来处理此问题. )
API 传输
与其他所有内容一样,IPFS 旨在灵活地处理 API 传输. 目前,go-ipfs实现支持 进程内 API 和 HTTP API. 通过在传输上 映射 API 函数,可以轻松添加更多内容. (这类似于 gRPC 也是如此映射在传输之上,像 HTTP) .
映射到传输涉及利用 传输的功能 来表达函数调用. 例如:
API 传输的 CLI
在命令行中,IPFS 使用 传统的 flag 和 基于 arg 的映射,其中:
- 第一个参数选择命令,如在 git 中 - 例如
ipfs object get - flag 指定选项 - 例如
--enc=protobuf -q - 其余的是位置参数 - 例如
ipfs object patch <hash1> add-linkfoo <hash2> - 文件由 filename 或 stdin 指定
(注意: 当 go-ipfs 运行守护进程时,CLI API 实际上转换为 HTTP 调用. 否则,它们在同一进程中执行)
HTTP API 传输
在 HTTP 中,我们的 API 分层 使用类似 REST 的映射,其中:
- URL 路径选择命令 - 例如:
/object/get - URL 查询字符串 实现 选项参数 - 例如:
&enc=protobuf&q=true - URL 查询 还实现 位置参数 - 例如:
&arg=<hash1>&arg=add-link&arg=foo&arg=<hash2> 请求主体流文件数据 - 读取文件 或 stdin
- 多个流与多部分复用 (todo: 添加 tar 流 支持)
API 命令
这是”标准 IPFS API”,当前定义为”go-ipfs 实现所公开的所有命令”.
有自动生成API 文档,你也可以看看在这里列出,或通过运行ipfs commands获取命令列表.
实现 HTTP API 的绑定
如上所述,API 命令映射到 HTTP:
- URL 路径 选择 命令 - 例如
/object/get - URL 查询字符串 实现 选项参数 - 例如
&enc=protobuf&q=true - URL 查询 还实现 位置参数 - 例如
&arg=<hash1>&arg=add-link&arg=foo&arg=<hash2> - 请求主体流文件数据 - 读取文件 或 stdin
- 多个流与多部分复用 (todo: 添加 tar 流支持)
到目前为止,我们有两个不同的 HTTP API 客户端:
- js-ipfs-API- 简单的 javascript 包装 - 最好看
- go-ipfs/commands/http- 基于命令定义的常见传输
Go 实现很适合回答更难的问题,例如如何处理 多部分,或者在边缘条件下应该设置哪些标题. 但是 javascript 实现也非常简洁,易于遵循.
node-ipfs-api 的剖析
目前,node-ipfs-api 有三个主要文件
- src/index.js定义 API 模块的客户端将使用的函数. 使用
RequestAPI,几乎直接将 函数调用参数 转换为 API. - src/get-files-stream.js实现最难的部分: 文件流. 这个使用 multipart.
- src/request-api.js泛型函数调用 来执行实际的 HTTP 请求
关于 multipart + 检查 请求 的注意事项
尽管上面已经说过所有的概括,但 IPFS API 实际上非常简单. 您可以检查所有请求带nc和--api选项 (截至这个 PR, 要么0.3.8) :
> nc -l 5002 &> ipfs --api /ip4/127.0.0.1/tcp/5002 swarm addrs local --enc=jsonPOST /api/v0/version?enc=json&stream-channels=true HTTP/1.1Host: 127.0.0.1:5002User-Agent: /go-ipfs/0.3.8/Content-Length: 0Content-Type: application/octet-streamAccept-Encoding: gzip
唯一困难的部分是让文件流正确. (现在) 使用 multipart 将文件流式传输到 go-ipfs 相当容易. 基本上,我们最终得到这样的 HTTP 请求:
> nc -l 5002 &> ipfs --api /ip4/127.0.0.1/tcp/5002 add -r ~/demo/basic/testPOST /api/v0/add?encoding=json&progress=true&r=true&stream-channels=true HTTP/1.1Host: 127.0.0.1:5002User-Agent: /go-ipfs/0.3.8/Transfer-Encoding: chunkedContent-Disposition: form-data: name="files"Content-Type: multipart/form-data; boundary=2186ef15d8f2c4f100af72d6d345afe36a4d17ef11264ec5b8ec4436447fAccept-Encoding: gzip1-e5-2186ef15d8f2c4f100af72d6d345afe36a4d17ef11264ec5b8ec4436447fContent-Disposition: form-data; name="file"; filename="test"Content-Type: multipart/mixed; boundary=acdb172fe12f25e8ffae9981ce6f4580abdefb0cae3ceebe464d802866be9c--acdb172fe12f25e8ffae9981ce6f4580abdefb0cae3ceebe464d802866beContent-Disposition: file; filename="test%2Fbar"Content-Type: application/octet-stream4bardc--acdb172fe12f25e8ffae9981ce6f4580abdefb0cae3ceebe464d802866beContent-Disposition: file; filename="test%2Fbaz"Content-Type: multipart/mixed; boundary=2799ac77a72ef7b8a0281945806b9f9a28f7681145aa8e91b052d599b2dda0--2799ac77a72ef7b8a0281945806b9f9a28f7681145aa8e91b052d599b2ddContent-Type: application/octet-streamContent-Disposition: file; filename="test%2Fbaz%2Fb"4bara2--2799ac77a72ef7b8a0281945806b9f9a28f7681145aa8e91b052d599b2ddContent-Disposition: file; filename="test%2Fbaz%2Ff"Content-Type: application/octet-stream4foo44--2799ac77a72ef7b8a0281945806b9f9a28f7681145aa8e91b052d599b2dd--9e--acdb172fe12f25e8ffae9981ce6f4580abdefb0cae3ceebe464d802866beContent-Disposition: file; filename="test%2Ffoo"Content-Type: application/octet-stream4foo44--acdb172fe12f25e8ffae9981ce6f4580abdefb0cae3ceebe464d802866be--44--2186ef15d8f2c4f100af72d6d345afe36a4d17ef11264ec5b8ec4436447f--0
是在这里产生的: http://gateway.ipfs.io/ipfs/QmNtpA5TBNqHrKf3cLQ1AiUKXiE4JmUodbG5gXrajg8wdv
