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.
This commit is contained in:
2026-07-09 16:08:33 +08:00
parent f3803d01cf
commit db3219416e
+24 -6
View File
@@ -91,6 +91,7 @@ const uploadMaxRetries = 5
// its original (non-temporary) classification so the account is not penalized // its original (non-temporary) classification so the account is not penalized
// for a network blip. // for a network blip.
func (c *Client) UploadImage(ctx context.Context, token string, content []byte, contentType, engine string) (string, error) { 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) body, err, retryable := c.uploadImageOnce(ctx, token, content, contentType, engine)
for attempt := 0; err != nil && retryable && attempt < uploadMaxRetries && ctx.Err() == nil; attempt++ { for attempt := 0; err != nil && retryable && attempt < uploadMaxRetries && ctx.Err() == nil; attempt++ {
body, err, retryable = c.uploadImageOnce(ctx, token, content, contentType, engine) 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). // body plus whether a failure is retryable (transport error / 429/451/5xx).
// Auth failures (401/403) and other non-200s are not retryable. // 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) { 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 { if err != nil {
return nil, err, false 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) { 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 { if err != nil {
return nil, nil, err 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) candidates = BuildImagePayloadCandidates(modelID, prompt, aspectRatio, resolution, blobIDs)
} }
for _, payload := range candidates { 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 { if err == nil {
meta, data, pollErr := c.pollImage(ctx, sess, token, pollURL) meta, data, pollErr := c.pollImage(ctx, pollSess, token, pollURL)
if pollErr != nil { if pollErr != nil {
return nil, nil, pollErr return nil, nil, pollErr
} }
@@ -892,15 +899,26 @@ type tlsSession struct {
fp fingerprint 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) { 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{ options := []tlsclient.HttpClientOption{
tlsclient.WithTimeoutSeconds(60), tlsclient.WithTimeoutSeconds(60),
tlsclient.WithClientProfile(fp.profile), tlsclient.WithClientProfile(fp.profile),
tlsclient.WithNotFollowRedirects(), tlsclient.WithNotFollowRedirects(),
tlsclient.WithRandomTLSExtensionOrder(), tlsclient.WithRandomTLSExtensionOrder(),
} }
if c.proxy != "" { if useProxy && c.proxy != "" {
options = append(options, tlsclient.WithProxyUrl(c.proxy)) options = append(options, tlsclient.WithProxyUrl(c.proxy))
} }
client, err := tlsclient.NewHttpClient(tlsclient.NewNoopLogger(), options...) client, err := tlsclient.NewHttpClient(tlsclient.NewNoopLogger(), options...)