Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
bb7bfb69
Unverified
Commit
bb7bfb69
authored
Dec 18, 2025
by
Wesley Liddick
Committed by
GitHub
Dec 18, 2025
Browse files
Merge pull request #1 from 7836246/fix/concurrent-proxy-race-condition
fix: 修复并发请求时共享httpClient.Transport导致的竞态条件
parents
b66f97c1
2392e7cf
Changes
1
Show whitespace changes
Inline
Side-by-side
backend/internal/service/gateway_service.go
View file @
bb7bfb69
...
@@ -418,13 +418,19 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *m
...
@@ -418,13 +418,19 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *m
}
}
// 构建上游请求
// 构建上游请求
upstreamRe
q
,
err
:=
s
.
buildUpstreamRequest
(
ctx
,
c
,
account
,
body
,
token
,
tokenType
)
upstreamRe
sult
,
err
:=
s
.
buildUpstreamRequest
(
ctx
,
c
,
account
,
body
,
token
,
tokenType
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
// 选择使用的client:如果有代理则使用独立的client,否则使用共享的httpClient
httpClient
:=
s
.
httpClient
if
upstreamResult
.
Client
!=
nil
{
httpClient
=
upstreamResult
.
Client
}
// 发送请求
// 发送请求
resp
,
err
:=
s
.
httpClient
.
Do
(
upstreamRe
q
)
resp
,
err
:=
httpClient
.
Do
(
upstreamRe
sult
.
Request
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"upstream request failed: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"upstream request failed: %w"
,
err
)
}
}
...
@@ -437,11 +443,16 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *m
...
@@ -437,11 +443,16 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *m
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"token refresh failed: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"token refresh failed: %w"
,
err
)
}
}
upstreamRe
q
,
err
=
s
.
buildUpstreamRequest
(
ctx
,
c
,
account
,
body
,
token
,
tokenType
)
upstreamRe
sult
,
err
=
s
.
buildUpstreamRequest
(
ctx
,
c
,
account
,
body
,
token
,
tokenType
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
resp
,
err
=
s
.
httpClient
.
Do
(
upstreamReq
)
// 重试时也需要使用正确的client
httpClient
=
s
.
httpClient
if
upstreamResult
.
Client
!=
nil
{
httpClient
=
upstreamResult
.
Client
}
resp
,
err
=
httpClient
.
Do
(
upstreamResult
.
Request
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"retry request failed: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"retry request failed: %w"
,
err
)
}
}
...
@@ -480,7 +491,13 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *m
...
@@ -480,7 +491,13 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *m
},
nil
},
nil
}
}
func
(
s
*
GatewayService
)
buildUpstreamRequest
(
ctx
context
.
Context
,
c
*
gin
.
Context
,
account
*
model
.
Account
,
body
[]
byte
,
token
,
tokenType
string
)
(
*
http
.
Request
,
error
)
{
// buildUpstreamRequestResult contains the request and optional custom client for proxy
type
buildUpstreamRequestResult
struct
{
Request
*
http
.
Request
Client
*
http
.
Client
// nil means use default s.httpClient
}
func
(
s
*
GatewayService
)
buildUpstreamRequest
(
ctx
context
.
Context
,
c
*
gin
.
Context
,
account
*
model
.
Account
,
body
[]
byte
,
token
,
tokenType
string
)
(
*
buildUpstreamRequestResult
,
error
)
{
// 确定目标URL
// 确定目标URL
targetURL
:=
claudeAPIURL
targetURL
:=
claudeAPIURL
if
account
.
Type
==
model
.
AccountTypeApiKey
{
if
account
.
Type
==
model
.
AccountTypeApiKey
{
...
@@ -549,7 +566,8 @@ func (s *GatewayService) buildUpstreamRequest(ctx context.Context, c *gin.Contex
...
@@ -549,7 +566,8 @@ func (s *GatewayService) buildUpstreamRequest(ctx context.Context, c *gin.Contex
req
.
Header
.
Set
(
"anthropic-beta"
,
s
.
getBetaHeader
(
body
,
c
.
GetHeader
(
"anthropic-beta"
)))
req
.
Header
.
Set
(
"anthropic-beta"
,
s
.
getBetaHeader
(
body
,
c
.
GetHeader
(
"anthropic-beta"
)))
}
}
// 配置代理
// 配置代理 - 创建独立的client避免并发修改共享httpClient
var
customClient
*
http
.
Client
if
account
.
ProxyID
!=
nil
&&
account
.
Proxy
!=
nil
{
if
account
.
ProxyID
!=
nil
&&
account
.
Proxy
!=
nil
{
proxyURL
:=
account
.
Proxy
.
URL
()
proxyURL
:=
account
.
Proxy
.
URL
()
if
proxyURL
!=
""
{
if
proxyURL
!=
""
{
...
@@ -566,12 +584,18 @@ func (s *GatewayService) buildUpstreamRequest(ctx context.Context, c *gin.Contex
...
@@ -566,12 +584,18 @@ func (s *GatewayService) buildUpstreamRequest(ctx context.Context, c *gin.Contex
IdleConnTimeout
:
90
*
time
.
Second
,
IdleConnTimeout
:
90
*
time
.
Second
,
ResponseHeaderTimeout
:
responseHeaderTimeout
,
ResponseHeaderTimeout
:
responseHeaderTimeout
,
}
}
s
.
httpClient
.
Transport
=
transport
// 创建独立的client,避免并发时修改共享的s.httpClient.Transport
customClient
=
&
http
.
Client
{
Transport
:
transport
,
}
}
}
}
}
}
}
return
req
,
nil
return
&
buildUpstreamRequestResult
{
Request
:
req
,
Client
:
customClient
,
},
nil
}
}
// getBetaHeader 处理anthropic-beta header
// getBetaHeader 处理anthropic-beta header
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment