fix(sora): 优化 challenge 重试与调试日志
This commit is contained in:
@@ -833,7 +833,7 @@ func TestSoraDirectClient_DoHTTP_SidecarSessionKeyStableForSameAccountProxy(t *t
|
||||
require.Equal(t, captured[0].SessionKey, captured[1].SessionKey)
|
||||
}
|
||||
|
||||
func TestSoraDirectClient_DoRequestWithProxy_CloudflareChallengeSetsCooldownAndSkipsRetry(t *testing.T) {
|
||||
func TestSoraDirectClient_DoRequestWithProxy_CloudflareChallengeSetsCooldownAfterSingleRetry(t *testing.T) {
|
||||
var sidecarCalls int32
|
||||
sidecar := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
atomic.AddInt32(&sidecarCalls, 1)
|
||||
@@ -879,7 +879,7 @@ func TestSoraDirectClient_DoRequestWithProxy_CloudflareChallengeSetsCooldownAndS
|
||||
var upstreamErr *SoraUpstreamError
|
||||
require.ErrorAs(t, err, &upstreamErr)
|
||||
require.Equal(t, http.StatusForbidden, upstreamErr.StatusCode)
|
||||
require.Equal(t, int32(1), atomic.LoadInt32(&sidecarCalls), "challenge should not trigger retry loop")
|
||||
require.Equal(t, int32(2), atomic.LoadInt32(&sidecarCalls), "challenge should trigger exactly one same-proxy retry")
|
||||
|
||||
_, _, err = client.doRequestWithProxy(
|
||||
context.Background(),
|
||||
@@ -896,7 +896,112 @@ func TestSoraDirectClient_DoRequestWithProxy_CloudflareChallengeSetsCooldownAndS
|
||||
require.Equal(t, http.StatusTooManyRequests, upstreamErr.StatusCode)
|
||||
require.Contains(t, upstreamErr.Message, "cooling down")
|
||||
require.Contains(t, upstreamErr.Message, "cf-ray")
|
||||
require.Equal(t, int32(1), atomic.LoadInt32(&sidecarCalls), "cooldown should block outbound request")
|
||||
require.Equal(t, int32(2), atomic.LoadInt32(&sidecarCalls), "cooldown should block outbound request")
|
||||
}
|
||||
|
||||
func TestSoraDirectClient_DoRequestWithProxy_CloudflareRetrySuccessClearsCooldown(t *testing.T) {
|
||||
var sidecarCalls int32
|
||||
sidecar := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
call := atomic.AddInt32(&sidecarCalls, 1)
|
||||
if call == 1 {
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"status_code": http.StatusForbidden,
|
||||
"headers": map[string]any{
|
||||
"cf-ray": "9d05d73dec4d8c8e-GRU",
|
||||
"content-type": "text/html",
|
||||
},
|
||||
"body": `<!DOCTYPE html><html><head><title>Just a moment...</title></head><body><script>window._cf_chl_opt={};</script></body></html>`,
|
||||
})
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"status_code": http.StatusOK,
|
||||
"headers": map[string]any{
|
||||
"content-type": "application/json",
|
||||
},
|
||||
"body": `{"ok":true}`,
|
||||
})
|
||||
}))
|
||||
defer sidecar.Close()
|
||||
|
||||
cfg := &config.Config{
|
||||
Sora: config.SoraConfig{
|
||||
Client: config.SoraClientConfig{
|
||||
BaseURL: "https://sora.chatgpt.com/backend",
|
||||
MaxRetries: 3,
|
||||
CloudflareChallengeCooldownSeconds: 60,
|
||||
CurlCFFISidecar: config.SoraCurlCFFISidecarConfig{
|
||||
Enabled: true,
|
||||
BaseURL: sidecar.URL,
|
||||
Impersonate: "chrome131",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
client := NewSoraDirectClient(cfg, nil, nil)
|
||||
headers := http.Header{}
|
||||
account := &Account{ID: 109}
|
||||
proxyURL := "http://127.0.0.1:18080"
|
||||
|
||||
body, _, err := client.doRequestWithProxy(
|
||||
context.Background(),
|
||||
account,
|
||||
proxyURL,
|
||||
http.MethodGet,
|
||||
"https://sora.chatgpt.com/backend/me",
|
||||
headers,
|
||||
nil,
|
||||
true,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Contains(t, string(body), `"ok":true`)
|
||||
require.Equal(t, int32(2), atomic.LoadInt32(&sidecarCalls))
|
||||
|
||||
_, _, err = client.doRequestWithProxy(
|
||||
context.Background(),
|
||||
account,
|
||||
proxyURL,
|
||||
http.MethodGet,
|
||||
"https://sora.chatgpt.com/backend/me",
|
||||
headers,
|
||||
nil,
|
||||
true,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int32(3), atomic.LoadInt32(&sidecarCalls), "cooldown should be cleared after retry succeeds")
|
||||
}
|
||||
|
||||
func TestSoraComputeChallengeCooldownSeconds(t *testing.T) {
|
||||
require.Equal(t, 0, soraComputeChallengeCooldownSeconds(0, 3))
|
||||
require.Equal(t, 10, soraComputeChallengeCooldownSeconds(10, 1))
|
||||
require.Equal(t, 20, soraComputeChallengeCooldownSeconds(10, 2))
|
||||
require.Equal(t, 40, soraComputeChallengeCooldownSeconds(10, 4))
|
||||
require.Equal(t, 40, soraComputeChallengeCooldownSeconds(10, 9), "streak should cap at x4")
|
||||
require.Equal(t, 3600, soraComputeChallengeCooldownSeconds(1200, 9), "cooldown should cap at 3600s")
|
||||
}
|
||||
|
||||
func TestSoraDirectClient_RecordCloudflareChallengeCooldown_EscalatesStreak(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
Sora: config.SoraConfig{
|
||||
Client: config.SoraClientConfig{
|
||||
CloudflareChallengeCooldownSeconds: 10,
|
||||
},
|
||||
},
|
||||
}
|
||||
client := NewSoraDirectClient(cfg, nil, nil)
|
||||
account := &Account{ID: 201}
|
||||
proxyURL := "http://127.0.0.1:18080"
|
||||
|
||||
client.recordCloudflareChallengeCooldown(account, proxyURL, http.StatusForbidden, http.Header{"Cf-Ray": []string{"9d05d73dec4d8c8e-GRU"}}, nil)
|
||||
client.recordCloudflareChallengeCooldown(account, proxyURL, http.StatusForbidden, http.Header{"Cf-Ray": []string{"9d05d73dec4d8c8f-GRU"}}, nil)
|
||||
|
||||
key := soraAccountProxyKey(account, proxyURL)
|
||||
entry, ok := client.challengeCooldowns[key]
|
||||
require.True(t, ok)
|
||||
require.Equal(t, 2, entry.ConsecutiveChallenges)
|
||||
require.Equal(t, "9d05d73dec4d8c8f-GRU", entry.CFRay)
|
||||
remain := int(entry.Until.Sub(entry.LastChallengeAt).Seconds())
|
||||
require.GreaterOrEqual(t, remain, 19)
|
||||
}
|
||||
|
||||
func TestSoraDirectClient_SidecarSessionKey_SkipsWhenAccountMissing(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user