diff --git a/CHANGELOG.md b/CHANGELOG.md index b9a5a4916df..68c6eaa7ba7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Drop support for [Go 1.21]. (#6046, #6047) +### Fixed + +- Superfluous call to `WriteHeader` when writing the response body after setting a status code in `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp`. (#6055) + diff --git a/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go b/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go index aea171fb260..c5f2fa80524 100644 --- a/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go +++ b/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go @@ -44,7 +44,9 @@ func (w *RespWriterWrapper) Write(p []byte) (int, error) { w.mu.Lock() defer w.mu.Unlock() - w.writeHeader(http.StatusOK) + if !w.wroteHeader { + w.writeHeader(http.StatusOK) + } n, err := w.ResponseWriter.Write(p) n1 := int64(n) diff --git a/instrumentation/net/http/otelhttp/test/handler_test.go b/instrumentation/net/http/otelhttp/test/handler_test.go index 1f2034df6d5..780ec6fab54 100644 --- a/instrumentation/net/http/otelhttp/test/handler_test.go +++ b/instrumentation/net/http/otelhttp/test/handler_test.go @@ -250,6 +250,21 @@ func TestHandlerPropagateWriteHeaderCalls(t *testing.T) { }, expectHeadersWritten: []int{http.StatusInternalServerError, http.StatusOK}, }, + { + name: "When writing the header indirectly through body write", + handler: func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write([]byte("hello")) + }, + expectHeadersWritten: []int{http.StatusOK}, + }, + { + name: "With a header already written when writing the body", + handler: func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusBadRequest) + _, _ = w.Write([]byte("hello")) + }, + expectHeadersWritten: []int{http.StatusBadRequest}, + }, } for _, tc := range testCases {