1
2
3
4 package httpsnoop
5
6 import (
7 "bufio"
8 "io"
9 "net"
10 "net/http"
11 )
12
13
14 type HeaderFunc func() http.Header
15
16
17 type WriteHeaderFunc func(code int)
18
19
20 type WriteFunc func(b []byte) (int, error)
21
22
23 type FlushFunc func()
24
25
26 type CloseNotifyFunc func() <-chan bool
27
28
29 type HijackFunc func() (net.Conn, *bufio.ReadWriter, error)
30
31
32 type ReadFromFunc func(src io.Reader) (int64, error)
33
34
35 type PushFunc func(target string, opts *http.PushOptions) error
36
37
38
39
40 type Hooks struct {
41 Header func(HeaderFunc) HeaderFunc
42 WriteHeader func(WriteHeaderFunc) WriteHeaderFunc
43 Write func(WriteFunc) WriteFunc
44 Flush func(FlushFunc) FlushFunc
45 CloseNotify func(CloseNotifyFunc) CloseNotifyFunc
46 Hijack func(HijackFunc) HijackFunc
47 ReadFrom func(ReadFromFunc) ReadFromFunc
48 Push func(PushFunc) PushFunc
49 }
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter {
67 rw := &rw{w: w, h: hooks}
68 _, i0 := w.(http.Flusher)
69 _, i1 := w.(http.CloseNotifier)
70 _, i2 := w.(http.Hijacker)
71 _, i3 := w.(io.ReaderFrom)
72 _, i4 := w.(http.Pusher)
73 switch {
74
75 case !i0 && !i1 && !i2 && !i3 && !i4:
76 return struct {
77 Unwrapper
78 http.ResponseWriter
79 }{rw, rw}
80
81 case !i0 && !i1 && !i2 && !i3 && i4:
82 return struct {
83 Unwrapper
84 http.ResponseWriter
85 http.Pusher
86 }{rw, rw, rw}
87
88 case !i0 && !i1 && !i2 && i3 && !i4:
89 return struct {
90 Unwrapper
91 http.ResponseWriter
92 io.ReaderFrom
93 }{rw, rw, rw}
94
95 case !i0 && !i1 && !i2 && i3 && i4:
96 return struct {
97 Unwrapper
98 http.ResponseWriter
99 io.ReaderFrom
100 http.Pusher
101 }{rw, rw, rw, rw}
102
103 case !i0 && !i1 && i2 && !i3 && !i4:
104 return struct {
105 Unwrapper
106 http.ResponseWriter
107 http.Hijacker
108 }{rw, rw, rw}
109
110 case !i0 && !i1 && i2 && !i3 && i4:
111 return struct {
112 Unwrapper
113 http.ResponseWriter
114 http.Hijacker
115 http.Pusher
116 }{rw, rw, rw, rw}
117
118 case !i0 && !i1 && i2 && i3 && !i4:
119 return struct {
120 Unwrapper
121 http.ResponseWriter
122 http.Hijacker
123 io.ReaderFrom
124 }{rw, rw, rw, rw}
125
126 case !i0 && !i1 && i2 && i3 && i4:
127 return struct {
128 Unwrapper
129 http.ResponseWriter
130 http.Hijacker
131 io.ReaderFrom
132 http.Pusher
133 }{rw, rw, rw, rw, rw}
134
135 case !i0 && i1 && !i2 && !i3 && !i4:
136 return struct {
137 Unwrapper
138 http.ResponseWriter
139 http.CloseNotifier
140 }{rw, rw, rw}
141
142 case !i0 && i1 && !i2 && !i3 && i4:
143 return struct {
144 Unwrapper
145 http.ResponseWriter
146 http.CloseNotifier
147 http.Pusher
148 }{rw, rw, rw, rw}
149
150 case !i0 && i1 && !i2 && i3 && !i4:
151 return struct {
152 Unwrapper
153 http.ResponseWriter
154 http.CloseNotifier
155 io.ReaderFrom
156 }{rw, rw, rw, rw}
157
158 case !i0 && i1 && !i2 && i3 && i4:
159 return struct {
160 Unwrapper
161 http.ResponseWriter
162 http.CloseNotifier
163 io.ReaderFrom
164 http.Pusher
165 }{rw, rw, rw, rw, rw}
166
167 case !i0 && i1 && i2 && !i3 && !i4:
168 return struct {
169 Unwrapper
170 http.ResponseWriter
171 http.CloseNotifier
172 http.Hijacker
173 }{rw, rw, rw, rw}
174
175 case !i0 && i1 && i2 && !i3 && i4:
176 return struct {
177 Unwrapper
178 http.ResponseWriter
179 http.CloseNotifier
180 http.Hijacker
181 http.Pusher
182 }{rw, rw, rw, rw, rw}
183
184 case !i0 && i1 && i2 && i3 && !i4:
185 return struct {
186 Unwrapper
187 http.ResponseWriter
188 http.CloseNotifier
189 http.Hijacker
190 io.ReaderFrom
191 }{rw, rw, rw, rw, rw}
192
193 case !i0 && i1 && i2 && i3 && i4:
194 return struct {
195 Unwrapper
196 http.ResponseWriter
197 http.CloseNotifier
198 http.Hijacker
199 io.ReaderFrom
200 http.Pusher
201 }{rw, rw, rw, rw, rw, rw}
202
203 case i0 && !i1 && !i2 && !i3 && !i4:
204 return struct {
205 Unwrapper
206 http.ResponseWriter
207 http.Flusher
208 }{rw, rw, rw}
209
210 case i0 && !i1 && !i2 && !i3 && i4:
211 return struct {
212 Unwrapper
213 http.ResponseWriter
214 http.Flusher
215 http.Pusher
216 }{rw, rw, rw, rw}
217
218 case i0 && !i1 && !i2 && i3 && !i4:
219 return struct {
220 Unwrapper
221 http.ResponseWriter
222 http.Flusher
223 io.ReaderFrom
224 }{rw, rw, rw, rw}
225
226 case i0 && !i1 && !i2 && i3 && i4:
227 return struct {
228 Unwrapper
229 http.ResponseWriter
230 http.Flusher
231 io.ReaderFrom
232 http.Pusher
233 }{rw, rw, rw, rw, rw}
234
235 case i0 && !i1 && i2 && !i3 && !i4:
236 return struct {
237 Unwrapper
238 http.ResponseWriter
239 http.Flusher
240 http.Hijacker
241 }{rw, rw, rw, rw}
242
243 case i0 && !i1 && i2 && !i3 && i4:
244 return struct {
245 Unwrapper
246 http.ResponseWriter
247 http.Flusher
248 http.Hijacker
249 http.Pusher
250 }{rw, rw, rw, rw, rw}
251
252 case i0 && !i1 && i2 && i3 && !i4:
253 return struct {
254 Unwrapper
255 http.ResponseWriter
256 http.Flusher
257 http.Hijacker
258 io.ReaderFrom
259 }{rw, rw, rw, rw, rw}
260
261 case i0 && !i1 && i2 && i3 && i4:
262 return struct {
263 Unwrapper
264 http.ResponseWriter
265 http.Flusher
266 http.Hijacker
267 io.ReaderFrom
268 http.Pusher
269 }{rw, rw, rw, rw, rw, rw}
270
271 case i0 && i1 && !i2 && !i3 && !i4:
272 return struct {
273 Unwrapper
274 http.ResponseWriter
275 http.Flusher
276 http.CloseNotifier
277 }{rw, rw, rw, rw}
278
279 case i0 && i1 && !i2 && !i3 && i4:
280 return struct {
281 Unwrapper
282 http.ResponseWriter
283 http.Flusher
284 http.CloseNotifier
285 http.Pusher
286 }{rw, rw, rw, rw, rw}
287
288 case i0 && i1 && !i2 && i3 && !i4:
289 return struct {
290 Unwrapper
291 http.ResponseWriter
292 http.Flusher
293 http.CloseNotifier
294 io.ReaderFrom
295 }{rw, rw, rw, rw, rw}
296
297 case i0 && i1 && !i2 && i3 && i4:
298 return struct {
299 Unwrapper
300 http.ResponseWriter
301 http.Flusher
302 http.CloseNotifier
303 io.ReaderFrom
304 http.Pusher
305 }{rw, rw, rw, rw, rw, rw}
306
307 case i0 && i1 && i2 && !i3 && !i4:
308 return struct {
309 Unwrapper
310 http.ResponseWriter
311 http.Flusher
312 http.CloseNotifier
313 http.Hijacker
314 }{rw, rw, rw, rw, rw}
315
316 case i0 && i1 && i2 && !i3 && i4:
317 return struct {
318 Unwrapper
319 http.ResponseWriter
320 http.Flusher
321 http.CloseNotifier
322 http.Hijacker
323 http.Pusher
324 }{rw, rw, rw, rw, rw, rw}
325
326 case i0 && i1 && i2 && i3 && !i4:
327 return struct {
328 Unwrapper
329 http.ResponseWriter
330 http.Flusher
331 http.CloseNotifier
332 http.Hijacker
333 io.ReaderFrom
334 }{rw, rw, rw, rw, rw, rw}
335
336 case i0 && i1 && i2 && i3 && i4:
337 return struct {
338 Unwrapper
339 http.ResponseWriter
340 http.Flusher
341 http.CloseNotifier
342 http.Hijacker
343 io.ReaderFrom
344 http.Pusher
345 }{rw, rw, rw, rw, rw, rw, rw}
346 }
347 panic("unreachable")
348 }
349
350 type rw struct {
351 w http.ResponseWriter
352 h Hooks
353 }
354
355 func (w *rw) Unwrap() http.ResponseWriter {
356 return w.w
357 }
358
359 func (w *rw) Header() http.Header {
360 f := w.w.(http.ResponseWriter).Header
361 if w.h.Header != nil {
362 f = w.h.Header(f)
363 }
364 return f()
365 }
366
367 func (w *rw) WriteHeader(code int) {
368 f := w.w.(http.ResponseWriter).WriteHeader
369 if w.h.WriteHeader != nil {
370 f = w.h.WriteHeader(f)
371 }
372 f(code)
373 }
374
375 func (w *rw) Write(b []byte) (int, error) {
376 f := w.w.(http.ResponseWriter).Write
377 if w.h.Write != nil {
378 f = w.h.Write(f)
379 }
380 return f(b)
381 }
382
383 func (w *rw) Flush() {
384 f := w.w.(http.Flusher).Flush
385 if w.h.Flush != nil {
386 f = w.h.Flush(f)
387 }
388 f()
389 }
390
391 func (w *rw) CloseNotify() <-chan bool {
392 f := w.w.(http.CloseNotifier).CloseNotify
393 if w.h.CloseNotify != nil {
394 f = w.h.CloseNotify(f)
395 }
396 return f()
397 }
398
399 func (w *rw) Hijack() (net.Conn, *bufio.ReadWriter, error) {
400 f := w.w.(http.Hijacker).Hijack
401 if w.h.Hijack != nil {
402 f = w.h.Hijack(f)
403 }
404 return f()
405 }
406
407 func (w *rw) ReadFrom(src io.Reader) (int64, error) {
408 f := w.w.(io.ReaderFrom).ReadFrom
409 if w.h.ReadFrom != nil {
410 f = w.h.ReadFrom(f)
411 }
412 return f(src)
413 }
414
415 func (w *rw) Push(target string, opts *http.PushOptions) error {
416 f := w.w.(http.Pusher).Push
417 if w.h.Push != nil {
418 f = w.h.Push(f)
419 }
420 return f(target, opts)
421 }
422
423 type Unwrapper interface {
424 Unwrap() http.ResponseWriter
425 }
426
427
428
429 func Unwrap(w http.ResponseWriter) http.ResponseWriter {
430 if rw, ok := w.(Unwrapper); ok {
431
432 return Unwrap(rw.Unwrap())
433 } else {
434 return w
435 }
436 }
437
View as plain text