mirror of
https://github.com/WJQSERVER-STUDIO/ghproxy.git
synced 2026-02-03 00:01:10 +08:00
commit
060453f070
13 changed files with 120 additions and 81 deletions
33
CHANGELOG.md
33
CHANGELOG.md
|
|
@ -1,6 +1,37 @@
|
|||
# 更新日志
|
||||
|
||||
3.0.1 -2025-04-08
|
||||
3.0.2 - 2025-04-15
|
||||
---
|
||||
- CHANGE: 避免重复的re编译操作
|
||||
- CHANGE: 去除不必要的请求
|
||||
- CHANGE: 改进`httpc`相关配置
|
||||
- CHANGE: 更新`httpc` 0.4.0
|
||||
- CHANGE: 为不遵守`RFC 2616`, `RFC 9112`的客户端带来兼容性改进
|
||||
|
||||
25w28b - 2025-04-15
|
||||
---
|
||||
- PRE-RELEASE: 此版本是v3.0.2预发布版本,请勿在生产环境中使用;
|
||||
- CHANGE: 改进resp关闭
|
||||
- CHANGE: 避免重复的re编译操作
|
||||
|
||||
25w28a - 2025-04-14
|
||||
---
|
||||
- PRE-RELEASE: 此版本是预发布版本,请勿在生产环境中使用;
|
||||
- CHANGE: 去除不必要的请求
|
||||
- CHANGE: 改进`httpc`相关配置
|
||||
- CHANGE: 合入test版本修改
|
||||
|
||||
25w28t-2 - 2025-04-11
|
||||
---
|
||||
- TEST: 测试验证版本
|
||||
- CHANGE: 为不遵守`RFC 2616`, `RFC 9112`的客户端带来兼容性改进
|
||||
|
||||
25w28t-1 - 2025-04-11
|
||||
---
|
||||
- TEST: 测试验证版本
|
||||
- CHANGE: 更新httpc 0.4.0
|
||||
|
||||
3.0.1 - 2025-04-08
|
||||
---
|
||||
- CHANGE: 加入`memLimit`指示gc
|
||||
- CHANGE: 加入`hlog`输出路径配置
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
25w27a
|
||||
25w28b
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[](https://goreportcard.com/report/github.com/WJQSERVER-STUDIO/ghproxy)
|
||||
|
||||
使用Go实现的GHProxy,用于加速部分地区Github仓库的拉取,支持速率限制,用户鉴权,支持Docker部署
|
||||
支持 Git clone、raw、releases的 Github 加速项目, 支持自托管的同时带来卓越的性能与极低的资源占用(Golang和HertZ带来的优势), 同时支持多种额外功能
|
||||
|
||||
## 项目说明
|
||||
|
||||
|
|
@ -16,9 +16,10 @@
|
|||
- 🚫 **支持自定义黑名单/白名单**
|
||||
- 🗄️ **支持 Git Clone 缓存(配合 [Smart-Git](https://github.com/WJQSERVER-STUDIO/smart-git))**
|
||||
- 🐳 **支持 Docker 部署**
|
||||
- 🐳 **支持自托管**
|
||||
- ⚡ **支持速率限制**
|
||||
- 🔒 **支持用户鉴权**
|
||||
- 🐚 **支持 shell 脚本嵌套加速**
|
||||
- 🐚 **支持 shell 脚本多层嵌套加速**
|
||||
|
||||
### 项目相关
|
||||
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
3.0.1
|
||||
3.0.2
|
||||
8
go.mod
8
go.mod
|
|
@ -5,10 +5,10 @@ go 1.24.2
|
|||
require (
|
||||
github.com/BurntSushi/toml v1.5.0
|
||||
github.com/WJQSERVER-STUDIO/go-utils/logger v1.5.0
|
||||
github.com/cloudwego/hertz v0.9.6
|
||||
github.com/cloudwego/hertz v0.9.7
|
||||
github.com/hertz-contrib/http2 v0.1.8
|
||||
github.com/satomitouka/touka-httpc v0.3.3
|
||||
golang.org/x/net v0.38.0
|
||||
github.com/satomitouka/touka-httpc v0.4.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/time v0.11.0
|
||||
)
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ require (
|
|||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
golang.org/x/arch v0.16.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
|
|
|
|||
16
go.sum
16
go.sum
|
|
@ -20,8 +20,8 @@ github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCy
|
|||
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/gopkg v0.1.4 h1:EoQiCG4sTonTPHxOGE0VlQs+sQR+Hsi2uN0qqwu8O50=
|
||||
github.com/cloudwego/gopkg v0.1.4/go.mod h1:FQuXsRWRsSqJLsMVd5SYzp8/Z1y5gXKnVvRrWUOsCMI=
|
||||
github.com/cloudwego/hertz v0.9.6 h1:Kj5SSPlKBC32NIN7+B/tt8O1pdDz8brMai00rqqjULQ=
|
||||
github.com/cloudwego/hertz v0.9.6/go.mod h1:X5Ez52XhtszU4t+CTBGIJI4PqmcI1oSf8ULBz0SWfLo=
|
||||
github.com/cloudwego/hertz v0.9.7 h1:tAVaiO+vTf+ZkQhvNhKbDJ0hmC4oJ7bzwDi1KhvhHy4=
|
||||
github.com/cloudwego/hertz v0.9.7/go.mod h1:t6d7NcoQxPmETvzPMMIVPHMn5C5QzpqIiFsaavoLJYQ=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cloudwego/netpoll v0.7.0 h1:bDrxQaNfijRI1zyGgXHQoE/nYegL0nr+ijO1Norelc4=
|
||||
github.com/cloudwego/netpoll v0.7.0/go.mod h1:PI+YrmyS7cIr0+SD4seJz3Eo3ckkXdu2ZVKBLhURLNU=
|
||||
|
|
@ -50,8 +50,8 @@ github.com/nyaruka/phonenumbers v1.6.0 h1:r9ax45fFg+YLUs2X4bNXm5RAxWl00hYjFgNlv3
|
|||
github.com/nyaruka/phonenumbers v1.6.0/go.mod h1:7gjs+Lchqm49adhAKB5cdcng5ZXgt6x7Jgvi0ZorUtU=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/satomitouka/touka-httpc v0.3.3 h1:Th0uJ5do3oqqZgdUDtqD1SH11x8TcJmrwHMJQlEIKCg=
|
||||
github.com/satomitouka/touka-httpc v0.3.3/go.mod h1:sNXyW5XBufkwB9ZJ+PIlgN/6xiJ7aZV1fWGrXR0u3bA=
|
||||
github.com/satomitouka/touka-httpc v0.4.0 h1:cnOONdyJHJImMY8L64bvYF+7Ow/5CPf2Yr3RQRRMZOU=
|
||||
github.com/satomitouka/touka-httpc v0.4.0/go.mod h1:sNXyW5XBufkwB9ZJ+PIlgN/6xiJ7aZV1fWGrXR0u3bA=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
|
|
@ -87,8 +87,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
|
@ -98,8 +98,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
|
|||
5
main.go
5
main.go
|
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/cloudwego/hertz/pkg/common/adaptor"
|
||||
"github.com/cloudwego/hertz/pkg/common/hlog"
|
||||
|
||||
//"github.com/cloudwego/hertz/pkg/network/standard"
|
||||
"github.com/hertz-contrib/http2/factory"
|
||||
)
|
||||
|
||||
|
|
@ -146,6 +147,7 @@ func setupHertZLogger(cfg *config.Config) {
|
|||
} else {
|
||||
hlog.SetOutput(hertZfile)
|
||||
}
|
||||
hlog.SetLevel(hlog.LevelInfo)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -239,7 +241,6 @@ func setupPages(cfg *config.Config, r *server.Hertz) {
|
|||
r.StaticFile("/style.css", stylesheetsPath)
|
||||
r.StaticFile("/bootstrap.min.css", bootstrapPath)
|
||||
r.StaticFile("/bootstrap.bundle.min.js", bootstrapBundlePath)
|
||||
//router.StaticFile("/bootstrap.min.css", bootstrapPath)
|
||||
|
||||
default:
|
||||
// 处理无效的Pages Mode
|
||||
|
|
@ -377,6 +378,8 @@ func main() {
|
|||
r = server.New(
|
||||
server.WithHostPorts(addr),
|
||||
server.WithH2C(true),
|
||||
// server.WithALPN(true),
|
||||
// server.WithTransport(standard.NewTransporter),
|
||||
)
|
||||
r.AddProtocol("h2", factory.NewServerFactory())
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"ghproxy/config"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
|
|
@ -15,39 +14,6 @@ import (
|
|||
func ChunkedProxyRequest(ctx context.Context, c *app.RequestContext, u string, cfg *config.Config, matcher string) {
|
||||
method := c.Request.Method
|
||||
|
||||
// 发送HEAD请求, 预获取Content-Length
|
||||
headReq, err := client.NewRequest("HEAD", u, nil)
|
||||
if err != nil {
|
||||
HandleError(c, fmt.Sprintf("Failed to create request: %v", err))
|
||||
return
|
||||
}
|
||||
setRequestHeaders(c, headReq)
|
||||
removeWSHeader(headReq) // 删除Conection Upgrade头, 避免与HTTP/2冲突(检查是否存在Upgrade头)
|
||||
AuthPassThrough(c, cfg, headReq)
|
||||
|
||||
headResp, err := client.Do(headReq)
|
||||
if err != nil {
|
||||
HandleError(c, fmt.Sprintf("Failed to send request: %v", err))
|
||||
return
|
||||
}
|
||||
defer func(Body io.ReadCloser) {
|
||||
if err := Body.Close(); err != nil {
|
||||
logError("Failed to close response body: %v", err)
|
||||
}
|
||||
}(headResp.Body)
|
||||
|
||||
contentLength := headResp.Header.Get("Content-Length")
|
||||
sizelimit := cfg.Server.SizeLimit * 1024 * 1024
|
||||
if contentLength != "" {
|
||||
size, err := strconv.Atoi(contentLength)
|
||||
if err == nil && size > sizelimit {
|
||||
finalURL := headResp.Request.URL.String()
|
||||
c.Redirect(http.StatusMovedPermanently, []byte(finalURL))
|
||||
logWarning("%s %s %s %s %s Final-URL: %s Size-Limit-Exceeded: %d", c.ClientIP(), c.Method(), c.Path(), c.Request.Header.Get("User-Agent"), c.Request.Header.GetProtocol(), finalURL, size)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
body := c.Request.Body()
|
||||
|
||||
bodyReader := bytes.NewBuffer(body)
|
||||
|
|
@ -69,18 +35,33 @@ func ChunkedProxyRequest(ctx context.Context, c *app.RequestContext, u string, c
|
|||
|
||||
// 错误处理(404)
|
||||
if resp.StatusCode == 404 {
|
||||
c.String(http.StatusNotFound, "File Not Found")
|
||||
//c.Status(http.StatusNotFound)
|
||||
//c.String(http.StatusNotFound, "File Not Found")
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
bodySize int
|
||||
contentLength string
|
||||
sizelimit int
|
||||
)
|
||||
sizelimit = cfg.Server.SizeLimit * 1024 * 1024
|
||||
contentLength = resp.Header.Get("Content-Length")
|
||||
if contentLength != "" {
|
||||
size, err := strconv.Atoi(contentLength)
|
||||
if err == nil && size > sizelimit {
|
||||
var err error
|
||||
bodySize, err = strconv.Atoi(contentLength)
|
||||
if err != nil {
|
||||
logWarning("%s %s %s %s %s Content-Length header is not a valid integer: %v", c.ClientIP(), c.Method(), c.Path(), c.UserAgent(), c.Request.Header.GetProtocol(), err)
|
||||
bodySize = -1
|
||||
}
|
||||
if err == nil && bodySize > sizelimit {
|
||||
finalURL := resp.Request.URL.String()
|
||||
err := resp.Body.Close()
|
||||
if err != nil {
|
||||
logError("Failed to close response body: %v", err)
|
||||
}
|
||||
c.Redirect(http.StatusMovedPermanently, []byte(finalURL))
|
||||
logWarning("%s %s %s %s %s Final-URL: %s Size-Limit-Exceeded: %d", c.ClientIP(), c.Method(), c.Path(), c.UserAgent(), c.Request.Header.GetProtocol(), finalURL, size)
|
||||
logWarning("%s %s %s %s %s Final-URL: %s Size-Limit-Exceeded: %d", c.ClientIP(), c.Method(), c.Path(), c.UserAgent(), c.Request.Header.GetProtocol(), finalURL, bodySize)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -132,6 +113,10 @@ func ChunkedProxyRequest(ctx context.Context, c *app.RequestContext, u string, c
|
|||
return
|
||||
}
|
||||
} else {
|
||||
if contentLength != "" {
|
||||
c.SetBodyStream(resp.Body, bodySize)
|
||||
return
|
||||
}
|
||||
c.SetBodyStream(resp.Body, -1)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ func GitReq(ctx context.Context, c *app.RequestContext, u string, cfg *config.Co
|
|||
if contentLength != "" {
|
||||
size, err := strconv.Atoi(contentLength)
|
||||
sizelimit := cfg.Server.SizeLimit * 1024 * 1024
|
||||
if err != nil {
|
||||
logWarning("%s %s %s %s %s Content-Length header is not a valid integer: %v", c.ClientIP(), c.Method(), c.Path(), c.UserAgent(), c.Request.Header.GetProtocol(), err)
|
||||
}
|
||||
if err == nil && size > sizelimit {
|
||||
finalURL := []byte(resp.Request.URL.String())
|
||||
c.Redirect(http.StatusMovedPermanently, finalURL)
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter, iplimiter *ra
|
|||
}
|
||||
|
||||
// 鉴权
|
||||
if cfg.Auth.Enabled {
|
||||
var authcheck bool
|
||||
authcheck, err = auth.AuthHandler(ctx, c, cfg)
|
||||
if !authcheck {
|
||||
|
|
@ -114,6 +115,7 @@ func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter, iplimiter *ra
|
|||
logWarning("%s %s %s %s %s Auth-Error: %v", c.ClientIP(), c.Method(), rawPath, c.Request.Header.UserAgent(), c.Request.Header.GetProtocol(), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// IP METHOD URL USERAGENT PROTO MATCHES
|
||||
logDebug("%s %s %s %s %s Matched: %v", c.ClientIP(), c.Method(), rawPath, c.Request.Header.UserAgent(), c.Request.Header.GetProtocol(), matcher)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ func initHTTPClient(cfg *config.Config) {
|
|||
if cfg.Httpc.Mode == "auto" {
|
||||
|
||||
tr = &http.Transport{
|
||||
//MaxIdleConns: 160,
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
WriteBufferSize: 32 * 1024, // 32KB
|
||||
ReadBufferSize: 32 * 1024, // 32KB
|
||||
|
|
@ -64,7 +63,6 @@ func initHTTPClient(cfg *config.Config) {
|
|||
logWarning("use Auto to Run HTTP Client")
|
||||
fmt.Println("use Auto to Run HTTP Client")
|
||||
tr = &http.Transport{
|
||||
//MaxIdleConns: 160,
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
WriteBufferSize: 32 * 1024, // 32KB
|
||||
ReadBufferSize: 32 * 1024, // 32KB
|
||||
|
|
@ -87,23 +85,11 @@ func initHTTPClient(cfg *config.Config) {
|
|||
|
||||
func initGitHTTPClient(cfg *config.Config) {
|
||||
|
||||
var proTolcols = new(http.Protocols)
|
||||
proTolcols.SetHTTP1(true)
|
||||
proTolcols.SetHTTP2(true)
|
||||
proTolcols.SetUnencryptedHTTP2(true)
|
||||
if cfg.GitClone.ForceH2C {
|
||||
proTolcols.SetHTTP1(false)
|
||||
proTolcols.SetHTTP2(false)
|
||||
proTolcols.SetUnencryptedHTTP2(true)
|
||||
}
|
||||
if cfg.Httpc.Mode == "auto" {
|
||||
|
||||
gittr = &http.Transport{
|
||||
//MaxIdleConns: 160,
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
WriteBufferSize: 32 * 1024, // 32KB
|
||||
ReadBufferSize: 32 * 1024, // 32KB
|
||||
Protocols: proTolcols,
|
||||
}
|
||||
} else if cfg.Httpc.Mode == "advanced" {
|
||||
gittr = &http.Transport{
|
||||
|
|
@ -112,7 +98,6 @@ func initGitHTTPClient(cfg *config.Config) {
|
|||
MaxIdleConnsPerHost: cfg.Httpc.MaxIdleConnsPerHost,
|
||||
WriteBufferSize: 32 * 1024, // 32KB
|
||||
ReadBufferSize: 32 * 1024, // 32KB
|
||||
Protocols: proTolcols,
|
||||
}
|
||||
} else {
|
||||
// 错误的模式
|
||||
|
|
@ -130,14 +115,39 @@ func initGitHTTPClient(cfg *config.Config) {
|
|||
if cfg.Outbound.Enabled {
|
||||
initTransport(cfg, gittr)
|
||||
}
|
||||
if cfg.Server.Debug {
|
||||
if cfg.Server.Debug && cfg.GitClone.ForceH2C {
|
||||
gitclient = httpc.New(
|
||||
httpc.WithTransport(gittr),
|
||||
httpc.WithDumpLog(),
|
||||
httpc.WithProtocols(httpc.ProtocolsConfig{
|
||||
ForceH2C: true,
|
||||
}),
|
||||
)
|
||||
} else if !cfg.Server.Debug && cfg.GitClone.ForceH2C {
|
||||
gitclient = httpc.New(
|
||||
httpc.WithTransport(gittr),
|
||||
httpc.WithProtocols(httpc.ProtocolsConfig{
|
||||
ForceH2C: true,
|
||||
}),
|
||||
)
|
||||
} else if cfg.Server.Debug && !cfg.GitClone.ForceH2C {
|
||||
gitclient = httpc.New(
|
||||
httpc.WithTransport(gittr),
|
||||
httpc.WithDumpLog(),
|
||||
httpc.WithProtocols(httpc.ProtocolsConfig{
|
||||
Http1: true,
|
||||
Http2: true,
|
||||
Http2_Cleartext: true,
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
gitclient = httpc.New(
|
||||
httpc.WithTransport(gittr),
|
||||
httpc.WithProtocols(httpc.ProtocolsConfig{
|
||||
Http1: true,
|
||||
Http2: true,
|
||||
Http2_Cleartext: true,
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,6 +243,8 @@ func extractParts(rawURL string) (string, string, string, url.Values, error) {
|
|||
return repoOwner, repoName, remainingPath, queryParams, nil
|
||||
}
|
||||
|
||||
var urlPattern = regexp.MustCompile(`https?://[^\s'"]+`)
|
||||
|
||||
// processLinks 处理链接,返回包含处理后数据的 io.Reader
|
||||
func processLinks(input io.Reader, compress string, host string, cfg *config.Config) (readerOut io.Reader, written int64, err error) {
|
||||
pipeReader, pipeWriter := io.Pipe() // 创建 io.Pipe
|
||||
|
|
@ -315,7 +317,6 @@ func processLinks(input io.Reader, compress string, host string, cfg *config.Con
|
|||
}()
|
||||
|
||||
// 使用正则表达式匹配 http 和 https 链接
|
||||
urlPattern := regexp.MustCompile(`https?://[^\s'"]+`)
|
||||
for {
|
||||
line, readErr := bufReader.ReadString('\n')
|
||||
if readErr != nil {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ func setRequestHeaders(c *app.RequestContext, req *http.Request) {
|
|||
})
|
||||
}
|
||||
|
||||
// removeWSHeader removes the "Upgrade" and "Connection" headers from the given
|
||||
// Request, which are added by the client when it wants to upgrade the
|
||||
// connection to a WebSocket connection.
|
||||
func removeWSHeader(req *http.Request) {
|
||||
req.Header.Del("Upgrade")
|
||||
req.Header.Del("Connection")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue