Skip to content

Commit

Permalink
caddyhttp: Impl ResponseWriter.Unwrap(), prep for Go 1.20's `Respon…
Browse files Browse the repository at this point in the history
…seController` (#5509)

* feat: add support for ResponseWriter.Unwrap()

* cherry-pick Francis' code
  • Loading branch information
dunglas authored Apr 26, 2023
1 parent 2b04e09 commit 1c9ea01
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 0 deletions.
6 changes: 6 additions & 0 deletions metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,9 @@ func (d *delegator) WriteHeader(code int) {
d.status = code
d.ResponseWriter.WriteHeader(code)
}

// Unwrap returns the underlying ResponseWriter, necessary for
// http.ResponseController to work correctly.
func (d *delegator) Unwrap() http.ResponseWriter {
return d.ResponseWriter
}
5 changes: 5 additions & 0 deletions modules/caddyhttp/encode/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ func (rw *responseWriter) Close() error {
return err
}

// Unwrap returns the underlying ResponseWriter.
func (rw *responseWriter) Unwrap() http.ResponseWriter {
return rw.HTTPInterfaces
}

// init should be called before we write a response, if rw.buf has contents.
func (rw *responseWriter) init() {
if rw.Header().Get("Content-Encoding") == "" && isEncodeAllowed(rw.Header()) &&
Expand Down
6 changes: 6 additions & 0 deletions modules/caddyhttp/fileserver/staticfiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,12 @@ func (wr statusOverrideResponseWriter) WriteHeader(int) {
wr.ResponseWriter.WriteHeader(wr.code)
}

// Unwrap returns the underlying ResponseWriter, necessary for
// http.ResponseController to work correctly.
func (wr statusOverrideResponseWriter) Unwrap() http.ResponseWriter {
return wr.ResponseWriter
}

// osFS is a simple fs.FS implementation that uses the local
// file system. (We do not use os.DirFS because we do our own
// rooting or path prefixing without being constrained to a single
Expand Down
5 changes: 5 additions & 0 deletions modules/caddyhttp/responsewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ func (rww *ResponseWriterWrapper) ReadFrom(r io.Reader) (n int64, err error) {
return io.Copy(rww.ResponseWriter, r)
}

// Unwrap returns the underlying ResponseWriter.
func (rww *ResponseWriterWrapper) Unwrap() http.ResponseWriter {
return rww.ResponseWriter
}

// HTTPInterfaces mix all the interfaces that middleware ResponseWriters need to support.
type HTTPInterfaces interface {
http.ResponseWriter
Expand Down
8 changes: 8 additions & 0 deletions modules/caddyhttp/responsewriter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ func TestResponseWriterWrapperReadFrom(t *testing.T) {
}
}

func TestResponseWriterWrapperUnwrap(t *testing.T) {
w := &ResponseWriterWrapper{&baseRespWriter{}}

if _, ok := w.Unwrap().(*baseRespWriter); !ok {
t.Errorf("Unwrap() doesn't return the underlying ResponseWriter")
}
}

func TestResponseRecorderReadFrom(t *testing.T) {
tests := map[string]struct {
responseWriter responseWriterSpy
Expand Down

0 comments on commit 1c9ea01

Please sign in to comment.