fix(auth, executor): normalize Qwen base URL, adjust RefreshLead duration, and add tests
This commit is contained in:
@@ -632,6 +632,26 @@ func applyQwenHeaders(r *http.Request, token string, stream bool) {
|
|||||||
r.Header.Set("Accept", "application/json")
|
r.Header.Set("Accept", "application/json")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normaliseQwenBaseURL(resourceURL string) string {
|
||||||
|
raw := strings.TrimSpace(resourceURL)
|
||||||
|
if raw == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
normalized := raw
|
||||||
|
lower := strings.ToLower(normalized)
|
||||||
|
if !strings.HasPrefix(lower, "http://") && !strings.HasPrefix(lower, "https://") {
|
||||||
|
normalized = "https://" + normalized
|
||||||
|
}
|
||||||
|
|
||||||
|
normalized = strings.TrimRight(normalized, "/")
|
||||||
|
if !strings.HasSuffix(strings.ToLower(normalized), "/v1") {
|
||||||
|
normalized += "/v1"
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalized
|
||||||
|
}
|
||||||
|
|
||||||
func qwenCreds(a *cliproxyauth.Auth) (token, baseURL string) {
|
func qwenCreds(a *cliproxyauth.Auth) (token, baseURL string) {
|
||||||
if a == nil {
|
if a == nil {
|
||||||
return "", ""
|
return "", ""
|
||||||
@@ -649,7 +669,7 @@ func qwenCreds(a *cliproxyauth.Auth) (token, baseURL string) {
|
|||||||
token = v
|
token = v
|
||||||
}
|
}
|
||||||
if v, ok := a.Metadata["resource_url"].(string); ok {
|
if v, ok := a.Metadata["resource_url"].(string); ok {
|
||||||
baseURL = fmt.Sprintf("https://%s/v1", v)
|
baseURL = normaliseQwenBaseURL(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/thinking"
|
"github.com/router-for-me/CLIProxyAPI/v6/internal/thinking"
|
||||||
|
cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -176,3 +177,35 @@ func TestWrapQwenError_Maps403QuotaTo429WithoutRetryAfter(t *testing.T) {
|
|||||||
t.Fatalf("wrapQwenError retryAfter = %v, want nil", *retryAfter)
|
t.Fatalf("wrapQwenError retryAfter = %v, want nil", *retryAfter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestQwenCreds_NormalizesResourceURL(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
resourceURL string
|
||||||
|
wantBaseURL string
|
||||||
|
}{
|
||||||
|
{"host only", "portal.qwen.ai", "https://portal.qwen.ai/v1"},
|
||||||
|
{"scheme no v1", "https://portal.qwen.ai", "https://portal.qwen.ai/v1"},
|
||||||
|
{"scheme with v1", "https://portal.qwen.ai/v1", "https://portal.qwen.ai/v1"},
|
||||||
|
{"scheme with v1 slash", "https://portal.qwen.ai/v1/", "https://portal.qwen.ai/v1"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
auth := &cliproxyauth.Auth{
|
||||||
|
Metadata: map[string]any{
|
||||||
|
"access_token": "test-token",
|
||||||
|
"resource_url": tt.resourceURL,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
token, baseURL := qwenCreds(auth)
|
||||||
|
if token != "test-token" {
|
||||||
|
t.Fatalf("qwenCreds token = %q, want %q", token, "test-token")
|
||||||
|
}
|
||||||
|
if baseURL != tt.wantBaseURL {
|
||||||
|
t.Fatalf("qwenCreds baseURL = %q, want %q", baseURL, tt.wantBaseURL)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ func (a *QwenAuthenticator) Provider() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *QwenAuthenticator) RefreshLead() *time.Duration {
|
func (a *QwenAuthenticator) RefreshLead() *time.Duration {
|
||||||
return new(3 * time.Hour)
|
return new(20 * time.Minute)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *QwenAuthenticator) Login(ctx context.Context, cfg *config.Config, opts *LoginOptions) (*coreauth.Auth, error) {
|
func (a *QwenAuthenticator) Login(ctx context.Context, cfg *config.Config, opts *LoginOptions) (*coreauth.Auth, error) {
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestQwenAuthenticator_RefreshLeadIsSane(t *testing.T) {
|
||||||
|
lead := NewQwenAuthenticator().RefreshLead()
|
||||||
|
if lead == nil {
|
||||||
|
t.Fatal("RefreshLead() = nil, want non-nil")
|
||||||
|
}
|
||||||
|
if *lead <= 0 {
|
||||||
|
t.Fatalf("RefreshLead() = %s, want > 0", *lead)
|
||||||
|
}
|
||||||
|
if *lead > 30*time.Minute {
|
||||||
|
t.Fatalf("RefreshLead() = %s, want <= %s", *lead, 30*time.Minute)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user