@@ -536,6 +536,55 @@ func TestOpenAIGatewayService_OAuthPassthrough_UpstreamErrorIncludesPassthroughF
536536 require .True (t , arr [len (arr )- 1 ].Passthrough )
537537}
538538
539+ func TestOpenAIGatewayService_OAuthPassthrough_429PersistsRateLimit (t * testing.T ) {
540+ gin .SetMode (gin .TestMode )
541+
542+ rec := httptest .NewRecorder ()
543+ c , _ := gin .CreateTestContext (rec )
544+ c .Request = httptest .NewRequest (http .MethodPost , "/v1/responses" , bytes .NewReader (nil ))
545+ c .Request .Header .Set ("User-Agent" , "codex_cli_rs/0.1.0" )
546+
547+ originalBody := []byte (`{"model":"gpt-5.2","stream":false,"instructions":"local-test-instructions","input":[{"type":"text","text":"hi"}]}` )
548+ resetAt := time .Now ().Add (7 * 24 * time .Hour ).Unix ()
549+ resp := & http.Response {
550+ StatusCode : http .StatusTooManyRequests ,
551+ Header : http.Header {
552+ "Content-Type" : []string {"application/json" },
553+ "x-request-id" : []string {"rid-rate-limit" },
554+ },
555+ Body : io .NopCloser (strings .NewReader (fmt .Sprintf (`{"error":{"message":"The usage limit has been reached","type":"usage_limit_reached","resets_at":%d}}` , resetAt ))),
556+ }
557+ upstream := & httpUpstreamRecorder {resp : resp }
558+ repo := & openAIWSRateLimitSignalRepo {}
559+ rateSvc := & RateLimitService {accountRepo : repo }
560+
561+ svc := & OpenAIGatewayService {
562+ cfg : & config.Config {Gateway : config.GatewayConfig {ForceCodexCLI : false }},
563+ httpUpstream : upstream ,
564+ rateLimitService : rateSvc ,
565+ }
566+
567+ account := & Account {
568+ ID : 123 ,
569+ Name : "acc" ,
570+ Platform : PlatformOpenAI ,
571+ Type : AccountTypeOAuth ,
572+ Concurrency : 1 ,
573+ Credentials : map [string ]any {"access_token" : "oauth-token" , "chatgpt_account_id" : "chatgpt-acc" },
574+ Extra : map [string ]any {"openai_passthrough" : true },
575+ Status : StatusActive ,
576+ Schedulable : true ,
577+ RateMultiplier : f64p (1 ),
578+ }
579+
580+ _ , err := svc .Forward (context .Background (), c , account , originalBody )
581+ require .Error (t , err )
582+ require .Equal (t , http .StatusTooManyRequests , rec .Code )
583+ require .Contains (t , rec .Body .String (), "usage_limit_reached" )
584+ require .Len (t , repo .rateLimitCalls , 1 )
585+ require .WithinDuration (t , time .Unix (resetAt , 0 ), repo .rateLimitCalls [0 ], 2 * time .Second )
586+ }
587+
539588func TestOpenAIGatewayService_OAuthPassthrough_NonCodexUAFallbackToCodexUA (t * testing.T ) {
540589 gin .SetMode (gin .TestMode )
541590
0 commit comments