You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Docker返回的基本都是json数据,最后对 response body 进行处理,就可以拿到数据了。
Chunked transfer encoding
当然 Docker 返回的不都是json数据,在查询 containers logs,以及 Attach to a container 文档中标识返回的是 stream.
经过测试发现使用的是分块传输编码(Chunked transfer encoding), response.header 中有Transfer-Encoding = chunked标记.
格式:
如果一个HTTP消息(请求消息或应答消息)的Transfer-Encoding消息头的值为chunked,那么,消息体由数量未定的块组成,并以最后一个大小为0的块为结束。
每一个非空的块都以该块包含数据的字节数(字节数以十六进制表示)开始,跟随一个CRLF (回车及换行),然后是数据本身,最后块CRLF结束。在一些实现中,块大小和CRLF之间填充有白空格(0x20)。
最后一块是单行,由块大小(0),一些可选的填充白空格,以及CRLF。最后一块不再包含任何数据,但是可以发送可选的尾部,包括消息头字段。
消息最后以CRLF结尾。
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
25
This is the data in the first chunk
1C
and this is the second one
3
con
8
sequence
0
至此,已经得到了Docker Engine Api 回传的数据了,大多数api都是返回的json数据,转table后直接可以使用,stream格式的数据需要额外处理。
即,每个数据包的头部有8个字节,第一个自交表示stream的type,接下来3个为空,剩余4个字节组成一个int32的整型数据,表示这个数据包中有效数据的长度。剩余的即是数据。
Docker API Doc 介绍如下:
Stream format
When the TTY setting is disabled in POST /containers/create, the stream over the hijacked connected is multiplexed to separate out stdout and stderr. The stream consists of a series of frames, each containing a header and a payload.
The header contains the information which the stream writes (stdout or stderr). It also contains the size of the associated frame encoded in the last four bytes (uint32).
It is encoded on the first eight bytes like this:
header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}
STREAM_TYPE can be:
0: stdin (is written on stdout)
1: stdout
2: stderr
SIZE1, SIZE2, SIZE3, SIZE4 are the four bytes of the uint32 size encoded as big endian.
Following the header is the payload, which is the specified number of bytes of STREAM_TYPE.
实现方法:
functiondocker_stream_filter(buffer)
buffer=bufferor""if#buffer<8thenreturn"" endlocalstream_type=((string.byte(buffer,1) ==1) and'stdout') or ((string.byte(buffer,1) ==2) and'stderr') or ((string.byte(buffer,1) ==0) and'stdin') or'stream_err'localvalid_length=tonumber(string.byte(buffer,5)) *256*256*256+tonumber(string.byte(buffer,6)) *256*256+tonumber(string.byte(buffer,7)) *256+tonumber(string.byte(buffer,8))
ifvalid_length>#buffer+8thenreturn"" endreturnstream_type..': ' ..string.sub(buffer, 9, valid_length+8)
endstream_data={}
fori,vinipairs(response.body) dostream_data[#stream_data+1] =docker_stream_filter(response.body[i])
end
The text was updated successfully, but these errors were encountered:
HTTP ON UNIX SOCKET
Docker 采用 unix socket 方式进行通信,使用 luci 自带 nixio 库中的 socket
使用 HTTP 协议进行传输
接受数据, 并处理header
Docker返回的基本都是json数据,最后对 response body 进行处理,就可以拿到数据了。
Chunked transfer encoding
当然 Docker 返回的不都是json数据,在查询 containers logs,以及 Attach to a container 文档中标识返回的是 stream.
经过测试发现使用的是分块传输编码(Chunked transfer encoding),
response.header
中有Transfer-Encoding = chunked
标记.格式:
如果一个HTTP消息(请求消息或应答消息)的Transfer-Encoding消息头的值为chunked,那么,消息体由数量未定的块组成,并以最后一个大小为0的块为结束。
每一个非空的块都以该块包含数据的字节数(字节数以十六进制表示)开始,跟随一个CRLF (回车及换行),然后是数据本身,最后块CRLF结束。在一些实现中,块大小和CRLF之间填充有白空格(0x20)。
最后一块是单行,由块大小(0),一些可选的填充白空格,以及CRLF。最后一块不再包含任何数据,但是可以发送可选的尾部,包括消息头字段。
消息最后以CRLF结尾。
这里弯路走了很多,后来发现 luci.httpclient 已经提供了 decoding 的方法:
httpclient.chunksource(source,buffer)
,所以只需要:不过貌似
http.client.chunksource
在解码Chunked transfer的时候存在一些bug,所以重新修复了一下:处理body
至此,已经得到了Docker Engine Api 回传的数据了,大多数api都是返回的json数据,转table后直接可以使用,stream格式的数据需要额外处理。
即,每个数据包的头部有8个字节,第一个自交表示stream的type,接下来3个为空,剩余4个字节组成一个int32的整型数据,表示这个数据包中有效数据的长度。剩余的即是数据。
Docker API Doc 介绍如下:
实现方法:
The text was updated successfully, but these errors were encountered: