axios 如何从Docker API格式化/解码服务日志

lpwwtiir  于 2023-06-22  发布在  iOS
关注(0)|答案(2)|浏览(167)

我正在尝试从此端点的Docker API获取日志。我只是尝试将日志作为字符串返回,而不是使用websocket选项。它基本上可以工作,但是字符串包含奇怪的字符,我不知道该怎么办。
我用的是Axios和Express,像这样:

let result = await AXIOS.get(`http://${managerNodeIPAddress}/services/${idForLogs}/logs?stdout=true&stderr=true`);

如果I console.log(result)data属性如下所示:

data: '\x01\x00\x00\x00\x00\x00\x00#Example app listening on port 5000\n' +
    '\x01\x00\x00\x00\x00\x00\x00\x1F[16/4/2022-21:05:02] GET/: 200\n' +
    '\x01\x00\x00\x00\x00\x00\x00\x1F[16/4/2022-21:05:43] GET/: 200\n' +
    '\x01\x00\x00\x00\x00\x00\x00\x1F[16/4/2022-21:05:44] GET/: 200\n' +
    '\x01\x00\x00\x00\x00\x00\x00\x1F[16/4/2022-21:06:33] GET/: 200\n' +
// ...

如果我console.log(result.data),它看起来像这样:

<Buffer 01 00 00 00 00 00 00 23 45 78 61 6d 70 6c 65 20 61 70 70 20 6c 69 73 74 65 6e 69 6e 67 20 6f 6e 20 70 6f 72 74 20 35 30 30 30 0a 01 00 00 00 00 00 00 ... 972 more bytes>

如果我发送这个响应,并尝试在Postman或其他地方查看它的响应,查看者不知道如何处理初始的\x01类型字符串:

我认为它们是转义的二进制文件,或者类似的东西,我需要改变我的请求头,或者以一种特殊的方式解析axios响应来处理这个问题。我也会很高兴
1.将这些字符解码成它们应该是的任何东西(我已经尝试过使用toString('utf-8)等“解码”缓冲区,但这似乎并没有摆脱字符,所以当在某些上下文中传递和查看时,它们仍然显示奇怪。或,
1.完全删除这些字符(我尝试使用replace方法来执行后一个操作,但由于某些原因,它不起作用)。
我以前从来没有处理过这个问题,所以像这样的编码/解码世界感觉有点神秘,我希望任何人都能有任何提示。

w8ntj3qf

w8ntj3qf1#

我想我能弄明白。就我现在所理解的事情来说,00和01是(或代表?)十六进制字节,其中correspond to ASCII字符SOH(头的开始)和NUL(空)。mac终端在解读这些代码时没有问题,但似乎其他一些应用程序有问题。我可以通过过滤缓冲区数组来消除它们,如下所示:

let logs = result.data.filter(byte => byte !== 01 && byte !== 00).toString();

老实说,我有点惊讶这起作用了,但它似乎有。这并不影响日志在终端中的外观,现在在Postman中看起来很好。

5t7ly7z5

5t7ly7z52#

(Note:这适用于/containers/{id}/logs端点,但我认为该格式很可能被重用。)
我发现docker logs输出正确,cat-ing JSON也是如此,但是通过Engine API获取返回类似的“畸形”数据。在我的例子中,我注意到了一个额外的非空字符(例如:十六进制01 00 00 00 00 00 00 59
似乎每一个区块(行?)之前是以下8字节报头序列:
SOH NUL NUL NUL A B C D其中ABCD是表示长度的大端32位整数。
我从下面的docker-py库代码中推断出了这一点(我的评论):

# Within a while loop
# STREAM_HEADER_SIZE_BYTES is 8
header = response.raw.read(STREAM_HEADER_SIZE_BYTES)
if not header:
    break
# `>`=big endian, `B`=unsigned char (SOH/0x01)
# `x`=padding, `L`=long aka unsigned int32
# _ is getting SOH, length is getting the chunk size
_, length = struct.unpack('>BxxxL', header)
if not length:
    continue
# Read remainder of chunk
data = response.raw.read(length)
if not data:
    break
yield data

来源:struct docsdocker-py source(GitHub)

相关问题