Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
c9486526
authored
Feb 22, 2026
by
Calcium-Ion
Committed by
GitHub
Feb 22, 2026
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2961 from seefs001/feature/codex-oauth-with-proxy
feat: codex oauth proxy
parents
49eb6d3c
f8a66a6e
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
39 additions
and
9 deletions
+39
-9
controller/codex_oauth.go
+3
-1
controller/codex_usage.go
+2
-3
service/codex_credential_refresh.go
+1
-1
service/codex_oauth.go
+33
-4
No files found.
controller/codex_oauth.go
View file @
c9486526
...
@@ -145,6 +145,7 @@ func completeCodexOAuthWithChannelID(c *gin.Context, channelID int) {
...
@@ -145,6 +145,7 @@ func completeCodexOAuthWithChannelID(c *gin.Context, channelID int) {
return
return
}
}
channelProxy
:=
""
if
channelID
>
0
{
if
channelID
>
0
{
ch
,
err
:=
model
.
GetChannelById
(
channelID
,
false
)
ch
,
err
:=
model
.
GetChannelById
(
channelID
,
false
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -159,6 +160,7 @@ func completeCodexOAuthWithChannelID(c *gin.Context, channelID int) {
...
@@ -159,6 +160,7 @@ func completeCodexOAuthWithChannelID(c *gin.Context, channelID int) {
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"channel type is not Codex"
})
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"channel type is not Codex"
})
return
return
}
}
channelProxy
=
ch
.
GetSetting
()
.
Proxy
}
}
session
:=
sessions
.
Default
(
c
)
session
:=
sessions
.
Default
(
c
)
...
@@ -176,7 +178,7 @@ func completeCodexOAuthWithChannelID(c *gin.Context, channelID int) {
...
@@ -176,7 +178,7 @@ func completeCodexOAuthWithChannelID(c *gin.Context, channelID int) {
ctx
,
cancel
:=
context
.
WithTimeout
(
c
.
Request
.
Context
(),
15
*
time
.
Second
)
ctx
,
cancel
:=
context
.
WithTimeout
(
c
.
Request
.
Context
(),
15
*
time
.
Second
)
defer
cancel
()
defer
cancel
()
tokenRes
,
err
:=
service
.
ExchangeCodexAuthorizationCode
(
ctx
,
code
,
verifier
)
tokenRes
,
err
:=
service
.
ExchangeCodexAuthorizationCode
WithProxy
(
ctx
,
code
,
verifier
,
channelProxy
)
if
err
!=
nil
{
if
err
!=
nil
{
common
.
SysError
(
"failed to exchange codex authorization code: "
+
err
.
Error
())
common
.
SysError
(
"failed to exchange codex authorization code: "
+
err
.
Error
())
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"授权码交换失败,请重试"
})
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
"授权码交换失败,请重试"
})
...
...
controller/codex_usage.go
View file @
c9486526
...
@@ -2,7 +2,6 @@ package controller
...
@@ -2,7 +2,6 @@ package controller
import
(
import
(
"context"
"context"
"encoding/json"
"fmt"
"fmt"
"net/http"
"net/http"
"strconv"
"strconv"
...
@@ -80,7 +79,7 @@ func GetCodexChannelUsage(c *gin.Context) {
...
@@ -80,7 +79,7 @@ func GetCodexChannelUsage(c *gin.Context) {
refreshCtx
,
refreshCancel
:=
context
.
WithTimeout
(
c
.
Request
.
Context
(),
10
*
time
.
Second
)
refreshCtx
,
refreshCancel
:=
context
.
WithTimeout
(
c
.
Request
.
Context
(),
10
*
time
.
Second
)
defer
refreshCancel
()
defer
refreshCancel
()
res
,
refreshErr
:=
service
.
RefreshCodexOAuthToken
(
refreshCtx
,
oauthKey
.
RefreshToken
)
res
,
refreshErr
:=
service
.
RefreshCodexOAuthToken
WithProxy
(
refreshCtx
,
oauthKey
.
RefreshToken
,
ch
.
GetSetting
()
.
Proxy
)
if
refreshErr
==
nil
{
if
refreshErr
==
nil
{
oauthKey
.
AccessToken
=
res
.
AccessToken
oauthKey
.
AccessToken
=
res
.
AccessToken
oauthKey
.
RefreshToken
=
res
.
RefreshToken
oauthKey
.
RefreshToken
=
res
.
RefreshToken
...
@@ -109,7 +108,7 @@ func GetCodexChannelUsage(c *gin.Context) {
...
@@ -109,7 +108,7 @@ func GetCodexChannelUsage(c *gin.Context) {
}
}
var
payload
any
var
payload
any
if
js
on
.
Unmarshal
(
body
,
&
payload
)
!=
nil
{
if
comm
on
.
Unmarshal
(
body
,
&
payload
)
!=
nil
{
payload
=
string
(
body
)
payload
=
string
(
body
)
}
}
...
...
service/codex_credential_refresh.go
View file @
c9486526
...
@@ -62,7 +62,7 @@ func RefreshCodexChannelCredential(ctx context.Context, channelID int, opts Code
...
@@ -62,7 +62,7 @@ func RefreshCodexChannelCredential(ctx context.Context, channelID int, opts Code
refreshCtx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
10
*
time
.
Second
)
refreshCtx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
10
*
time
.
Second
)
defer
cancel
()
defer
cancel
()
res
,
err
:=
RefreshCodexOAuthToken
(
refreshCtx
,
oauthKey
.
RefreshToken
)
res
,
err
:=
RefreshCodexOAuthToken
WithProxy
(
refreshCtx
,
oauthKey
.
RefreshToken
,
ch
.
GetSetting
()
.
Proxy
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
nil
,
err
return
nil
,
nil
,
err
}
}
...
...
service/codex_oauth.go
View file @
c9486526
...
@@ -12,6 +12,8 @@ import (
...
@@ -12,6 +12,8 @@ import (
"net/url"
"net/url"
"strings"
"strings"
"time"
"time"
"github.com/QuantumNous/new-api/common"
)
)
const
(
const
(
...
@@ -38,12 +40,26 @@ type CodexOAuthAuthorizationFlow struct {
...
@@ -38,12 +40,26 @@ type CodexOAuthAuthorizationFlow struct {
}
}
func
RefreshCodexOAuthToken
(
ctx
context
.
Context
,
refreshToken
string
)
(
*
CodexOAuthTokenResult
,
error
)
{
func
RefreshCodexOAuthToken
(
ctx
context
.
Context
,
refreshToken
string
)
(
*
CodexOAuthTokenResult
,
error
)
{
client
:=
&
http
.
Client
{
Timeout
:
defaultHTTPTimeout
}
return
RefreshCodexOAuthTokenWithProxy
(
ctx
,
refreshToken
,
""
)
}
func
RefreshCodexOAuthTokenWithProxy
(
ctx
context
.
Context
,
refreshToken
string
,
proxyURL
string
)
(
*
CodexOAuthTokenResult
,
error
)
{
client
,
err
:=
getCodexOAuthHTTPClient
(
proxyURL
)
if
err
!=
nil
{
return
nil
,
err
}
return
refreshCodexOAuthToken
(
ctx
,
client
,
codexOAuthTokenURL
,
codexOAuthClientID
,
refreshToken
)
return
refreshCodexOAuthToken
(
ctx
,
client
,
codexOAuthTokenURL
,
codexOAuthClientID
,
refreshToken
)
}
}
func
ExchangeCodexAuthorizationCode
(
ctx
context
.
Context
,
code
string
,
verifier
string
)
(
*
CodexOAuthTokenResult
,
error
)
{
func
ExchangeCodexAuthorizationCode
(
ctx
context
.
Context
,
code
string
,
verifier
string
)
(
*
CodexOAuthTokenResult
,
error
)
{
client
:=
&
http
.
Client
{
Timeout
:
defaultHTTPTimeout
}
return
ExchangeCodexAuthorizationCodeWithProxy
(
ctx
,
code
,
verifier
,
""
)
}
func
ExchangeCodexAuthorizationCodeWithProxy
(
ctx
context
.
Context
,
code
string
,
verifier
string
,
proxyURL
string
)
(
*
CodexOAuthTokenResult
,
error
)
{
client
,
err
:=
getCodexOAuthHTTPClient
(
proxyURL
)
if
err
!=
nil
{
return
nil
,
err
}
return
exchangeCodexAuthorizationCode
(
ctx
,
client
,
codexOAuthTokenURL
,
codexOAuthClientID
,
code
,
verifier
,
codexOAuthRedirectURI
)
return
exchangeCodexAuthorizationCode
(
ctx
,
client
,
codexOAuthTokenURL
,
codexOAuthClientID
,
code
,
verifier
,
codexOAuthRedirectURI
)
}
}
...
@@ -104,7 +120,7 @@ func refreshCodexOAuthToken(
...
@@ -104,7 +120,7 @@ func refreshCodexOAuthToken(
ExpiresIn
int
`json:"expires_in"`
ExpiresIn
int
`json:"expires_in"`
}
}
if
err
:=
json
.
NewDecoder
(
resp
.
Body
)
.
Decode
(
&
payload
);
err
!=
nil
{
if
err
:=
common
.
DecodeJson
(
resp
.
Body
,
&
payload
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
if
resp
.
StatusCode
<
200
||
resp
.
StatusCode
>=
300
{
if
resp
.
StatusCode
<
200
||
resp
.
StatusCode
>=
300
{
...
@@ -165,7 +181,7 @@ func exchangeCodexAuthorizationCode(
...
@@ -165,7 +181,7 @@ func exchangeCodexAuthorizationCode(
RefreshToken
string
`json:"refresh_token"`
RefreshToken
string
`json:"refresh_token"`
ExpiresIn
int
`json:"expires_in"`
ExpiresIn
int
`json:"expires_in"`
}
}
if
err
:=
json
.
NewDecoder
(
resp
.
Body
)
.
Decode
(
&
payload
);
err
!=
nil
{
if
err
:=
common
.
DecodeJson
(
resp
.
Body
,
&
payload
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
if
resp
.
StatusCode
<
200
||
resp
.
StatusCode
>=
300
{
if
resp
.
StatusCode
<
200
||
resp
.
StatusCode
>=
300
{
...
@@ -181,6 +197,19 @@ func exchangeCodexAuthorizationCode(
...
@@ -181,6 +197,19 @@ func exchangeCodexAuthorizationCode(
},
nil
},
nil
}
}
func
getCodexOAuthHTTPClient
(
proxyURL
string
)
(
*
http
.
Client
,
error
)
{
baseClient
,
err
:=
GetHttpClientWithProxy
(
strings
.
TrimSpace
(
proxyURL
))
if
err
!=
nil
{
return
nil
,
err
}
if
baseClient
==
nil
{
return
&
http
.
Client
{
Timeout
:
defaultHTTPTimeout
},
nil
}
clientCopy
:=
*
baseClient
clientCopy
.
Timeout
=
defaultHTTPTimeout
return
&
clientCopy
,
nil
}
func
buildCodexAuthorizeURL
(
state
string
,
challenge
string
)
(
string
,
error
)
{
func
buildCodexAuthorizeURL
(
state
string
,
challenge
string
)
(
string
,
error
)
{
u
,
err
:=
url
.
Parse
(
codexOAuthAuthorizeURL
)
u
,
err
:=
url
.
Parse
(
codexOAuthAuthorizeURL
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
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