
最近在实现一个类似 gh-proxy 样的项目,本质上是代理转发流量,然后将源站的响应通过代理返回给客户端,目前 HTTP GET 和 POST 请求均能正常代理,但是 Git clone HTTP 不能正常执行。
git clone https://proxy.local/https://github.com/user/repos.git Cloning into 'repos'... error: 1 bytes of length header were received fatal: protocol error: bad line length character: 005 通过抓包比较发现共发出两个请求,分别是:
GET https://proxy.local/https://github.com/user/repos.git/info/refs?service=git-upload-pack HTTP/1.1 Host: proxy.local User-Agent: git/2.30.1 (Apple Git-130) Accept: */* Accept-Encoding: deflate, gzip Pragma: no-cache Git-Protocol: version=2 --- HTTP/1.1 200 OK Date: Thu, 23 Nov 2023 02:40:38 GMT Content-Type: application/x-git-upload-pack-advertisement Transfer-Encoding: chunked Connection: keep-alive expires: Fri, 01 Jan 1980 00:00:00 GMT pragma: no-cache Cache-Control: no-cache, max-age=0, must-revalidate vary: Accept-Encoding x-frame-options: DENY x-github-request-id: DE6A:5407:B244AD:BB74E2:XXXXXXXX access-control-expose-headers: * access-control-allow-origin: * strict-transport-security: max-age=2592000; includeSubDomains; preload 001e# service=git-upload-pack 0000000eversion 2 0022agent=git/github-cbc05ce31956 0013ls-refs=unborn 0027fetch=shallow wait-for-done filter 0012server-option 0017object-format=sha1 0000 和
POST https://proxy.local/https://github.com/user/repos.git/git-upload-pack HTTP/1.1 Host: proxy.local User-Agent: git/2.30.1 (Apple Git-130) Accept-Encoding: deflate, gzip Content-Type: application/x-git-upload-pack-request Accept: application/x-git-upload-pack-result Git-Protocol: version=2 Content-Length: 180 0014command=ls-refs 0024agent=git/2.30.1.(Apple.Git-130)0016object-format=sha100010009peel 000csymrefs 0014ref-prefix HEAD 001bref-prefix refs/heads/ 001aref-prefix refs/tags/ 0000 --- HTTP/1.1 200 OK Date: Thu, 23 Nov 2023 02:40:38 GMT Content-Type: application/x-git-upload-pack-result Transfer-Encoding: chunked Connection: keep-alive expires: Fri, 01 Jan 1980 00:00:00 GMT pragma: no-cache Cache-Control: no-cache, max-age=0, must-revalidate vary: Accept-Encoding x-github-request-id: 4CD0:60C4:A2B144:E33C9D:XXXXXXXX x-frame-options: DENY access-control-expose-headers: * access-control-allow-origin: * strict-transport-security: max-age=2592000; includeSubDomains; preload 0050c1e8f715543c3d40150ba757aa91c65671570b19 HEAD symref-target:refs/heads/main 003dc1e8f715543c3d40150ba757aa91c65671570b19 refs/heads/main 0000 上面 git clone 失败时的错误字符 005 应该是第二个请求 body 中的内容,但是我比对直接 clone GitHub 源仓库地址 https://github.com/user/repos.git,第二个请求响应的格式均一致,源站能直接 clone 完整,但是为什么通过代理 clone 就会报错呢?
1 pagxir 2023-11-23 12:45:56 +08:00 via Android 用了 chunked 编码,你查查你代理有正确处理 chunk 吗 |
2 iSecret OP @pagxir 感谢提供思路,我查看了下 `Transfer-Encoding: chunked` 似乎是我使用流( stream )方式请求后响应给客户端时自动在 header 头添加的 `Transfer-Encoding: chunked`,感觉看上去没问题,我是用 ghproxy.com 克隆仓库时也是有这个 header 头,也就是说 Git 客户端是支持分片传输的,奇怪。 ![]() |