Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
542fffb289 | ||
|
|
35b70fadca | ||
|
|
91c3ad7fd8 | ||
|
|
97b1f69f99 | ||
|
|
fd7e270db4 | ||
|
|
cf5ae0d184 | ||
|
|
ed826d2a1c | ||
|
|
0008366e07 | ||
|
|
c13dd9082b | ||
|
|
e0cbfed1e7 | ||
|
|
1b06260a14 | ||
|
|
8ab622d149 | ||
|
|
96c30889f4 | ||
|
|
bbb108689a | ||
|
|
41395b1d72 | ||
|
|
bd8412f157 | ||
|
|
d2a0177015 | ||
|
|
bf75e62eb2 | ||
|
|
a5bf7686bd |
53
CHANGELOG.md
53
CHANGELOG.md
@@ -1,5 +1,58 @@
|
|||||||
# 更新日志
|
# 更新日志
|
||||||
|
|
||||||
|
3.5.6 - 2025-06-15
|
||||||
|
---
|
||||||
|
- FIX: 修正blob重写的生成问题
|
||||||
|
- CHANGE: 改进302重定向逻辑
|
||||||
|
|
||||||
|
25w48c - 2025-06-15
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v3.5.6预发布版本,请勿在生产环境中使用;
|
||||||
|
- CHANGE: 加入内部301处理
|
||||||
|
|
||||||
|
25w48b - 2025-06-15
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v3.5.6预发布版本,请勿在生产环境中使用;
|
||||||
|
- FIX: 修正blob重写的生成问题
|
||||||
|
- CHANGE: 验证与连接释放相关的修正
|
||||||
|
|
||||||
|
25w48a - 2025-06-14
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v3.5.6预发布版本,请勿在生产环境中使用;
|
||||||
|
- CHANGE: 测试302重定向逻辑
|
||||||
|
|
||||||
|
3.5.5 - 2025-06-14
|
||||||
|
---
|
||||||
|
- CHANGE: 修正新匹配器的覆盖问题, 同时增加test的覆盖
|
||||||
|
|
||||||
|
25w47a - 2025-06-14
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v3.5.5预发布版本,请勿在生产环境中使用;
|
||||||
|
- CHANGE: 修正新匹配器的覆盖问题, 同时增加test的覆盖
|
||||||
|
|
||||||
|
3.5.4 - 2025-06-14
|
||||||
|
---
|
||||||
|
- CHANGE: 移植来自于[GHProxy-Touka](https://github.com/WJQSERVER-STUDIO/ghproxy-touka)的blob处理逻辑与302处理逻辑
|
||||||
|
|
||||||
|
25w46c - 2025-06-14
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v3.5.4预发布版本,请勿在生产环境中使用;
|
||||||
|
- CHANGE: 移植来自于[GHProxy-Touka](https://github.com/WJQSERVER-STUDIO/ghproxy-touka)的blob处理逻辑与302处理逻辑
|
||||||
|
|
||||||
|
25w46b - 2025-06-14
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v3.5.4预发布版本,请勿在生产环境中使用;
|
||||||
|
- CHANGE: 修改关闭行为以测试问题
|
||||||
|
|
||||||
|
25w46a - 2025-06-14
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v3.5.4预发布版本,请勿在生产环境中使用;
|
||||||
|
- CHANGE: 修改payload行为以测试问题
|
||||||
|
|
||||||
|
3.5.3 - 2025-06-13
|
||||||
|
---
|
||||||
|
- CHANGE: 显式配置`WithStreamBody(true)`
|
||||||
|
|
||||||
3.5.2 - 2025-06-11
|
3.5.2 - 2025-06-11
|
||||||
---
|
---
|
||||||
- CHANGE: 加入MPL 2.0许可证, 项目转为双重许可
|
- CHANGE: 加入MPL 2.0许可证, 项目转为双重许可
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
25w45a
|
25w48c
|
||||||
@@ -109,7 +109,7 @@ wget -O install-dev.sh https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghprox
|
|||||||
|
|
||||||
## LICENSE
|
## LICENSE
|
||||||
|
|
||||||
v3.5.2开始, 本项目使用 [WJQserver Studio License 2.0](https://wjqserver-studio.github.io/LICENSE/LICENSE.html) 和 [Mozilla Public License Version 2.0](https://mozilla.org/MPL/2.0/) 双重许可, 您可从中选择一个使用
|
v3.5.2开始, 本项目使用 [WJQserver Studio License 2.1](https://wjqserver-studio.github.io/LICENSE/LICENSE.html) 和 [Mozilla Public License Version 2.0](https://mozilla.org/MPL/2.0/) 双重许可, 您可从中选择一个使用
|
||||||
|
|
||||||
前端位于单独仓库中, 且各个主题均存在各自的许可证, 本项目许可证并不包括前端
|
前端位于单独仓库中, 且各个主题均存在各自的许可证, 本项目许可证并不包括前端
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type Config struct {
|
|||||||
host = "0.0.0.0"
|
host = "0.0.0.0"
|
||||||
port = 8080
|
port = 8080
|
||||||
netlib = "netpoll" # "netpoll" / "std" "standard" "net/http" "net"
|
netlib = "netpoll" # "netpoll" / "std" "standard" "net/http" "net"
|
||||||
|
goPoolSize = 1024
|
||||||
sizeLimit = 125 # MB
|
sizeLimit = 125 # MB
|
||||||
memLimit = 0 # MB
|
memLimit = 0 # MB
|
||||||
H2C = true
|
H2C = true
|
||||||
@@ -38,6 +39,7 @@ type ServerConfig struct {
|
|||||||
Host string `toml:"host"`
|
Host string `toml:"host"`
|
||||||
NetLib string `toml:"netlib"`
|
NetLib string `toml:"netlib"`
|
||||||
SenseClientDisconnection bool `toml:"senseClientDisconnection"`
|
SenseClientDisconnection bool `toml:"senseClientDisconnection"`
|
||||||
|
GoPoolSize int `toml:"goPoolSize"`
|
||||||
SizeLimit int `toml:"sizeLimit"`
|
SizeLimit int `toml:"sizeLimit"`
|
||||||
MemLimit int64 `toml:"memLimit"`
|
MemLimit int64 `toml:"memLimit"`
|
||||||
H2C bool `toml:"H2C"`
|
H2C bool `toml:"H2C"`
|
||||||
@@ -224,14 +226,15 @@ func FileExists(filename string) bool {
|
|||||||
func DefaultConfig() *Config {
|
func DefaultConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
Server: ServerConfig{
|
Server: ServerConfig{
|
||||||
Port: 8080,
|
Port: 8080,
|
||||||
Host: "0.0.0.0",
|
Host: "0.0.0.0",
|
||||||
NetLib: "netpoll",
|
NetLib: "netpoll",
|
||||||
SizeLimit: 125,
|
GoPoolSize: 1024,
|
||||||
MemLimit: 0,
|
SizeLimit: 125,
|
||||||
H2C: true,
|
MemLimit: 0,
|
||||||
Cors: "*",
|
H2C: true,
|
||||||
Debug: false,
|
Cors: "*",
|
||||||
|
Debug: false,
|
||||||
},
|
},
|
||||||
Httpc: HttpcConfig{
|
Httpc: HttpcConfig{
|
||||||
Mode: "auto",
|
Mode: "auto",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ host = "0.0.0.0"
|
|||||||
port = 8080
|
port = 8080
|
||||||
netlib = "netpoll" # "netpoll" / "std" "standard" "net/http" "net"
|
netlib = "netpoll" # "netpoll" / "std" "standard" "net/http" "net"
|
||||||
senseClientDisconnection = false
|
senseClientDisconnection = false
|
||||||
|
goPoolSize = 1024
|
||||||
sizeLimit = 125 # MB
|
sizeLimit = 125 # MB
|
||||||
memLimit = 0 # MB
|
memLimit = 0 # MB
|
||||||
H2C = true
|
H2C = true
|
||||||
|
|||||||
7
go.mod
7
go.mod
@@ -5,8 +5,8 @@ go 1.24.3
|
|||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.5.0
|
github.com/BurntSushi/toml v1.5.0
|
||||||
github.com/WJQSERVER-STUDIO/httpc v0.7.0
|
github.com/WJQSERVER-STUDIO/httpc v0.7.0
|
||||||
github.com/WJQSERVER-STUDIO/logger v1.7.3
|
github.com/WJQSERVER-STUDIO/logger v1.8.0
|
||||||
github.com/cloudwego/hertz v0.10.0
|
github.com/cloudwego/hertz v0.10.1-0.20250611091639-3dde619f5598
|
||||||
github.com/hertz-contrib/http2 v0.1.8
|
github.com/hertz-contrib/http2 v0.1.8
|
||||||
golang.org/x/net v0.41.0
|
golang.org/x/net v0.41.0
|
||||||
golang.org/x/time v0.12.0
|
golang.org/x/time v0.12.0
|
||||||
@@ -44,6 +44,3 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/nyaruka/phonenumbers => github.com/nyaruka/phonenumbers v1.6.1 // 1.6.3 has reflect leaking
|
replace github.com/nyaruka/phonenumbers => github.com/nyaruka/phonenumbers v1.6.1 // 1.6.3 has reflect leaking
|
||||||
|
|
||||||
//replace github.com/WJQSERVER-STUDIO/httpc v0.5.1 => /data/github/WJQSERVER-STUDIO/httpc
|
|
||||||
//replace github.com/WJQSERVER-STUDIO/logger v1.6.0 => /data/github/WJQSERVER-STUDIO/logger
|
|
||||||
|
|||||||
22
go.sum
22
go.sum
@@ -6,14 +6,10 @@ github.com/WJQSERVER-STUDIO/go-utils/limitreader v0.0.2 h1:8bBkKk6E2Zr+I5szL7gyc
|
|||||||
github.com/WJQSERVER-STUDIO/go-utils/limitreader v0.0.2/go.mod h1:yPX8xuZH+py7eLJwOYj3VVI/4/Yuy5+x8Mhq8qezcPg=
|
github.com/WJQSERVER-STUDIO/go-utils/limitreader v0.0.2/go.mod h1:yPX8xuZH+py7eLJwOYj3VVI/4/Yuy5+x8Mhq8qezcPg=
|
||||||
github.com/WJQSERVER-STUDIO/go-utils/log v0.0.3 h1:t6nyLhmo9pSfVHm1Wu1WyLsTpXFSjSpQtVKqEDpiZ5Q=
|
github.com/WJQSERVER-STUDIO/go-utils/log v0.0.3 h1:t6nyLhmo9pSfVHm1Wu1WyLsTpXFSjSpQtVKqEDpiZ5Q=
|
||||||
github.com/WJQSERVER-STUDIO/go-utils/log v0.0.3/go.mod h1:j9Q+xnwpOfve7/uJnZ2izRQw6NNoXjvJHz7vUQAaLZE=
|
github.com/WJQSERVER-STUDIO/go-utils/log v0.0.3/go.mod h1:j9Q+xnwpOfve7/uJnZ2izRQw6NNoXjvJHz7vUQAaLZE=
|
||||||
github.com/WJQSERVER-STUDIO/httpc v0.5.1 h1:+TKCPYBuj7PAHuiduGCGAqsHAa4QtsUfoVwRN777q64=
|
|
||||||
github.com/WJQSERVER-STUDIO/httpc v0.5.1/go.mod h1:M7KNUZjjhCkzzcg9lBPs9YfkImI+7vqjAyjdA19+joE=
|
|
||||||
github.com/WJQSERVER-STUDIO/httpc v0.6.0 h1:GXKc6BNGn5ALdDLkCsM+mP24jyi1S9QBLL2XQ1a2sPM=
|
|
||||||
github.com/WJQSERVER-STUDIO/httpc v0.6.0/go.mod h1:M7KNUZjjhCkzzcg9lBPs9YfkImI+7vqjAyjdA19+joE=
|
|
||||||
github.com/WJQSERVER-STUDIO/httpc v0.7.0 h1:iHhqlxppJBjlmvsIjvLZKRbWXqSdbeSGGofjHGmqGJc=
|
github.com/WJQSERVER-STUDIO/httpc v0.7.0 h1:iHhqlxppJBjlmvsIjvLZKRbWXqSdbeSGGofjHGmqGJc=
|
||||||
github.com/WJQSERVER-STUDIO/httpc v0.7.0/go.mod h1:M7KNUZjjhCkzzcg9lBPs9YfkImI+7vqjAyjdA19+joE=
|
github.com/WJQSERVER-STUDIO/httpc v0.7.0/go.mod h1:M7KNUZjjhCkzzcg9lBPs9YfkImI+7vqjAyjdA19+joE=
|
||||||
github.com/WJQSERVER-STUDIO/logger v1.7.3 h1:XoFJ1nBcZKyMvP4v0MZv5jL2q7IkAF7yfXgwyB3MLP4=
|
github.com/WJQSERVER-STUDIO/logger v1.8.0 h1:AQ3Qe2kxiqpuOoDlRzseGP6u4LAaJc+ng4l8P+CK7Co=
|
||||||
github.com/WJQSERVER-STUDIO/logger v1.7.3/go.mod h1:yzXPtot0OvR1gzx4+rlFrv/sccUpz0gIXVBwUx3H7fM=
|
github.com/WJQSERVER-STUDIO/logger v1.8.0/go.mod h1:yzXPtot0OvR1gzx4+rlFrv/sccUpz0gIXVBwUx3H7fM=
|
||||||
github.com/bytedance/gopkg v0.1.1/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
github.com/bytedance/gopkg v0.1.1/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||||
github.com/bytedance/gopkg v0.1.2 h1:8o2feYuxknDpN+O7kPwvSXfMEKfYvJYiA2K7aonoMEQ=
|
github.com/bytedance/gopkg v0.1.2 h1:8o2feYuxknDpN+O7kPwvSXfMEKfYvJYiA2K7aonoMEQ=
|
||||||
github.com/bytedance/gopkg v0.1.2/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
github.com/bytedance/gopkg v0.1.2/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||||
@@ -28,8 +24,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/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 h1:EoQiCG4sTonTPHxOGE0VlQs+sQR+Hsi2uN0qqwu8O50=
|
||||||
github.com/cloudwego/gopkg v0.1.4/go.mod h1:FQuXsRWRsSqJLsMVd5SYzp8/Z1y5gXKnVvRrWUOsCMI=
|
github.com/cloudwego/gopkg v0.1.4/go.mod h1:FQuXsRWRsSqJLsMVd5SYzp8/Z1y5gXKnVvRrWUOsCMI=
|
||||||
github.com/cloudwego/hertz v0.10.0 h1:V0vmBaLdQPlgL6w2TA6PZL1g6SGgQznFx6vqxWdCcKw=
|
github.com/cloudwego/hertz v0.10.1-0.20250611091639-3dde619f5598 h1:8tVol3hNJS7+7f7yQIkP57tZMzUV3fOhn6pQ7t4R06k=
|
||||||
github.com/cloudwego/hertz v0.10.0/go.mod h1:lRBohmcDkGx5TLK6QKFGdzJ6n3IXqGueHsOiXcYgXA4=
|
github.com/cloudwego/hertz v0.10.1-0.20250611091639-3dde619f5598/go.mod h1:lRBohmcDkGx5TLK6QKFGdzJ6n3IXqGueHsOiXcYgXA4=
|
||||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
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 h1:bDrxQaNfijRI1zyGgXHQoE/nYegL0nr+ijO1Norelc4=
|
||||||
github.com/cloudwego/netpoll v0.7.0/go.mod h1:PI+YrmyS7cIr0+SD4seJz3Eo3ckkXdu2ZVKBLhURLNU=
|
github.com/cloudwego/netpoll v0.7.0/go.mod h1:PI+YrmyS7cIr0+SD4seJz3Eo3ckkXdu2ZVKBLhURLNU=
|
||||||
@@ -91,16 +87,12 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC
|
|||||||
github.com/wjqserver/modembed v0.0.1 h1:8ZDz7t9M5DLrUFlYgBUUmrMzxWsZPmHvOazkr/T2jEs=
|
github.com/wjqserver/modembed v0.0.1 h1:8ZDz7t9M5DLrUFlYgBUUmrMzxWsZPmHvOazkr/T2jEs=
|
||||||
github.com/wjqserver/modembed v0.0.1/go.mod h1:sYbQJMAjSBsdYQrUsuHY380XXE1CuRh8g9yyCztTXOQ=
|
github.com/wjqserver/modembed v0.0.1/go.mod h1:sYbQJMAjSBsdYQrUsuHY380XXE1CuRh8g9yyCztTXOQ=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU=
|
|
||||||
golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
|
||||||
golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc=
|
golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc=
|
||||||
golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
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.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b h1:QoALfVG9rhQ/M7vYDScfPdWjGL9dlsVVM5VGh7aKoAA=
|
|
||||||
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
|
||||||
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 h1:bsqhLWFR6G6xiQcb+JoGqdKdRU6WzPWmK8E0jxTjzo4=
|
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 h1:bsqhLWFR6G6xiQcb+JoGqdKdRU6WzPWmK8E0jxTjzo4=
|
||||||
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
@@ -112,8 +104,6 @@ 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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
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.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
|
||||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
|
||||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -143,12 +133,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
|
||||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
|
||||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
|
||||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
|
||||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|||||||
18
main.go
18
main.go
@@ -430,12 +430,16 @@ func main() {
|
|||||||
server.WithH2C(true),
|
server.WithH2C(true),
|
||||||
server.WithHostPorts(addr),
|
server.WithHostPorts(addr),
|
||||||
server.WithTransport(standard.NewTransporter),
|
server.WithTransport(standard.NewTransporter),
|
||||||
|
server.WithStreamBody(true),
|
||||||
|
server.WithIdleTimeout(30*time.Second),
|
||||||
)
|
)
|
||||||
r.AddProtocol("h2", factory.NewServerFactory())
|
r.AddProtocol("h2", factory.NewServerFactory())
|
||||||
} else {
|
} else {
|
||||||
r = server.New(
|
r = server.New(
|
||||||
server.WithHostPorts(addr),
|
server.WithHostPorts(addr),
|
||||||
server.WithTransport(standard.NewTransporter),
|
server.WithTransport(standard.NewTransporter),
|
||||||
|
server.WithStreamBody(true),
|
||||||
|
server.WithIdleTimeout(30*time.Second),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if cfg.Server.NetLib == "netpoll" || cfg.Server.NetLib == "" {
|
} else if cfg.Server.NetLib == "netpoll" || cfg.Server.NetLib == "" {
|
||||||
@@ -444,12 +448,16 @@ func main() {
|
|||||||
server.WithH2C(true),
|
server.WithH2C(true),
|
||||||
server.WithHostPorts(addr),
|
server.WithHostPorts(addr),
|
||||||
server.WithSenseClientDisconnection(cfg.Server.SenseClientDisconnection),
|
server.WithSenseClientDisconnection(cfg.Server.SenseClientDisconnection),
|
||||||
|
server.WithStreamBody(true),
|
||||||
|
server.WithIdleTimeout(30*time.Second),
|
||||||
)
|
)
|
||||||
r.AddProtocol("h2", factory.NewServerFactory())
|
r.AddProtocol("h2", factory.NewServerFactory())
|
||||||
} else {
|
} else {
|
||||||
r = server.New(
|
r = server.New(
|
||||||
server.WithHostPorts(addr),
|
server.WithHostPorts(addr),
|
||||||
server.WithSenseClientDisconnection(cfg.Server.SenseClientDisconnection),
|
server.WithSenseClientDisconnection(cfg.Server.SenseClientDisconnection),
|
||||||
|
server.WithStreamBody(true),
|
||||||
|
server.WithIdleTimeout(30*time.Second),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -458,6 +466,14 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if cfg.Server.GoPoolSize > 0 {
|
||||||
|
gopool.SetCap(int32(cfg.Server.GoPoolSize))
|
||||||
|
} else {
|
||||||
|
gopool.SetCap(1024)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
r.Use(recovery.Recovery()) // Recovery中间件
|
r.Use(recovery.Recovery()) // Recovery中间件
|
||||||
r.Use(loggin.Middleware()) // log中间件
|
r.Use(loggin.Middleware()) // log中间件
|
||||||
r.Use(viaHeader())
|
r.Use(viaHeader())
|
||||||
@@ -503,7 +519,7 @@ func main() {
|
|||||||
proxy.NoRouteHandler(cfg, limiter, iplimiter)(ctx, c)
|
proxy.NoRouteHandler(cfg, limiter, iplimiter)(ctx, c)
|
||||||
})
|
})
|
||||||
|
|
||||||
r.GET("/api.github.com/repos/:user/:repo/*filepath", func(ctx context.Context, c *app.RequestContext) {
|
r.Any("/api.github.com/repos/:user/:repo/*filepath", func(ctx context.Context, c *app.RequestContext) {
|
||||||
c.Set("matcher", "api")
|
c.Set("matcher", "api")
|
||||||
proxy.RoutingHandler(cfg, limiter, iplimiter)(ctx, c)
|
proxy.RoutingHandler(cfg, limiter, iplimiter)(ctx, c)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -23,16 +23,18 @@ func ChunkedProxyRequest(ctx context.Context, c *app.RequestContext, u string, c
|
|||||||
go func() {
|
go func() {
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
if resp != nil && resp.Body != nil {
|
if resp != nil && resp.Body != nil {
|
||||||
resp.Body.Close()
|
err := resp.Body.Close()
|
||||||
}
|
if err != nil {
|
||||||
if req != nil {
|
logError("Failed to close response body: %v", err)
|
||||||
req.Body.Close()
|
}
|
||||||
}
|
}
|
||||||
|
c.Abort()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
rb := client.NewRequestBuilder(string(c.Request.Method()), u)
|
rb := client.NewRequestBuilder(string(c.Request.Method()), u)
|
||||||
rb.NoDefaultHeaders()
|
rb.NoDefaultHeaders()
|
||||||
rb.SetBody(c.Request.BodyStream())
|
//rb.SetBody(bytes.NewBuffer(c.Request.Body()))
|
||||||
|
rb.SetBody(c.RequestBodyStream())
|
||||||
rb.WithContext(ctx)
|
rb.WithContext(ctx)
|
||||||
|
|
||||||
req, err = rb.Build()
|
req, err = rb.Build()
|
||||||
@@ -56,6 +58,21 @@ func ChunkedProxyRequest(ctx context.Context, c *app.RequestContext, u string, c
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理302情况
|
||||||
|
if resp.StatusCode == 302 || resp.StatusCode == 301 {
|
||||||
|
finalURL := resp.Header.Get("Location")
|
||||||
|
if finalURL != "" {
|
||||||
|
err = resp.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
logError("Failed to close response body: %v", err)
|
||||||
|
}
|
||||||
|
c.Request.Header.Del("Referer")
|
||||||
|
logInfo("Internal Redirecting to %s", finalURL)
|
||||||
|
ChunkedProxyRequest(ctx, c, finalURL, cfg, matcher)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
bodySize int
|
bodySize int
|
||||||
contentLength string
|
contentLength string
|
||||||
@@ -136,6 +153,7 @@ func ChunkedProxyRequest(ctx context.Context, c *app.RequestContext, u string, c
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.SetBodyStream(bodyReader, -1)
|
c.SetBodyStream(bodyReader, -1)
|
||||||
|
bodyReader.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,15 +17,16 @@ func GitReq(ctx context.Context, c *app.RequestContext, u string, cfg *config.Co
|
|||||||
var (
|
var (
|
||||||
req *http.Request
|
req *http.Request
|
||||||
resp *http.Response
|
resp *http.Response
|
||||||
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
if resp != nil && resp.Body != nil {
|
if resp != nil && resp.Body != nil {
|
||||||
resp.Body.Close()
|
err = resp.Body.Close()
|
||||||
}
|
if err != nil {
|
||||||
if req != nil {
|
logError("Failed to close response body: %v", err)
|
||||||
req.Body.Close()
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ func GitReq(ctx context.Context, c *app.RequestContext, u string, cfg *config.Co
|
|||||||
rb.SetBody(reqBodyReader)
|
rb.SetBody(reqBodyReader)
|
||||||
rb.WithContext(ctx)
|
rb.WithContext(ctx)
|
||||||
|
|
||||||
req, err := rb.Build()
|
req, err = rb.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HandleError(c, fmt.Sprintf("Failed to create request: %v", err))
|
HandleError(c, fmt.Sprintf("Failed to create request: %v", err))
|
||||||
return
|
return
|
||||||
@@ -143,4 +144,5 @@ func GitReq(ctx context.Context, c *app.RequestContext, u string, cfg *config.Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.SetBodyStream(bodyReader, -1)
|
c.SetBodyStream(bodyReader, -1)
|
||||||
|
bodyReader.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,10 @@ func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter, iplimiter *ra
|
|||||||
|
|
||||||
// 处理blob/raw路径
|
// 处理blob/raw路径
|
||||||
if matcher == "blob" {
|
if matcher == "blob" {
|
||||||
rawPath = strings.Replace(rawPath, "/blob/", "/raw/", 1)
|
rawPath = rawPath[18:]
|
||||||
|
rawPath = "https://raw.githubusercontent.com" + rawPath
|
||||||
|
rawPath = strings.Replace(rawPath, "/blob/", "/", 1)
|
||||||
|
matcher = "raw"
|
||||||
}
|
}
|
||||||
|
|
||||||
logDebug("Matched: %v", matcher)
|
logDebug("Matched: %v", matcher)
|
||||||
|
|||||||
@@ -10,14 +10,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
githubPrefix = "https://github.com/"
|
githubPrefix = "https://github.com/"
|
||||||
rawPrefix = "https://raw.githubusercontent.com/"
|
rawPrefix = "https://raw.githubusercontent.com/"
|
||||||
gistPrefix = "https://gist.github.com/"
|
gistPrefix = "https://gist.github.com/"
|
||||||
apiPrefix = "https://api.github.com/"
|
gistContentPrefix = "https://gist.githubusercontent.com/"
|
||||||
githubPrefixLen int
|
apiPrefix = "https://api.github.com/"
|
||||||
rawPrefixLen int
|
githubPrefixLen int
|
||||||
gistPrefixLen int
|
rawPrefixLen int
|
||||||
apiPrefixLen int
|
gistPrefixLen int
|
||||||
|
gistContentPrefixLen int
|
||||||
|
apiPrefixLen int
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -25,6 +27,7 @@ func init() {
|
|||||||
rawPrefixLen = len(rawPrefix)
|
rawPrefixLen = len(rawPrefix)
|
||||||
gistPrefixLen = len(gistPrefix)
|
gistPrefixLen = len(gistPrefix)
|
||||||
apiPrefixLen = len(apiPrefix)
|
apiPrefixLen = len(apiPrefix)
|
||||||
|
gistContentPrefixLen = len(gistContentPrefix)
|
||||||
//log.Printf("githubPrefixLen: %d, rawPrefixLen: %d, gistPrefixLen: %d, apiPrefixLen: %d", githubPrefixLen, rawPrefixLen, gistPrefixLen, apiPrefixLen)
|
//log.Printf("githubPrefixLen: %d, rawPrefixLen: %d, gistPrefixLen: %d, apiPrefixLen: %d", githubPrefixLen, rawPrefixLen, gistPrefixLen, apiPrefixLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +117,23 @@ func Matcher(rawPath string, cfg *config.Config) (string, string, string, *GHPro
|
|||||||
return user, "", "gist", nil
|
return user, "", "gist", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 匹配 "https://gist.githubusercontent.com/"
|
||||||
|
if strings.HasPrefix(rawPath, gistContentPrefix) {
|
||||||
|
remaining := rawPath[gistContentPrefixLen:]
|
||||||
|
i := strings.IndexByte(remaining, '/')
|
||||||
|
if i <= 0 {
|
||||||
|
// case: https://gist.githubusercontent.com/user
|
||||||
|
// 这种情况下, gist_id 缺失, 但我们仍然可以认为 user 是有效的
|
||||||
|
if len(remaining) > 0 {
|
||||||
|
return remaining, "", "gist", nil
|
||||||
|
}
|
||||||
|
return "", "", "", NewErrorWithStatusLookup(400, "malformed gist url: missing user")
|
||||||
|
}
|
||||||
|
// case: https://gist.githubusercontent.com/user/gist_id...
|
||||||
|
user := remaining[:i]
|
||||||
|
return user, "", "gist", nil
|
||||||
|
}
|
||||||
|
|
||||||
// 匹配 "https://api.github.com/"
|
// 匹配 "https://api.github.com/"
|
||||||
if strings.HasPrefix(rawPath, apiPrefix) {
|
if strings.HasPrefix(rawPath, apiPrefix) {
|
||||||
if !cfg.Auth.ForceAllowApi && (cfg.Auth.Method != "header" || !cfg.Auth.Enabled) {
|
if !cfg.Auth.ForceAllowApi && (cfg.Auth.Method != "header" || !cfg.Auth.Enabled) {
|
||||||
|
|||||||
@@ -87,6 +87,12 @@ func TestMatcher_Compatibility(t *testing.T) {
|
|||||||
config: cfgWithAuth,
|
config: cfgWithAuth,
|
||||||
expectedUser: "user", expectedRepo: "", expectedMatcher: "gist",
|
expectedUser: "user", expectedRepo: "", expectedMatcher: "gist",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Gist UserContent Path",
|
||||||
|
rawPath: "https://gist.githubusercontent.com/user/abcdef1234567890",
|
||||||
|
config: cfgWithAuth,
|
||||||
|
expectedUser: "user", expectedRepo: "", expectedMatcher: "gist",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "API Repos Path (with Auth)",
|
name: "API Repos Path (with Auth)",
|
||||||
rawPath: "https://api.github.com/repos/owner/repo/pulls",
|
rawPath: "https://api.github.com/repos/owner/repo/pulls",
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// copyHeader 将所有头部从 src 复制到 dst。
|
||||||
|
// 对于多值头部,它会为每个值调用 Add,从而保留所有值。
|
||||||
|
func copyHeader(dst, src http.Header) {
|
||||||
|
for k, vv := range src {
|
||||||
|
for _, v := range vv {
|
||||||
|
dst.Add(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func setRequestHeaders(c *app.RequestContext, req *http.Request, cfg *config.Config, matcher string) {
|
func setRequestHeaders(c *app.RequestContext, req *http.Request, cfg *config.Config, matcher string) {
|
||||||
if matcher == "raw" && cfg.Httpc.UseCustomRawHeaders {
|
if matcher == "raw" && cfg.Httpc.UseCustomRawHeaders {
|
||||||
// 使用预定义Header
|
// 使用预定义Header
|
||||||
@@ -56,20 +66,23 @@ func setRequestHeaders(c *app.RequestContext, req *http.Request, cfg *config.Con
|
|||||||
req.Header.Set(key, value)
|
req.Header.Set(key, value)
|
||||||
}
|
}
|
||||||
} else if matcher == "clone" {
|
} else if matcher == "clone" {
|
||||||
|
|
||||||
c.Request.Header.VisitAll(func(key, value []byte) {
|
c.Request.Header.VisitAll(func(key, value []byte) {
|
||||||
headerKey := string(key)
|
headerKey := string(key)
|
||||||
headerValue := string(value)
|
headerValue := string(value)
|
||||||
if _, shouldRemove := cloneHeadersToRemove[headerKey]; !shouldRemove {
|
req.Header.Set(headerKey, headerValue)
|
||||||
req.Header.Set(headerKey, headerValue)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
for key := range cloneHeadersToRemove {
|
||||||
|
req.Header.Del(key)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
c.Request.Header.VisitAll(func(key, value []byte) {
|
c.Request.Header.VisitAll(func(key, value []byte) {
|
||||||
headerKey := string(key)
|
headerKey := string(key)
|
||||||
headerValue := string(value)
|
headerValue := string(value)
|
||||||
if _, shouldRemove := reqHeadersToRemove[headerKey]; !shouldRemove {
|
req.Header.Set(headerKey, headerValue)
|
||||||
req.Header.Set(headerKey, headerValue)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
for key := range reqHeadersToRemove {
|
||||||
|
req.Header.Del(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,13 @@ func RoutingHandler(cfg *config.Config, limiter *rate.RateLimiter, iplimiter *ra
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理blob/raw路径
|
||||||
// 处理blob/raw路径
|
// 处理blob/raw路径
|
||||||
if matcher == "blob" {
|
if matcher == "blob" {
|
||||||
rawPath = strings.Replace(rawPath, "/blob/", "/raw/", 1)
|
rawPath = rawPath[10:]
|
||||||
|
rawPath = "raw.githubusercontent.com" + rawPath
|
||||||
|
rawPath = strings.Replace(rawPath, "/blob/", "/", 1)
|
||||||
|
matcher = "raw"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 为rawpath加入https:// 头
|
// 为rawpath加入https:// 头
|
||||||
|
|||||||
Reference in New Issue
Block a user