From db3219416e5b6a0bc678592d939a5855346a51d8 Mon Sep 17 00:00:00 2001 From: chiyi Date: Thu, 9 Jul 2026 16:08:33 +0800 Subject: [PATCH] feat(adobe): route only the image-generate submit through the proxy Reference-image upload, job polling and result download now run on the local IP; only the generate submit egresses via proxy.url. Verified live: submit egress 74.244.159.228 (proxy) vs upload/poll/download 76.209.9.65 (local), 1K adobe gpt image generated OK. --- backend/internal/provider/adobe/client.go | 30 ++++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/backend/internal/provider/adobe/client.go b/backend/internal/provider/adobe/client.go index 8bc74d7..2efd1eb 100644 --- a/backend/internal/provider/adobe/client.go +++ b/backend/internal/provider/adobe/client.go @@ -91,6 +91,7 @@ const uploadMaxRetries = 5 // its original (non-temporary) classification so the account is not penalized // for a network blip. func (c *Client) UploadImage(ctx context.Context, token string, content []byte, contentType, engine string) (string, error) { + // Reference-image upload runs on the local IP (not the proxy). body, err, retryable := c.uploadImageOnce(ctx, token, content, contentType, engine) for attempt := 0; err != nil && retryable && attempt < uploadMaxRetries && ctx.Err() == nil; attempt++ { body, err, retryable = c.uploadImageOnce(ctx, token, content, contentType, engine) @@ -120,7 +121,7 @@ func (c *Client) UploadImage(ctx context.Context, token string, content []byte, // body plus whether a failure is retryable (transport error / 429/451/5xx). // Auth failures (401/403) and other non-200s are not retryable. func (c *Client) uploadImageOnce(ctx context.Context, token string, content []byte, contentType, engine string) ([]byte, error, bool) { - sess, err := c.newTLSClient() + sess, err := c.newDirectTLSClient() if err != nil { return nil, err, false } @@ -174,7 +175,13 @@ func (c *Client) uploadImageOnce(ctx context.Context, token string, content []by } func (c *Client) GenerateImage(ctx context.Context, token, modelID, prompt, aspectRatio, resolution string, blobIDs []string) ([]byte, map[string]any, error) { - sess, err := c.newTLSClient() + // Only the generate submit goes through the proxy; polling + download run on + // the local IP. + submitSess, err := c.newTLSClient() + if err != nil { + return nil, nil, err + } + pollSess, err := c.newDirectTLSClient() if err != nil { return nil, nil, err } @@ -192,9 +199,9 @@ func (c *Client) GenerateImage(ctx context.Context, token, modelID, prompt, aspe candidates = BuildImagePayloadCandidates(modelID, prompt, aspectRatio, resolution, blobIDs) } for _, payload := range candidates { - respBody, pollURL, err := c.submitImage(ctx, sess, token, prompt, endpoint, payload) + respBody, pollURL, err := c.submitImage(ctx, submitSess, token, prompt, endpoint, payload) if err == nil { - meta, data, pollErr := c.pollImage(ctx, sess, token, pollURL) + meta, data, pollErr := c.pollImage(ctx, pollSess, token, pollURL) if pollErr != nil { return nil, nil, pollErr } @@ -892,15 +899,26 @@ type tlsSession struct { fp fingerprint } +// newTLSClient builds a session that routes through the configured proxy (when +// set). newDirectTLSClient builds one that always uses the local IP. Only the +// image-generation submit goes through the proxy; reference-image upload, +// polling and result download run on the local IP. func (c *Client) newTLSClient() (*tlsSession, error) { - fp := randomFingerprint() + return c.newTLSSession(randomFingerprint(), true) +} + +func (c *Client) newDirectTLSClient() (*tlsSession, error) { + return c.newTLSSession(randomFingerprint(), false) +} + +func (c *Client) newTLSSession(fp fingerprint, useProxy bool) (*tlsSession, error) { options := []tlsclient.HttpClientOption{ tlsclient.WithTimeoutSeconds(60), tlsclient.WithClientProfile(fp.profile), tlsclient.WithNotFollowRedirects(), tlsclient.WithRandomTLSExtensionOrder(), } - if c.proxy != "" { + if useProxy && c.proxy != "" { options = append(options, tlsclient.WithProxyUrl(c.proxy)) } client, err := tlsclient.NewHttpClient(tlsclient.NewNoopLogger(), options...)