Skip to content

Commit d86cd75

Browse files
committed
Implement http.ResponseWriter unwrapping like http.ResponseController
Since we rely on the connection not being hijacked too early (i.e. detecting the presence of http.Hijacker) to set headers, we must manually implement the unwrapping of the http.ResponseController. By doing so, we also retain Go 1.19 compatibility without build tags. Fixes #455
1 parent e46e020 commit d86cd75

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

accept.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func accept(w http.ResponseWriter, r *http.Request, opts *AcceptOptions) (_ *Con
105105
}
106106
}
107107

108-
hj, ok := w.(http.Hijacker)
108+
hj, ok := hijacker(w)
109109
if !ok {
110110
err = errors.New("http.ResponseWriter does not implement http.Hijacker")
111111
http.Error(w, http.StatusText(http.StatusNotImplemented), http.StatusNotImplemented)

hijack.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package websocket
2+
3+
import (
4+
"net/http"
5+
)
6+
7+
type rwUnwrapper interface {
8+
Unwrap() http.ResponseWriter
9+
}
10+
11+
// hijacker returns the Hijacker interface of the http.ResponseWriter.
12+
// It follows the Unwrap method of the http.ResponseWriter if available,
13+
// matching the behavior of http.ResponseController. If the Hijacker
14+
// interface is not found, it returns false.
15+
//
16+
// Since the http.ResponseController is not available in Go 1.19, and
17+
// does not support checking the presence of the Hijacker interface,
18+
// this function is used to provide a consistent way to check for the
19+
// Hijacker interface across Go versions.
20+
func hijacker(rw http.ResponseWriter) (http.Hijacker, bool) {
21+
for {
22+
switch t := rw.(type) {
23+
case http.Hijacker:
24+
return t, true
25+
case rwUnwrapper:
26+
rw = t.Unwrap()
27+
default:
28+
return nil, false
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)