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