GitHub API returns 单字节(“0xC4”)二进制文件的三个字节

GitHub API returns three bytes for a single-byte ("0xC4") binary file

我正在解决可能是编码问题的问题,只是找不到它。 GitHub API 给了我 三个 个字节,而不是一个只包含 0xC4 的文件。插图:

正在创建文件:

~/github-binary-api-problem(master*) » echo -n -e '\xc4' > c4-createdfromfilesystem
~/github-binary-api-problem(master*) » hexdump c4-createdfromfilesystem
0000000 c4
0000001

我像往常一样将该文件提交给 GitHub - go take a look - GitHub 认为它是一个字节:

到目前为止一切顺利。现在我尝试使用 Contents API (GET /repos/{owner}/{repo}/contents/{path}):

下载它
~/github-binary-api-problem(master*) » curl \
-H "Accept: application/vnd.github.v3.raw" \
https://api.github.com/repos/Undo1/github-binary-api-problem/contents/c4-createdfromfilesystem | hexdump
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100     3  100     3    0     0      8      0 --:--:-- --:--:-- --:--:--     8
0000000 ef bf bd
0000003
~/github-binary-api-problem(master*) »

然后我得到 三个 字节!这个例子是在 macOS 环境下,但我第一次看到它是在 Windows 上。我确定这是堆栈中某处的编码问题,但我找不到它。我需要做什么才能从 GitHub API?

中获取二进制文件的准确表示

更新 - 我发现 0xef 0xbf 0xbdUTF-8 replacement character,所以我猜 GitHub 的 API 正在尝试使用 UTF-8 编码在发送文件之前,即使指定了 raw。我已发送 GitHub 支持票。

这看起来像是 GitHub 方面的真正问题。可以克隆包含此类文件的存储库并且生成的文件将是正确的,但是在网络中查看它 UI 或从原始 API 获取它会导致替换字符(EF BF BD).

作为解决方法,直到您的支持请求得到响应,请改为请求非原始 (JSON) API:

$ curl https://api.github.com/repos/Undo1/github-binary-api-problem/contents/c4-createdfromfilesystem
{
  "name": "c4-createdfromfilesystem",
  "path": "c4-createdfromfilesystem",
  "sha": "ef6080906700f3f3cdac7d60341a5de7b5da5581",
  "size": 1,
  "url": "https://api.github.com/repos/Undo1/github-binary-api-problem/contents/c4-createdfromfilesystem?ref=master",
  "html_url": "https://github.com/Undo1/github-binary-api-problem/blob/master/c4-createdfromfilesystem",
  "git_url": "https://api.github.com/repos/Undo1/github-binary-api-problem/git/blobs/ef6080906700f3f3cdac7d60341a5de7b5da5581",
  "download_url": "https://raw.githubusercontent.com/Undo1/github-binary-api-problem/master/c4-createdfromfilesystem",
  "type": "file",
  "content": "77+9\n",
  "encoding": "base64",
  "_links": {
    "self": "https://api.github.com/repos/Undo1/github-binary-api-problem/contents/c4-createdfromfilesystem?ref=master",
    "git": "https://api.github.com/repos/Undo1/github-binary-api-problem/git/blobs/ef6080906700f3f3cdac7d60341a5de7b5da5581",
    "html": "https://github.com/Undo1/github-binary-api-problem/blob/master/c4-createdfromfilesystem"
  }
}

这有一个 base64 编码的 content 属性,但对其解码显示它又是 EF BF BD - 一个替换字符。但是,鉴于 git 存储库有效,可以合理假设 git API 也可能有效 - 因此,遵循 _links.git 字段:

$ curl https://api.github.com/repos/Undo1/github-binary-api-problem/git/blobs/ef6080906700f3f3cdac7d60341a5de7b5da5581
{
  "sha": "ef6080906700f3f3cdac7d60341a5de7b5da5581",
  "node_id": "MDQ6QmxvYjI4MjA0NDU1NzplZjYwODA5MDY3MDBmM2YzY2RhYzdkNjAzNDFhNWRlN2I1ZGE1NTgx",
  "size": 1,
  "url": "https://api.github.com/repos/Undo1/github-binary-api-problem/git/blobs/ef6080906700f3f3cdac7d60341a5de7b5da5581",
  "content": "xA==\n",
  "encoding": "base64"
}

这个 有一个 base64 编码的 content 字段,解码后会产生 0xC4,即正确的值。


为了加分,如果你安装了所有正确的实用程序,你可以在终端中输入一行:

curl https://api.github.com/repos/Undo1/github-binary-api-problem/contents/c4-createdfromfilesystem | jq -r '._links.git' | xargs curl | jq -r '.content' | base64 --decode