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