Skip to content

Commit

Permalink
Documenting how otelhttp.Handler allows propagating WriteHeader calls
Browse files Browse the repository at this point in the history
We explicitly capture initial statusCode written while propagating all
consecutive calls to the wrapped ResponseWriter without altering state.
  • Loading branch information
jarlefosen committed Mar 17, 2023
1 parent 5454b80 commit a9ecdc7
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 3 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

- Add the new `go.opentelemetry.io/contrib/instrgen` package to provide auto-generated source code instrumentation. (#3068)

### Changed
### Fixed

- Remove early return in `respWriterWrapper` in `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` to avoid blocking multiple calls to underlying ResponseWriter.WriteHeader. (#3580)
- Enable `otelhttp.Handler` to propagate multiple WriteHeader calls while persisting initial statusCode in `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp`. (#3580)

## [1.16.0-rc.1/0.41.0-rc.1/0.9.0-rc.1] - 2023-03-02

Expand Down
7 changes: 6 additions & 1 deletion instrumentation/net/http/otelhttp/wrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (w *bodyWrapper) Close() error {
var _ http.ResponseWriter = &respWriterWrapper{}

// respWriterWrapper wraps a http.ResponseWriter in order to track the number of
// bytes written, the last error, and to catch the returned statusCode
// bytes written, the last error, and to catch the first written statusCode.
// TODO: The wrapped http.ResponseWriter doesn't implement any of the optional
// types (http.Hijacker, http.Pusher, http.CloseNotifier, http.Flusher, etc)
// that may be useful when using it in real life situations.
Expand Down Expand Up @@ -85,6 +85,11 @@ func (w *respWriterWrapper) Write(p []byte) (int, error) {
return n, err
}

// WriteHeader persists initial statusCode for span attribution.
// All calls to WriteHeader will be propagated to the underlying ResponseWriter
// but will not overwrite persisted statusCode.
// Blocking consecutive calls to WriteHeader alters expected behavior and will
// remove warning logs from net/http where developers will notice incorrect handler implementations.
func (w *respWriterWrapper) WriteHeader(statusCode int) {
if !w.wroteHeader {
w.wroteHeader = true
Expand Down

0 comments on commit a9ecdc7

Please sign in to comment.