diff --git a/internal/controller/gateway.go b/internal/controller/gateway.go index 3b076ed50e..4633c1fa4a 100644 --- a/internal/controller/gateway.go +++ b/internal/controller/gateway.go @@ -10,6 +10,7 @@ import ( "context" "fmt" "sort" + "strings" "time" "github.com/go-logr/logr" @@ -167,9 +168,12 @@ func headerMutationToFilterAPI(m *aigv1a1.HTTPHeaderMutation) *filterapi.HTTPHea return nil } ret := &filterapi.HTTPHeaderMutation{} - ret.Remove = append(ret.Remove, m.Remove...) + ret.Remove = make([]string, 0, len(m.Remove)) + for _, h := range m.Remove { + ret.Remove = append(ret.Remove, strings.ToLower(h)) + } for _, h := range m.Set { - ret.Set = append(ret.Set, filterapi.HTTPHeader{Name: string(h.Name), Value: h.Value}) + ret.Set = append(ret.Set, filterapi.HTTPHeader{Name: strings.ToLower(string(h.Name)), Value: h.Value}) } return ret } diff --git a/internal/controller/gateway_test.go b/internal/controller/gateway_test.go index 7e604d88ef..70aefb5aee 100644 --- a/internal/controller/gateway_test.go +++ b/internal/controller/gateway_test.go @@ -216,8 +216,11 @@ func TestGatewayController_reconcileFilterConfigSecret(t *testing.T) { { ObjectMeta: metav1.ObjectMeta{Name: "apple", Namespace: gwNamespace}, Spec: aigv1a1.AIServiceBackendSpec{ - BackendRef: gwapiv1.BackendObjectReference{Name: "some-backend1", Namespace: ptr.To[gwapiv1.Namespace](gwNamespace)}, - HeaderMutation: &aigv1a1.HTTPHeaderMutation{Set: []gwapiv1.HTTPHeader{{Name: "x-foo", Value: "foo"}}, Remove: []string{"x-bar"}}, + BackendRef: gwapiv1.BackendObjectReference{Name: "some-backend1", Namespace: ptr.To[gwapiv1.Namespace](gwNamespace)}, + HeaderMutation: &aigv1a1.HTTPHeaderMutation{Set: []gwapiv1.HTTPHeader{ + // Header name should be normalized to lowercase in the filter config. + {Name: "X-Foo", Value: "foo"}, + }, Remove: []string{"x-Bar"}}, }, }, { diff --git a/internal/extproc/embeddings_processor_test.go b/internal/extproc/embeddings_processor_test.go index 21d0bec6d8..0fe3ea0226 100644 --- a/internal/extproc/embeddings_processor_test.go +++ b/internal/extproc/embeddings_processor_test.go @@ -496,14 +496,13 @@ func TestEmbeddingsProcessorRouterFilter_ProcessResponseHeaders_ProcessResponseB } func TestEmbeddingsProcessorUpstreamFilter_ProcessRequestHeaders_WithHeaderMutations(t *testing.T) { - const testModelKey = "x-ai-gateway-model-key" t.Run("header mutations applied correctly", func(t *testing.T) { headers := map[string]string{ - ":path": "/v1/embeddings", - testModelKey: "some-model", - "authorization": "bearer token123", - "x-api-key": "secret-key", - "x-custom": "custom-value", + ":path": "/v1/embeddings", + internalapi.ModelNameHeaderKeyDefault: "some-model", + "authorization": "bearer token123", + "x-api-key": "secret-key", + "x-custom": "custom-value", } someBody := embeddingBodyFromModel(t, "some-model") var body openai.EmbeddingRequest @@ -557,86 +556,11 @@ func TestEmbeddingsProcessorUpstreamFilter_ProcessRequestHeaders_WithHeaderMutat require.Equal(t, "custom-value", headers["x-custom"]) }) - t.Run("header mutations restored on retry", func(t *testing.T) { - headers := map[string]string{ - ":path": "/v1/embeddings", - testModelKey: "some-model", - // "x-custom" is not present in current headers, so it can be restored. - "x-new-header": "new-value", // Already set from previous mutation. - } - someBody := embeddingBodyFromModel(t, "some-model") - var body openai.EmbeddingRequest - require.NoError(t, json.Unmarshal(someBody, &body)) - - // Create header mutations that don't remove x-custom (so it can be restored). - headerMutations := &filterapi.HTTPHeaderMutation{ - Remove: []string{"authorization", "x-api-key"}, - Set: []filterapi.HTTPHeader{{Name: "x-new-header", Value: "updated-value"}}, - } - - mt := &mockEmbeddingTranslator{t: t, expRequestBody: &body} - mm := &mockEmbeddingsMetrics{} - p := &embeddingsProcessorUpstreamFilter{ - config: &processorConfig{}, - requestHeaders: headers, - logger: slog.Default(), - metrics: mm, - translator: mt, - originalRequestBodyRaw: someBody, - originalRequestBody: &body, - handler: &mockBackendAuthHandler{}, - onRetry: true, // This is a retry request. - } - - // Use the same headers map as the original headers (this simulates the router filter's requestHeaders). - originalHeaders := map[string]string{ - ":path": "/v1/embeddings", - testModelKey: "some-model", - "authorization": "bearer original-token", // This will be removed, so won't be restored. - "x-api-key": "original-secret", // This will be removed, so won't be restored. - "x-custom": "original-custom", // This won't be removed, so can be restored. - "x-new-header": "original-value", // This will be set, so won't be restored. - } - p.headerMutator = headermutator.NewHeaderMutator(headerMutations, originalHeaders) - - resp, err := p.ProcessRequestHeaders(t.Context(), nil) - require.NoError(t, err) - require.NotNil(t, resp) - - commonRes := resp.Response.(*extprocv3.ProcessingResponse_RequestHeaders).RequestHeaders.Response - - // Check that header mutations were applied. - require.NotNil(t, commonRes.HeaderMutation) - // RemoveHeaders should be empty because authorization/x-api-key don't exist in current headers. - require.Empty(t, commonRes.HeaderMutation.RemoveHeaders) - require.Len(t, commonRes.HeaderMutation.SetHeaders, 2) // Updated header + restored header. - - // Check that x-custom header was restored on retry (it's not being removed or set). - var restoredHeader *corev3.HeaderValueOption - var updatedHeader *corev3.HeaderValueOption - for _, h := range commonRes.HeaderMutation.SetHeaders { - switch h.Header.Key { - case "x-custom": - restoredHeader = h - case "x-new-header": - updatedHeader = h - } - } - require.NotNil(t, restoredHeader) - require.Equal(t, []byte("original-custom"), restoredHeader.Header.RawValue) - require.NotNil(t, updatedHeader) - require.Equal(t, []byte("updated-value"), updatedHeader.Header.RawValue) - - // Check that headers were updated in the request headers. - require.Equal(t, "updated-value", headers["x-new-header"]) - require.Equal(t, "original-custom", headers["x-custom"]) - }) - t.Run("no header mutations when mutator is nil", func(t *testing.T) { headers := map[string]string{ - ":path": "/v1/embeddings", - testModelKey: "some-model", - "authorization": "bearer token123", + ":path": "/v1/embeddings", + internalapi.ModelNameHeaderKeyDefault: "some-model", + "authorization": "bearer token123", } someBody := embeddingBodyFromModel(t, "some-model") var body openai.EmbeddingRequest @@ -756,7 +680,7 @@ func TestEmbeddingsProcessorUpstreamFilter_SetBackend_WithHeaderMutations(t *tes // Test retry scenario - original headers should be restored. testHeaders := map[string]string{ - "x-existing": "current-value", // This exists, so won't be restored. + "x-existing": "previously-set-value", } mutation := p.headerMutator.Mutate(testHeaders, true) // onRetry = true. @@ -775,7 +699,7 @@ func TestEmbeddingsProcessorUpstreamFilter_SetBackend_WithHeaderMutations(t *tes require.NotNil(t, restoredHeader) require.Equal(t, []byte("original-value"), restoredHeader.Header.RawValue) require.Equal(t, "original-value", testHeaders["x-custom"]) - // x-existing should not be restored because it already exists. - require.Equal(t, "current-value", testHeaders["x-existing"]) + // x-existing should be equal to existing-value from original headers. + require.Equal(t, "existing-value", testHeaders["x-existing"]) }) } diff --git a/internal/extproc/headermutator/header_mutator.go b/internal/extproc/headermutator/header_mutator.go index 38a1c0dd55..7cdf1fc979 100644 --- a/internal/extproc/headermutator/header_mutator.go +++ b/internal/extproc/headermutator/header_mutator.go @@ -12,10 +12,11 @@ import ( extprocv3 "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3" "github.com/envoyproxy/ai-gateway/internal/filterapi" + "github.com/envoyproxy/ai-gateway/internal/internalapi" ) type HeaderMutator struct { - // getOrignalHeaders Callback to get removed sensitive headers from the router filter. + // originalHeaders is a map of original headers inherited from the router processor. originalHeaders map[string]string // headerMutations is a list of header mutations to apply. @@ -38,13 +39,15 @@ func (h *HeaderMutator) Mutate(headers map[string]string, onRetry bool) *extproc // Removes sensitive headers before sending to backend. removedHeadersSet := make(map[string]struct{}) if !skipRemove { - for _, h := range h.headerMutations.Remove { - key := strings.ToLower(h) + for _, key := range h.headerMutations.Remove { + if shouldIgnoreHeader(key) { + continue + } removedHeadersSet[key] = struct{}{} if _, ok := headers[key]; ok { // Do NOT delete from the local headers map so metrics can still read it. // Instead, always instruct Envoy to remove it before forwarding upstream. - headerMutation.RemoveHeaders = append(headerMutation.RemoveHeaders, h) + headerMutation.RemoveHeaders = append(headerMutation.RemoveHeaders, key) } } } @@ -53,7 +56,10 @@ func (h *HeaderMutator) Mutate(headers map[string]string, onRetry bool) *extproc setHeadersSet := make(map[string]struct{}) if !skipSet { for _, h := range h.headerMutations.Set { - key := strings.ToLower(h.Name) + key := h.Name + if shouldIgnoreHeader(key) { + continue + } setHeadersSet[key] = struct{}{} headers[key] = h.Value headerMutation.SetHeaders = append(headerMutation.SetHeaders, &corev3.HeaderValueOption{ @@ -62,21 +68,58 @@ func (h *HeaderMutator) Mutate(headers map[string]string, onRetry bool) *extproc } } - // Restore original headers on retry, only if not being removed, set or not already present. - if onRetry && h.originalHeaders != nil { - for h, v := range h.originalHeaders { - key := strings.ToLower(h) + if onRetry { + // Restore original headers on retry, only if not being removed, set or not already present. + for key, v := range h.originalHeaders { + if shouldIgnoreHeader(key) { + continue + } _, isRemoved := removedHeadersSet[key] _, isSet := setHeadersSet[key] _, exists := headers[key] if !isRemoved && !exists && !isSet { - headers[h] = v + headers[key] = v + setHeadersSet[key] = struct{}{} + headerMutation.SetHeaders = append(headerMutation.SetHeaders, &corev3.HeaderValueOption{ + Header: &corev3.HeaderValue{Key: key, RawValue: []byte(v)}, + }) + } + } + // 1. Remove any headers that were added in the previous attempt (not part of original headers and not being set now). + // 2. Restore any original headers that were modified in the previous attempt (and not being set now). + for key := range headers { + if shouldIgnoreHeader(key) { + continue + } + if _, isSet := setHeadersSet[key]; isSet { + continue + } + originalValue, exists := h.originalHeaders[key] + if !exists { + delete(headers, key) + headerMutation.RemoveHeaders = append(headerMutation.RemoveHeaders, key) + } else { + // Restore original value. + headers[key] = originalValue headerMutation.SetHeaders = append(headerMutation.SetHeaders, &corev3.HeaderValueOption{ - Header: &corev3.HeaderValue{Key: h, RawValue: []byte(v)}, + Header: &corev3.HeaderValue{Key: key, RawValue: []byte(originalValue)}, }) } } } - return headerMutation } + +// shouldIgnoreHeader returns true if the header key should be ignored for mutation. +// +// Skip Envoy AI Gateway headers since some of them are populated after the originalHeaders are captured. +// This should be safe since these headers are managed by Envoy AI Gateway itself, not expected to be +// modified by users via header mutation API. +// +// Also, skip Envoy pseudo-headers beginning with ':', such as ":method", ":path", etc. +// This is important because these headers are not only sensitive to our implementation detail as well as +// it can cause unexpected behavior if they are modified unexpectedly. User shouldn't need to +// modify these headers via header mutation API. +func shouldIgnoreHeader(key string) bool { + return strings.HasPrefix(key, ":") || strings.HasPrefix(key, internalapi.EnvoyAIGatewayHeaderPrefix) +} diff --git a/internal/extproc/headermutator/header_mutator_test.go b/internal/extproc/headermutator/header_mutator_test.go index 1e86fbdaac..ab3184e526 100644 --- a/internal/extproc/headermutator/header_mutator_test.go +++ b/internal/extproc/headermutator/header_mutator_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/envoyproxy/ai-gateway/internal/filterapi" + "github.com/envoyproxy/ai-gateway/internal/internalapi" ) func TestHeaderMutator_Mutate(t *testing.T) { @@ -41,13 +42,23 @@ func TestHeaderMutator_Mutate(t *testing.T) { t.Run("restore original headers on retry", func(t *testing.T) { originalHeaders := map[string]string{ - "authorization": "secret", - "x-api-key": "key123", - "other": "value", + "authorization": "secret", + "x-api-key": "key123", + "other": "value", + "only-in-original": "original", + "in-original-too-but-previous-attempt-set": "pikachu", + // Envoy pseudo-header should be ignored. + ":path": "/v1/endpoint", + // Internal headers should be ignored. + internalapi.EnvoyAIGatewayHeaderPrefix + "-foo-bar": "should-not-be-included", } headers := map[string]string{ "other": "value", "authorization": "secret", + "in-original-too-but-previous-attempt-set": "charmander", + "only-set-previously": "bulbasaur", + // Internal headers should be ignored. + internalapi.EnvoyAIGatewayHeaderPrefix + "-dog-cat": "should-not-be-included", } mutations := &filterapi.HTTPHeaderMutation{ Remove: []string{"authorization"}, @@ -57,9 +68,22 @@ func TestHeaderMutator_Mutate(t *testing.T) { mutation := mutator.Mutate(headers, true) require.NotNil(t, mutation) - require.ElementsMatch(t, []string{"authorization"}, mutation.RemoveHeaders) + require.ElementsMatch(t, []string{"authorization", "only-set-previously"}, mutation.RemoveHeaders) + require.Len(t, mutation.SetHeaders, 5) + setHeadersMap := make(map[string]string) + for _, h := range mutation.SetHeaders { + setHeadersMap[h.Header.Key] = string(h.Header.RawValue) + } + require.Equal(t, "key123", setHeadersMap["x-api-key"]) + require.Equal(t, "value", setHeadersMap["other"]) + require.Equal(t, "secret", setHeadersMap["authorization"]) + require.Equal(t, "original", setHeadersMap["only-in-original"]) + require.Equal(t, "pikachu", setHeadersMap["in-original-too-but-previous-attempt-set"]) + // Check the final headers map too. require.Equal(t, "key123", headers["x-api-key"]) require.Equal(t, "value", headers["other"]) require.Equal(t, "secret", headers["authorization"]) + require.Equal(t, "original", headers["only-in-original"]) + require.Equal(t, "pikachu", headers["in-original-too-but-previous-attempt-set"]) }) } diff --git a/internal/extproc/messages_processor_test.go b/internal/extproc/messages_processor_test.go index 2fdd6e2fba..7d0b696c4e 100644 --- a/internal/extproc/messages_processor_test.go +++ b/internal/extproc/messages_processor_test.go @@ -769,100 +769,6 @@ func TestMessagesProcessorUpstreamFilter_ProcessRequestHeaders_WithHeaderMutatio require.Equal(t, "custom-value", headers["x-custom"]) }) - t.Run("header mutations restored on retry", func(t *testing.T) { - headers := map[string]string{ - ":path": "/anthropic/v1/messages", - "x-ai-eg-model": "claude-3-sonnet", - // "x-custom" is not present in current headers, so it can be restored. - "x-new-header": "new-value", // Already set from previous mutation. - } - - // Create request body. - requestBody := &anthropicschema.MessagesRequest{ - "model": "claude-3-sonnet", - "max_tokens": 1000, - "messages": []any{map[string]any{"role": "user", "content": "Hello"}}, - } - requestBodyRaw := []byte(`{"model": "claude-3-sonnet", "max_tokens": 1000, "messages": [{"role": "user", "content": "Hello"}]}`) - - // Create header mutations that don't remove x-custom (so it can be restored). - headerMutations := &filterapi.HTTPHeaderMutation{ - Remove: []string{"authorization", "x-api-key"}, - Set: []filterapi.HTTPHeader{{Name: "x-new-header", Value: "updated-value"}}, - } - - // Create mock translator. - mockTranslator := mockAnthropicTranslator{ - t: t, - expRequestBody: requestBody, - expForceRequestBodyMutation: true, // This is a retry request. - retHeaderMutation: &extprocv3.HeaderMutation{}, - retBodyMutation: &extprocv3.BodyMutation{}, - retErr: nil, - } - - // Create mock metrics. - chatMetrics := metrics.NewMessagesFactory(noop.NewMeterProvider().Meter("test"), map[string]string{})() - - // Create processor. - processor := &messagesProcessorUpstreamFilter{ - config: &processorConfig{}, - requestHeaders: headers, - logger: slog.Default(), - metrics: chatMetrics, - translator: mockTranslator, - originalRequestBody: requestBody, - originalRequestBodyRaw: requestBodyRaw, - handler: &mockBackendAuthHandler{}, - onRetry: true, // This is a retry request. - } - - // Use the same headers map as the original headers (this simulates the router filter's requestHeaders). - originalHeaders := map[string]string{ - ":path": "/anthropic/v1/messages", - "x-ai-eg-model": "claude-3-sonnet", - "authorization": "bearer original-token", // This will be removed, so won't be restored. - "x-api-key": "original-secret", // This will be removed, so won't be restored. - "x-custom": "original-custom", // This won't be removed, so can be restored. - "x-new-header": "original-value", // This will be set, so won't be restored. - } - processor.headerMutator = headermutator.NewHeaderMutator(headerMutations, originalHeaders) - - ctx := context.Background() - response, err := processor.ProcessRequestHeaders(ctx, nil) - - require.NoError(t, err) - require.NotNil(t, response) - - commonRes := response.Response.(*extprocv3.ProcessingResponse_RequestHeaders).RequestHeaders.Response - - // Check that header mutations were applied. - require.NotNil(t, commonRes.HeaderMutation) - // RemoveHeaders should be empty because authorization/x-api-key don't exist in current headers. - require.Empty(t, commonRes.HeaderMutation.RemoveHeaders) - require.Len(t, commonRes.HeaderMutation.SetHeaders, 2) // Updated header + restored header. - - // Check that x-custom header was restored on retry (it's not being removed or set). - var restoredHeader *corev3.HeaderValueOption - var updatedHeader *corev3.HeaderValueOption - for _, h := range commonRes.HeaderMutation.SetHeaders { - switch h.Header.Key { - case "x-custom": - restoredHeader = h - case "x-new-header": - updatedHeader = h - } - } - require.NotNil(t, restoredHeader) - require.Equal(t, []byte("original-custom"), restoredHeader.Header.RawValue) - require.NotNil(t, updatedHeader) - require.Equal(t, []byte("updated-value"), updatedHeader.Header.RawValue) - - // Check that headers were updated in the request headers. - require.Equal(t, "updated-value", headers["x-new-header"]) - require.Equal(t, "original-custom", headers["x-custom"]) - }) - t.Run("no header mutations when mutator is nil", func(t *testing.T) { headers := map[string]string{ ":path": "/anthropic/v1/messages", @@ -1023,7 +929,7 @@ func TestMessagesProcessorUpstreamFilter_SetBackend_WithHeaderMutations(t *testi // Test retry scenario - original headers should be restored. testHeaders := map[string]string{ - "x-existing": "current-value", // This exists, so won't be restored. + "x-existing": "previously-set-value", } mutation := p.headerMutator.Mutate(testHeaders, true) // onRetry = true. @@ -1042,7 +948,7 @@ func TestMessagesProcessorUpstreamFilter_SetBackend_WithHeaderMutations(t *testi require.NotNil(t, restoredHeader) require.Equal(t, []byte("original-value"), restoredHeader.Header.RawValue) require.Equal(t, "original-value", testHeaders["x-custom"]) - // x-existing should not be restored because it already exists. - require.Equal(t, "current-value", testHeaders["x-existing"]) + // x-existing should be equal to existing-value from original headers. + require.Equal(t, "existing-value", testHeaders["x-existing"]) }) } diff --git a/internal/extproc/server.go b/internal/extproc/server.go index 61cbc4d014..fd606d42a8 100644 --- a/internal/extproc/server.go +++ b/internal/extproc/server.go @@ -132,11 +132,11 @@ func (s *Server) processorForPath(requestHeaders map[string]string, isUpstreamFi // originalPathHeader is the header used to pass the original path to the processor. // This is used in the upstream filter level to determine the original path of the request on retry. -const originalPathHeader = "x-ai-eg-original-path" +const originalPathHeader = internalapi.EnvoyAIGatewayHeaderPrefix + "original-path" // internalReqIDHeader is the header used to pass the unique internal request ID to the upstream filter. // This ensures that the upstream filter uses the same unique ID as the router filter to avoid race conditions. -const internalReqIDHeader = "x-ai-eg-internal-req-id" +const internalReqIDHeader = internalapi.EnvoyAIGatewayHeaderPrefix + "internal-req-id" // Process implements [extprocv3.ExternalProcessorServer]. func (s *Server) Process(stream extprocv3.ExternalProcessor_ProcessServer) error { diff --git a/internal/filterapi/filterconfig.go b/internal/filterapi/filterconfig.go index b9eb226216..25ffc0c383 100644 --- a/internal/filterapi/filterconfig.go +++ b/internal/filterapi/filterconfig.go @@ -207,12 +207,14 @@ type HTTPHeaderMutation struct { Set []HTTPHeader `json:"set,omitempty"` // Remove the given header(s) from the HTTP request before the action. The // value of Remove is a list of HTTP header names. + // This is always ensured to be lower-cased like Envoy does internally. Remove []string `json:"remove,omitempty"` } // HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. type HTTPHeader struct { // Name is the name of the HTTP Header to be matched. + // This is always ensured to be lower-cased like Envoy does internally. Name string `json:"name"` // Value is the value of HTTP Header to be matched. Value string `json:"value"` diff --git a/internal/internalapi/internalapi.go b/internal/internalapi/internalapi.go index a7d8d465ee..e03629a822 100644 --- a/internal/internalapi/internalapi.go +++ b/internal/internalapi/internalapi.go @@ -15,14 +15,16 @@ import ( ) const ( + // EnvoyAIGatewayHeaderPrefix is the prefix for special headers used by AI Gateway, either for internal or external use. + EnvoyAIGatewayHeaderPrefix = "x-ai-eg-" // InternalEndpointMetadataNamespace is the namespace used for the dynamic metadata for internal use. InternalEndpointMetadataNamespace = "aigateway.envoy.io" // InternalMetadataBackendNameKey is the key used to store the backend name InternalMetadataBackendNameKey = "per_route_rule_backend_name" // MCPBackendHeader is the special header key used to specify the target backend name. - MCPBackendHeader = "x-ai-eg-mcp-backend" + MCPBackendHeader = EnvoyAIGatewayHeaderPrefix + "mcp-backend" // MCPRouteHeader is the special header key used to identify the mcp route. - MCPRouteHeader = "x-ai-eg-mcp-route" + MCPRouteHeader = EnvoyAIGatewayHeaderPrefix + "mcp-route" // MCPBackendListenerPort is the port for the MCP backend listener. MCPBackendListenerPort = 10088 // MCPProxyPort is the port where the MCP proxy listens. diff --git a/tests/extproc/envoy.yaml b/tests/extproc/envoy.yaml index 6dad579169..ffe1af0481 100644 --- a/tests/extproc/envoy.yaml +++ b/tests/extproc/envoy.yaml @@ -461,7 +461,7 @@ static_resources: metadata: filter_metadata: aigateway.envoy.io: - per_route_rule_backend_name: "testupstream-openai-always-200" + per_route_rule_backend_name: "testupstream-openai" priority: 1 # Secondary. - name: testupstream-modelname-override connect_timeout: 0.25s diff --git a/tests/extproc/testupstream_test.go b/tests/extproc/testupstream_test.go index dfe5571e30..1bae78b8c0 100644 --- a/tests/extproc/testupstream_test.go +++ b/tests/extproc/testupstream_test.go @@ -61,10 +61,6 @@ func TestWithTestUpstream(t *testing.T) { testUpstreamAzureBackend, testUpstreamGCPVertexAIBackend, testUpstreamGCPAnthropicAIBackend, - // TODO: this shouldn't be needed. The previous per-backend headers shouldn't affect the subsequent retries. - {Name: "testupstream-openai-always-200", Schema: openAISchema, HeaderMutation: &filterapi.HTTPHeaderMutation{ - Set: []filterapi.HTTPHeader{{Name: testupstreamlib.ResponseStatusKey, Value: "200"}}, - }}, { Name: "testupstream-openai-5xx", Schema: openAISchema, HeaderMutation: &filterapi.HTTPHeaderMutation{ Set: []filterapi.HTTPHeader{{Name: testupstreamlib.ResponseStatusKey, Value: "500"}}, diff --git a/tests/internal/testenvironment/test_environment.go b/tests/internal/testenvironment/test_environment.go index b854d55f24..a86842b38d 100644 --- a/tests/internal/testenvironment/test_environment.go +++ b/tests/internal/testenvironment/test_environment.go @@ -262,8 +262,8 @@ func requireEnvoy(t testing.TB, "--concurrency", strconv.Itoa(max(runtime.NumCPU(), 2)), // This allows multiple Envoy instances to run in parallel. "--base-id", strconv.Itoa(time.Now().Nanosecond()), - // Add debug logging for extproc. - "--component-log-level", "ext_proc:trace,http:debug,connection:debug", + // Add debug logging for http. + "--component-log-level", "http:debug", ) // wait for the ready message or exit.