From a611742910bd8e33f19fa79fa74687e3618cf77c Mon Sep 17 00:00:00 2001 From: wucm667 Date: Thu, 14 May 2026 18:03:18 +0800 Subject: [PATCH] fix(gateway): detach upstream context unconditionally for image generation Image generation requests (forwardOpenAIImagesOAuth and forwardOpenAIImagesAPIKey) were calling detachStreamUpstreamContext with parsed.Stream, which for non-streaming requests (Stream=false) simply returned the original client context unchanged. When the client disconnected before the upstream completed (30-80s for image gen), the context cancellation propagated to the upstream HTTP request, causing a 502 error despite the upstream having already started processing. Switch to detachUpstreamContext (unconditional detach) so the upstream image generation request is always bound to a background context and completes regardless of client lifecycle. Fixes #2310 --- backend/internal/service/openai_images.go | 2 +- backend/internal/service/openai_images_responses.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/internal/service/openai_images.go b/backend/internal/service/openai_images.go index afa94156..51226f87 100644 --- a/backend/internal/service/openai_images.go +++ b/backend/internal/service/openai_images.go @@ -639,7 +639,7 @@ func (s *OpenAIGatewayService) forwardOpenAIImagesAPIKey( setOpsUpstreamRequestBody(c, forwardBody) } - upstreamCtx, releaseUpstreamCtx := detachStreamUpstreamContext(ctx, parsed.Stream) + upstreamCtx, releaseUpstreamCtx := detachUpstreamContext(ctx) defer releaseUpstreamCtx() token, _, err := s.GetAccessToken(upstreamCtx, account) diff --git a/backend/internal/service/openai_images_responses.go b/backend/internal/service/openai_images_responses.go index 25cd8228..4c861341 100644 --- a/backend/internal/service/openai_images_responses.go +++ b/backend/internal/service/openai_images_responses.go @@ -948,7 +948,7 @@ func (s *OpenAIGatewayService) forwardOpenAIImagesOAuth( ) } - upstreamCtx, releaseUpstreamCtx := detachStreamUpstreamContext(ctx, parsed.Stream) + upstreamCtx, releaseUpstreamCtx := detachUpstreamContext(ctx) defer releaseUpstreamCtx() token, _, err := s.GetAccessToken(upstreamCtx, account)