fix(worker): 香港站点直连 Gemini 官方平台
官方 Gemini 平台配置的共享 HTTP Proxy 会拒绝香港出口的 CONNECT 请求,导致香港 Worker 的真实 VEO 与图片任务进入 upstream_submission_unknown。 新增仅按平台 UUID 生效的代理直连白名单,并只在香港 Worker 为官方 Gemini 平台启用;宁波与其他平台继续使用原代理策略。 验证:API 全量 go test、代理路由单测、bash -n、ShellCheck、cluster release helper、manual release 与差异检查均通过。
This commit is contained in:
@@ -38,6 +38,13 @@ func (s *Service) httpClientForCandidate(candidate store.RuntimeModelCandidate,
|
||||
if simulated {
|
||||
return s.httpClients.none, nil
|
||||
}
|
||||
// Some Worker sites have direct provider egress but are not authorized to
|
||||
// use a platform's shared proxy. Keep this override explicitly scoped to
|
||||
// platform UUIDs so one site's routing exception cannot bypass proxies for
|
||||
// unrelated providers or platforms.
|
||||
if platformIDListed(s.cfg.PlatformProxyBypassIDs, candidate.PlatformID) {
|
||||
return s.httpClients.none, nil
|
||||
}
|
||||
config, err := netproxy.Normalize(netproxy.FromPlatformConfig(candidate.PlatformConfig))
|
||||
if err != nil {
|
||||
return nil, &clients.ClientError{Code: "invalid_proxy", Message: err.Error(), Retryable: false}
|
||||
@@ -55,6 +62,19 @@ func (s *Service) httpClientForCandidate(candidate store.RuntimeModelCandidate,
|
||||
}
|
||||
}
|
||||
|
||||
func platformIDListed(raw string, platformID string) bool {
|
||||
platformID = strings.TrimSpace(platformID)
|
||||
if platformID == "" {
|
||||
return false
|
||||
}
|
||||
for value := range strings.SplitSeq(raw, ",") {
|
||||
if strings.TrimSpace(value) == platformID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *httpClientCache) customClient(rawProxy string) (*http.Client, error) {
|
||||
normalized, proxyURL, err := netproxy.ParseHTTPProxy(rawProxy)
|
||||
if err != nil {
|
||||
|
||||
@@ -101,6 +101,41 @@ func TestPlatformProxyModeCustomUsesConfiguredHTTPProxy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlatformProxyBypassIDUsesDirectConnection(t *testing.T) {
|
||||
var targetHits int
|
||||
target := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
targetHits++
|
||||
_, _ = w.Write([]byte("target"))
|
||||
}))
|
||||
defer target.Close()
|
||||
|
||||
var proxyHits int
|
||||
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
proxyHits++
|
||||
w.WriteHeader(http.StatusProxyAuthRequired)
|
||||
}))
|
||||
defer proxy.Close()
|
||||
|
||||
client, err := testProxyService(config.Config{
|
||||
PlatformProxyBypassIDs: "other-platform, official-gemini-platform ",
|
||||
}).httpClientForCandidate(store.RuntimeModelCandidate{
|
||||
PlatformID: "official-gemini-platform",
|
||||
PlatformConfig: map[string]any{"networkProxy": map[string]any{"mode": "custom", "httpProxy": proxy.URL}},
|
||||
}, false)
|
||||
if err != nil {
|
||||
t.Fatalf("build bypassed http client: %v", err)
|
||||
}
|
||||
resp, err := client.Get(target.URL)
|
||||
if err != nil {
|
||||
t.Fatalf("get target directly: %v", err)
|
||||
}
|
||||
_, _ = io.Copy(io.Discard, resp.Body)
|
||||
_ = resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK || targetHits != 1 || proxyHits != 0 {
|
||||
t.Fatalf("unexpected status=%d targetHits=%d proxyHits=%d", resp.StatusCode, targetHits, proxyHits)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlatformProxyModeGlobalUsesConfiguredGlobalHTTPProxy(t *testing.T) {
|
||||
var targetHits int
|
||||
target := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user