diff --git a/pkg/http/middleware/request_config.go b/pkg/http/middleware/request_config.go index 6102825192..2c14edaa5c 100644 --- a/pkg/http/middleware/request_config.go +++ b/pkg/http/middleware/request_config.go @@ -26,12 +26,12 @@ func WithRequestConfig(next http.Handler) http.Handler { } // Toolsets - if toolsets := headers.ParseCommaSeparated(r.Header.Get(headers.MCPToolsetsHeader)); len(toolsets) > 0 { + if toolsets := headers.ParseCommaSeparated(strings.Join(r.Header.Values(headers.MCPToolsetsHeader), ",")); len(toolsets) > 0 { ctx = ghcontext.WithToolsets(ctx, toolsets) } // Tools - if tools := headers.ParseCommaSeparated(r.Header.Get(headers.MCPToolsHeader)); len(tools) > 0 { + if tools := headers.ParseCommaSeparated(strings.Join(r.Header.Values(headers.MCPToolsHeader), ",")); len(tools) > 0 { ctx = ghcontext.WithTools(ctx, tools) } @@ -41,7 +41,7 @@ func WithRequestConfig(next http.Handler) http.Handler { } // Excluded tools - if excludeTools := headers.ParseCommaSeparated(r.Header.Get(headers.MCPExcludeToolsHeader)); len(excludeTools) > 0 { + if excludeTools := headers.ParseCommaSeparated(strings.Join(r.Header.Values(headers.MCPExcludeToolsHeader), ",")); len(excludeTools) > 0 { ctx = ghcontext.WithExcludeTools(ctx, excludeTools) } @@ -54,7 +54,7 @@ func WithRequestConfig(next http.Handler) http.Handler { _, hasHeaderFeatures := r.Header[http.CanonicalHeaderKey(headers.MCPFeaturesHeader)] _, hasQueryFeatures := query[queryParamFeatures] if hasHeaderFeatures { - ctx = ghcontext.WithHeaderFeatures(ctx, headers.ParseCommaSeparated(r.Header.Get(headers.MCPFeaturesHeader))) + ctx = ghcontext.WithHeaderFeatures(ctx, headers.ParseCommaSeparated(strings.Join(r.Header.Values(headers.MCPFeaturesHeader), ","))) } else if hasQueryFeatures { ctx = ghcontext.WithHeaderFeatures(ctx, headers.ParseCommaSeparated(query.Get(queryParamFeatures))) } diff --git a/pkg/http/middleware/request_config_test.go b/pkg/http/middleware/request_config_test.go index 1937d0986b..ce572d5084 100644 --- a/pkg/http/middleware/request_config_test.go +++ b/pkg/http/middleware/request_config_test.go @@ -1,6 +1,7 @@ package middleware import ( + "context" "net/http" "net/http/httptest" "testing" @@ -10,6 +11,30 @@ import ( "github.com/stretchr/testify/assert" ) +func TestWithRequestConfigRepeatedListHeaders(t *testing.T) { + tests := []struct { + name string + header string + get func(context.Context) []string + }{ + {"toolsets", headers.MCPToolsetsHeader, ghcontext.GetToolsets}, + {"tools", headers.MCPToolsHeader, ghcontext.GetTools}, + {"excluded tools", headers.MCPExcludeToolsHeader, ghcontext.GetExcludeTools}, + {"features", headers.MCPFeaturesHeader, ghcontext.GetHeaderFeatures}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "/?features=query_flag", nil) + req.Header.Add(tc.header, "first, second") + req.Header.Add(tc.header, " third, , fourth ") + handler := WithRequestConfig(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { + assert.Equal(t, []string{"first", "second", "third", "fourth"}, tc.get(r.Context())) + })) + handler.ServeHTTP(httptest.NewRecorder(), req) + }) + } +} + func TestWithRequestConfigFeatureSelection(t *testing.T) { tests := []struct { name string