diff --git a/router-tests/header_propagation_test.go b/router-tests/header_propagation_test.go index 978e00eb0a..8ca3ab0373 100644 --- a/router-tests/header_propagation_test.go +++ b/router-tests/header_propagation_test.go @@ -178,6 +178,33 @@ func TestHeaderPropagation(t *testing.T) { }) }) + t.Run("works with unresponsive subgraph", func(t *testing.T) { + t.Parallel() + testenv.Run(t, &testenv.Config{ + RouterOptions: global(config.ResponseHeaderRuleAlgorithmLastWrite, customHeader, ""), + Subgraphs: testenv.SubgraphsConfig{ + Employees: testenv.SubgraphConfig{ + Middleware: func(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set(customHeader, employeeVal) + handler.ServeHTTP(w, r) + }) + }, + }, + Hobbies: testenv.SubgraphConfig{ + CloseOnStart: true, + }, + }, + }, func(t *testing.T, xEnv *testenv.Environment) { + res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: queryEmployeeWithHobby, + }) + ch := strings.Join(res.Response.Header.Values(customHeader), ",") + require.Equal(t, employeeVal, ch) + require.Equal(t, `{"errors":[{"message":"Failed to fetch from Subgraph 'hobbies' at Path 'employee'."}],"data":{"employee":{"id":1,"hobbies":null}}}`, res.Body) + }) + }) + t.Run("local last write wins", func(t *testing.T) { t.Parallel() testenv.Run(t, &testenv.Config{ diff --git a/router/core/header_rule_engine.go b/router/core/header_rule_engine.go index 97aee3f03c..e5d0484dba 100644 --- a/router/core/header_rule_engine.go +++ b/router/core/header_rule_engine.go @@ -263,6 +263,11 @@ func (h *HeaderPropagation) OnOriginRequest(request *http.Request, ctx RequestCo } func (h *HeaderPropagation) OnOriginResponse(resp *http.Response, ctx RequestContext) *http.Response { + // In the case of an error response, it is possible that the response is nil + if resp == nil { + return nil + } + propagation := getResponseHeaderPropagation(resp.Request.Context()) if propagation == nil { return resp diff --git a/router/core/header_rule_engine_test.go b/router/core/header_rule_engine_test.go index 08d42c6d03..b024d34dd5 100644 --- a/router/core/header_rule_engine_test.go +++ b/router/core/header_rule_engine_test.go @@ -174,6 +174,22 @@ func TestPropagateHeaderRule(t *testing.T) { assert.Equal(t, "test1", updatedClientReq.Header.Get("X-Test-1")) }) + + t.Run("Should handle nil resonses", func(t *testing.T) { + ht, err := NewHeaderPropagation(&config.HeaderRules{ + All: &config.GlobalHeaderRule{}, + }) + assert.Nil(t, err) + + rr := httptest.NewRecorder() + resp := ht.OnOriginResponse(nil, &requestContext{ + logger: zap.NewNop(), + responseWriter: rr, + operation: &operationContext{}, + subgraphResolver: NewSubgraphResolver(nil), + }) + require.Nil(t, resp) + }) } func TestRenamePropagateHeaderRule(t *testing.T) {