status-code-tracker.go 5.4 KB

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