diff --git a/backend/internal/handler/openai_gateway_credential_failover_test.go b/backend/internal/handler/openai_gateway_credential_failover_test.go index 07a5e4999f..d650ef6a21 100644 --- a/backend/internal/handler/openai_gateway_credential_failover_test.go +++ b/backend/internal/handler/openai_gateway_credential_failover_test.go @@ -206,6 +206,10 @@ func TestOpsRecoveredCredentialFailoverUsesAccountAuthAttribution(t *testing.T) require.NotContains(t, job.entry.ErrorMessage, "earlier inference failure") require.NotNil(t, job.entry.UpstreamStatusCode) require.Zero(t, *job.entry.UpstreamStatusCode) - require.Len(t, job.entry.UpstreamErrors, 2) - require.Equal(t, http.StatusForbidden, job.entry.UpstreamErrors[0].UpstreamStatusCode) + require.Nil(t, job.entry.UpstreamErrors) + require.NotNil(t, job.entry.UpstreamErrorsJSON) + events, err := service.ParseOpsUpstreamErrors(*job.entry.UpstreamErrorsJSON) + require.NoError(t, err) + require.Len(t, events, 2) + require.Equal(t, http.StatusForbidden, events[0].UpstreamStatusCode) } diff --git a/backend/internal/pkg/ip/ip.go b/backend/internal/pkg/ip/ip.go index d9a1f93fff..b9c7774490 100644 --- a/backend/internal/pkg/ip/ip.go +++ b/backend/internal/pkg/ip/ip.go @@ -41,9 +41,6 @@ func normalizeIP(ip string) string { return ip } -// privateNets 预编译私有 IP CIDR 块,避免每次调用 isPrivateIP 时重复解析 -var privateNets []*net.IPNet - // CompiledIPRules 表示预编译的 IP 匹配规则。 // PatternCount 记录原始规则数量,用于保留“规则存在但全无效”时的行为语义。 type CompiledIPRules struct { @@ -52,23 +49,6 @@ type CompiledIPRules struct { PatternCount int } -func init() { - for _, cidr := range []string{ - "10.0.0.0/8", - "172.16.0.0/12", - "192.168.0.0/16", - "127.0.0.0/8", - "::1/128", - "fc00::/7", - } { - _, block, err := net.ParseCIDR(cidr) - if err != nil { - panic("invalid CIDR: " + cidr) - } - privateNets = append(privateNets, block) - } -} - // CompileIPRules 将 IP/CIDR 字符串规则预编译为可复用结构。 // 非法规则会被忽略,但 PatternCount 会保留原始规则条数。 func CompileIPRules(patterns []string) *CompiledIPRules { @@ -116,20 +96,6 @@ func matchesCompiledRules(parsedIP net.IP, rules *CompiledIPRules) bool { return false } -// isPrivateIP 检查 IP 是否为私有地址。 -func isPrivateIP(ipStr string) bool { - ip := net.ParseIP(ipStr) - if ip == nil { - return false - } - for _, block := range privateNets { - if block.Contains(ip) { - return true - } - } - return false -} - // MatchesPattern 检查 IP 是否匹配指定的模式(支持单个 IP 或 CIDR)。 // pattern 可以是: // - 单个 IP: "192.168.1.100" diff --git a/backend/internal/pkg/ip/ip_test.go b/backend/internal/pkg/ip/ip_test.go index be1ba7b714..2432abe7ab 100644 --- a/backend/internal/pkg/ip/ip_test.go +++ b/backend/internal/pkg/ip/ip_test.go @@ -10,48 +10,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestIsPrivateIP(t *testing.T) { - tests := []struct { - name string - ip string - expected bool - }{ - // 私有 IPv4 - {"10.x 私有地址", "10.0.0.1", true}, - {"10.x 私有地址段末", "10.255.255.255", true}, - {"172.16.x 私有地址", "172.16.0.1", true}, - {"172.31.x 私有地址", "172.31.255.255", true}, - {"192.168.x 私有地址", "192.168.1.1", true}, - {"127.0.0.1 本地回环", "127.0.0.1", true}, - {"127.x 回环段", "127.255.255.255", true}, - - // 公网 IPv4 - {"8.8.8.8 公网 DNS", "8.8.8.8", false}, - {"1.1.1.1 公网", "1.1.1.1", false}, - {"172.15.255.255 非私有", "172.15.255.255", false}, - {"172.32.0.0 非私有", "172.32.0.0", false}, - {"11.0.0.1 公网", "11.0.0.1", false}, - - // IPv6 - {"::1 IPv6 回环", "::1", true}, - {"fc00:: IPv6 私有", "fc00::1", true}, - {"fd00:: IPv6 私有", "fd00::1", true}, - {"2001:db8::1 IPv6 公网", "2001:db8::1", false}, - - // 无效输入 - {"空字符串", "", false}, - {"非法字符串", "not-an-ip", false}, - {"不完整 IP", "192.168", false}, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - got := isPrivateIP(tc.ip) - require.Equal(t, tc.expected, got, "isPrivateIP(%q)", tc.ip) - }) - } -} - func TestGetTrustedClientIPUsesGinClientIP(t *testing.T) { gin.SetMode(gin.TestMode) diff --git a/backend/internal/repository/ops_ingress_reject_repo.go b/backend/internal/repository/ops_ingress_reject_repo.go index 12ad7a685b..14625781c8 100644 --- a/backend/internal/repository/ops_ingress_reject_repo.go +++ b/backend/internal/repository/ops_ingress_reject_repo.go @@ -36,13 +36,13 @@ func (r *opsRepository) BatchUpsertIngressRejects(ctx context.Context, items []* } var query strings.Builder - query.WriteString(`INSERT INTO ops_ingress_reject_aggregates + _, _ = query.WriteString(`INSERT INTO ops_ingress_reject_aggregates (bucket_start, reject_reason, route_family, protocol, client_ip, user_id, api_key_id, request_count, first_seen, last_seen) VALUES `) args := make([]any, 0, len(valid)*10) for i, item := range valid { if i > 0 { - query.WriteByte(',') + _ = query.WriteByte(',') } base := len(args) fmt.Fprintf(&query, "($%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d)", @@ -57,7 +57,7 @@ VALUES `) args = append(args, item.BucketStart.UTC(), item.RejectReason, item.RouteFamily, item.Protocol, item.ClientIP, userID, apiKeyID, item.RequestCount, item.FirstSeen.UTC(), item.LastSeen.UTC()) } - query.WriteString(` + _, _ = query.WriteString(` ON CONFLICT (bucket_start, reject_reason, route_family, protocol, client_ip, user_id, api_key_id) DO UPDATE SET request_count = ops_ingress_reject_aggregates.request_count + EXCLUDED.request_count, first_seen = LEAST(ops_ingress_reject_aggregates.first_seen, EXCLUDED.first_seen), @@ -131,7 +131,7 @@ FROM ops_ingress_reject_aggregates %s ORDER BY bucket_start DESC,id DESC LIMIT $ if err != nil { return nil, err } - defer rows.Close() + defer func() { _ = rows.Close() }() result := &service.OpsIngressRejectList{ Items: make([]*service.OpsIngressRejectAggregate, 0, pageSize), Total: total, Page: page, PageSize: pageSize, diff --git a/backend/internal/repository/ops_repo_args_test.go b/backend/internal/repository/ops_repo_args_test.go index 5a88758f0a..9a5864b46f 100644 --- a/backend/internal/repository/ops_repo_args_test.go +++ b/backend/internal/repository/ops_repo_args_test.go @@ -14,7 +14,7 @@ func TestOpsInsertErrorLogArgsPreservesExplicitZeroUpstreamStatus(t *testing.T) zero := 0 args := opsInsertErrorLogArgs(&service.OpsInsertErrorLogInput{UpstreamStatusCode: &zero}) - require.Len(t, args, 41) + require.Len(t, args, 38) encoded, ok := args[27].(sql.NullInt64) require.True(t, ok) require.True(t, encoded.Valid) diff --git a/backend/internal/service/ops_ingress_reject.go b/backend/internal/service/ops_ingress_reject.go index a12d20e413..7e0452e5e2 100644 --- a/backend/internal/service/ops_ingress_reject.go +++ b/backend/internal/service/ops_ingress_reject.go @@ -156,8 +156,8 @@ func (a *OpsIngressRejectAggregator) Stop() { a.stopOnce.Do(func() { a.accepting.Store(false) a.recordMu.Lock() - a.recordMu.Unlock() a.cancel() + a.recordMu.Unlock() a.wg.Wait() a.snapshotAndEnqueue(false) a.flushPending()