关于 Git clone HTTP 协议代理的问题请教

2023-11-23 10:55:29 +08:00
 iSecret

最近在实现一个类似 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 就会报错呢?

920 次点击
所在节点    git
2 条回复
pagxir
2023-11-23 12:45:56 +08:00
用了 chunked 编码,你查查你代理有正确处理 chunk 吗
iSecret
2023-11-23 15:02:34 +08:00
@pagxir 感谢提供思路,我查看了下 `Transfer-Encoding: chunked` 似乎是我使用流( stream )方式请求后响应给客户端时自动在 header 头添加的 `Transfer-Encoding: chunked`,感觉看上去没问题,我是用 ghproxy.com 克隆仓库时也是有这个 header 头,也就是说 Git 客户端是支持分片传输的,奇怪。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/994430

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX