Skip to content

Commit 121aeb2

Browse files
authored
feat(http): make interceptingWriter reimplement common interfaces from stdlib. (#1212)
successor to #1093 and closes #1092.
1 parent 513a72b commit 121aeb2

File tree

3 files changed

+1297
-20
lines changed

3 files changed

+1297
-20
lines changed

transport/http/intercepting_writer.go

+257
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
package http
2+
3+
import (
4+
"io"
5+
"net/http"
6+
)
7+
8+
type interceptingWriter struct {
9+
http.ResponseWriter
10+
code int
11+
written int64
12+
}
13+
14+
// WriteHeader may not be explicitly called, so care must be taken to
15+
// initialize w.code to its default value of http.StatusOK.
16+
func (w *interceptingWriter) WriteHeader(code int) {
17+
w.code = code
18+
w.ResponseWriter.WriteHeader(code)
19+
}
20+
21+
func (w *interceptingWriter) Write(p []byte) (int, error) {
22+
n, err := w.ResponseWriter.Write(p)
23+
w.written += int64(n)
24+
return n, err
25+
}
26+
27+
// reimplementInterfaces returns a wrapped version of the embedded ResponseWriter
28+
// and selectively implements the same combination of additional interfaces as
29+
// the wrapped one. The interfaces it may implement are: http.Hijacker,
30+
// http.CloseNotifier, http.Pusher, http.Flusher and io.ReaderFrom. The standard
31+
// library is known to assert the existence of these interfaces and behaves
32+
// differently. This implementation is derived from
33+
// https://github.com/felixge/httpsnoop.
34+
func (w *interceptingWriter) reimplementInterfaces() http.ResponseWriter {
35+
var (
36+
hj, i0 = w.ResponseWriter.(http.Hijacker)
37+
cn, i1 = w.ResponseWriter.(http.CloseNotifier)
38+
pu, i2 = w.ResponseWriter.(http.Pusher)
39+
fl, i3 = w.ResponseWriter.(http.Flusher)
40+
rf, i4 = w.ResponseWriter.(io.ReaderFrom)
41+
)
42+
43+
switch {
44+
case !i0 && !i1 && !i2 && !i3 && !i4:
45+
return struct {
46+
http.ResponseWriter
47+
}{w}
48+
case !i0 && !i1 && !i2 && !i3 && i4:
49+
return struct {
50+
http.ResponseWriter
51+
io.ReaderFrom
52+
}{w, rf}
53+
case !i0 && !i1 && !i2 && i3 && !i4:
54+
return struct {
55+
http.ResponseWriter
56+
http.Flusher
57+
}{w, fl}
58+
case !i0 && !i1 && !i2 && i3 && i4:
59+
return struct {
60+
http.ResponseWriter
61+
http.Flusher
62+
io.ReaderFrom
63+
}{w, fl, rf}
64+
case !i0 && !i1 && i2 && !i3 && !i4:
65+
return struct {
66+
http.ResponseWriter
67+
http.Pusher
68+
}{w, pu}
69+
case !i0 && !i1 && i2 && !i3 && i4:
70+
return struct {
71+
http.ResponseWriter
72+
http.Pusher
73+
io.ReaderFrom
74+
}{w, pu, rf}
75+
case !i0 && !i1 && i2 && i3 && !i4:
76+
return struct {
77+
http.ResponseWriter
78+
http.Pusher
79+
http.Flusher
80+
}{w, pu, fl}
81+
case !i0 && !i1 && i2 && i3 && i4:
82+
return struct {
83+
http.ResponseWriter
84+
http.Pusher
85+
http.Flusher
86+
io.ReaderFrom
87+
}{w, pu, fl, rf}
88+
case !i0 && i1 && !i2 && !i3 && !i4:
89+
return struct {
90+
http.ResponseWriter
91+
http.CloseNotifier
92+
}{w, cn}
93+
case !i0 && i1 && !i2 && !i3 && i4:
94+
return struct {
95+
http.ResponseWriter
96+
http.CloseNotifier
97+
io.ReaderFrom
98+
}{w, cn, rf}
99+
case !i0 && i1 && !i2 && i3 && !i4:
100+
return struct {
101+
http.ResponseWriter
102+
http.CloseNotifier
103+
http.Flusher
104+
}{w, cn, fl}
105+
case !i0 && i1 && !i2 && i3 && i4:
106+
return struct {
107+
http.ResponseWriter
108+
http.CloseNotifier
109+
http.Flusher
110+
io.ReaderFrom
111+
}{w, cn, fl, rf}
112+
case !i0 && i1 && i2 && !i3 && !i4:
113+
return struct {
114+
http.ResponseWriter
115+
http.CloseNotifier
116+
http.Pusher
117+
}{w, cn, pu}
118+
case !i0 && i1 && i2 && !i3 && i4:
119+
return struct {
120+
http.ResponseWriter
121+
http.CloseNotifier
122+
http.Pusher
123+
io.ReaderFrom
124+
}{w, cn, pu, rf}
125+
case !i0 && i1 && i2 && i3 && !i4:
126+
return struct {
127+
http.ResponseWriter
128+
http.CloseNotifier
129+
http.Pusher
130+
http.Flusher
131+
}{w, cn, pu, fl}
132+
case !i0 && i1 && i2 && i3 && i4:
133+
return struct {
134+
http.ResponseWriter
135+
http.CloseNotifier
136+
http.Pusher
137+
http.Flusher
138+
io.ReaderFrom
139+
}{w, cn, pu, fl, rf}
140+
case i0 && !i1 && !i2 && !i3 && !i4:
141+
return struct {
142+
http.ResponseWriter
143+
http.Hijacker
144+
}{w, hj}
145+
case i0 && !i1 && !i2 && !i3 && i4:
146+
return struct {
147+
http.ResponseWriter
148+
http.Hijacker
149+
io.ReaderFrom
150+
}{w, hj, rf}
151+
case i0 && !i1 && !i2 && i3 && !i4:
152+
return struct {
153+
http.ResponseWriter
154+
http.Hijacker
155+
http.Flusher
156+
}{w, hj, fl}
157+
case i0 && !i1 && !i2 && i3 && i4:
158+
return struct {
159+
http.ResponseWriter
160+
http.Hijacker
161+
http.Flusher
162+
io.ReaderFrom
163+
}{w, hj, fl, rf}
164+
case i0 && !i1 && i2 && !i3 && !i4:
165+
return struct {
166+
http.ResponseWriter
167+
http.Hijacker
168+
http.Pusher
169+
}{w, hj, pu}
170+
case i0 && !i1 && i2 && !i3 && i4:
171+
return struct {
172+
http.ResponseWriter
173+
http.Hijacker
174+
http.Pusher
175+
io.ReaderFrom
176+
}{w, hj, pu, rf}
177+
case i0 && !i1 && i2 && i3 && !i4:
178+
return struct {
179+
http.ResponseWriter
180+
http.Hijacker
181+
http.Pusher
182+
http.Flusher
183+
}{w, hj, pu, fl}
184+
case i0 && !i1 && i2 && i3 && i4:
185+
return struct {
186+
http.ResponseWriter
187+
http.Hijacker
188+
http.Pusher
189+
http.Flusher
190+
io.ReaderFrom
191+
}{w, hj, pu, fl, rf}
192+
case i0 && i1 && !i2 && !i3 && !i4:
193+
return struct {
194+
http.ResponseWriter
195+
http.Hijacker
196+
http.CloseNotifier
197+
}{w, hj, cn}
198+
case i0 && i1 && !i2 && !i3 && i4:
199+
return struct {
200+
http.ResponseWriter
201+
http.Hijacker
202+
http.CloseNotifier
203+
io.ReaderFrom
204+
}{w, hj, cn, rf}
205+
case i0 && i1 && !i2 && i3 && !i4:
206+
return struct {
207+
http.ResponseWriter
208+
http.Hijacker
209+
http.CloseNotifier
210+
http.Flusher
211+
}{w, hj, cn, fl}
212+
case i0 && i1 && !i2 && i3 && i4:
213+
return struct {
214+
http.ResponseWriter
215+
http.Hijacker
216+
http.CloseNotifier
217+
http.Flusher
218+
io.ReaderFrom
219+
}{w, hj, cn, fl, rf}
220+
case i0 && i1 && i2 && !i3 && !i4:
221+
return struct {
222+
http.ResponseWriter
223+
http.Hijacker
224+
http.CloseNotifier
225+
http.Pusher
226+
}{w, hj, cn, pu}
227+
case i0 && i1 && i2 && !i3 && i4:
228+
return struct {
229+
http.ResponseWriter
230+
http.Hijacker
231+
http.CloseNotifier
232+
http.Pusher
233+
io.ReaderFrom
234+
}{w, hj, cn, pu, rf}
235+
case i0 && i1 && i2 && i3 && !i4:
236+
return struct {
237+
http.ResponseWriter
238+
http.Hijacker
239+
http.CloseNotifier
240+
http.Pusher
241+
http.Flusher
242+
}{w, hj, cn, pu, fl}
243+
case i0 && i1 && i2 && i3 && i4:
244+
return struct {
245+
http.ResponseWriter
246+
http.Hijacker
247+
http.CloseNotifier
248+
http.Pusher
249+
http.Flusher
250+
io.ReaderFrom
251+
}{w, hj, cn, pu, fl, rf}
252+
default:
253+
return struct {
254+
http.ResponseWriter
255+
}{w}
256+
}
257+
}

0 commit comments

Comments
 (0)