最近在实现一个类似 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 客户端是支持分片传输的,奇怪。
|