diff --git a/agent/utils/utils.go b/agent/utils/utils.go index f9a695a..3021784 100644 --- a/agent/utils/utils.go +++ b/agent/utils/utils.go @@ -473,17 +473,24 @@ func (w *streamingResponseWriter) WriteHeader(status int) { // Initialize the response trailers. w.trailer = make(http.Header) - for _, k := range w.Header().Values("Trailer") { - // Initialize trailers with empty slices for any pre-declared values. - // - // This is necessary for the httputil.ReverseProxy type to forward them correctly. - // See [here](https://github.com/golang/go/blob/5e3c4016a436c357a57a6f7870913c6911c6904e/src/net/http/httputil/reverseproxy.go#L509) - if _, ok := hopHeaders[k]; ok { - continue + for _, joined := range w.Header().Values("Trailer") { + for _, k := range strings.Split(joined, ",") { + k = strings.TrimSpace(k) + if k == "" { + continue + } + if _, ok := hopHeaders[k]; ok { + continue + } + // Initialize trailers with empty slices for any pre-declared values. + // + // This is necessary for the httputil.ReverseProxy type to forward them correctly. + // See [here](https://github.com/golang/go/blob/5e3c4016a436c357a57a6f7870913c6911c6904e/src/net/http/httputil/reverseproxy.go#L509) + // + // We manually call `CanonicalHeaderKey` to preserve the invariant that + // all keys in a `Header` instance must be in their canonical format. + w.trailer[http.CanonicalHeaderKey(k)] = []string{} } - // We manually call `CanonicalHeaderKey` to preserve the invariant that - // all keys in a `Header` instance must be in their canonical format. - w.trailer[http.CanonicalHeaderKey(k)] = []string{} } // Filter out hop-by-hop headers. diff --git a/agent/utils/utils_test.go b/agent/utils/utils_test.go index f323513..3b9d986 100644 --- a/agent/utils/utils_test.go +++ b/agent/utils/utils_test.go @@ -292,6 +292,26 @@ func TestStreamingResponseWriter(t *testing.T) { }, WantResponseBody: "OK", }, + { + Description: "Coalesced trailer", + Request: &http.Request{}, + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Trailer", "Foo, Bar") + w.Write([]byte("OK")) + w.Header().Add("Foo", "Baz") + w.Header().Add("Bar", "Baz") + }), + WantResponse: &http.Response{ + Status: http.StatusText(http.StatusOK), + StatusCode: http.StatusOK, + Header: http.Header{}, + Trailer: http.Header{ + "Foo": []string{"Baz"}, + "Bar": []string{"Baz"}, + }, + }, + WantResponseBody: "OK", + }, { Description: "Undeclared trailer", Request: &http.Request{},