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=json
POST /api/v0/version?enc=json&stream-channels=true HTTP/1.1
Host: 127.0.0.1:5002
User-Agent: /go-ipfs/0.3.8/
Content-Length: 0
Content-Type: application/octet-stream
Accept-Encoding: gzip
唯一困难的部分是让文件流正确. (现在) 使用 multipart 将文件流式传输到 go-ipfs 相当容易. 基本上,我们最终得到这样的 HTTP 请求:
> nc -l 5002 &
> ipfs --api /ip4/127.0.0.1/tcp/5002 add -r ~/demo/basic/test
POST /api/v0/add?encoding=json&progress=true&r=true&stream-channels=true HTTP/1.1
Host: 127.0.0.1:5002
User-Agent: /go-ipfs/0.3.8/
Transfer-Encoding: chunked
Content-Disposition: form-data: name="files"
Content-Type: multipart/form-data; boundary=2186ef15d8f2c4f100af72d6d345afe36a4d17ef11264ec5b8ec4436447f
Accept-Encoding: gzip
1
-
e5
-2186ef15d8f2c4f100af72d6d345afe36a4d17ef11264ec5b8ec4436447f
Content-Disposition: form-data; name="file"; filename="test"
Content-Type: multipart/mixed; boundary=acdb172fe12f25e8ffae9981ce6f4580abdefb0cae3ceebe464d802866be
9c
--acdb172fe12f25e8ffae9981ce6f4580abdefb0cae3ceebe464d802866be
Content-Disposition: file; filename="test%2Fbar"
Content-Type: application/octet-stream
4
bar
dc
--acdb172fe12f25e8ffae9981ce6f4580abdefb0cae3ceebe464d802866be
Content-Disposition: file; filename="test%2Fbaz"
Content-Type: multipart/mixed; boundary=2799ac77a72ef7b8a0281945806b9f9a28f7681145aa8e91b052d599b2dd
a0
--2799ac77a72ef7b8a0281945806b9f9a28f7681145aa8e91b052d599b2dd
Content-Type: application/octet-stream
Content-Disposition: file; filename="test%2Fbaz%2Fb"
4
bar
a2
--2799ac77a72ef7b8a0281945806b9f9a28f7681145aa8e91b052d599b2dd
Content-Disposition: file; filename="test%2Fbaz%2Ff"
Content-Type: application/octet-stream
4
foo
44
--2799ac77a72ef7b8a0281945806b9f9a28f7681145aa8e91b052d599b2dd--
9e
--acdb172fe12f25e8ffae9981ce6f4580abdefb0cae3ceebe464d802866be
Content-Disposition: file; filename="test%2Ffoo"
Content-Type: application/octet-stream
4
foo
44
--acdb172fe12f25e8ffae9981ce6f4580abdefb0cae3ceebe464d802866be--
44
--2186ef15d8f2c4f100af72d6d345afe36a4d17ef11264ec5b8ec4436447f--
0
是在这里产生的: http://gateway.ipfs.io/ipfs/QmNtpA5TBNqHrKf3cLQ1AiUKXiE4JmUodbG5gXrajg8wdv