response_writer.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. package context
  2. import (
  3. "bufio"
  4. "errors"
  5. "io"
  6. "net"
  7. "net/http"
  8. "sync"
  9. )
  10. // ResponseWriter interface is used by the context to serve an HTTP handler to
  11. // construct an HTTP response.
  12. //
  13. // Note: Only this ResponseWriter is an interface in order to be able
  14. // for developers to change the response writer of the Context via `context.ResetResponseWriter`.
  15. // The rest of the response writers implementations (ResponseRecorder & CompressResponseWriter)
  16. // are coupled to the internal ResponseWriter implementation(*responseWriter).
  17. //
  18. // A ResponseWriter may not be used after the Handler
  19. // has returned.
  20. type ResponseWriter interface {
  21. http.ResponseWriter
  22. // Naive returns the simple, underline and original http.ResponseWriter
  23. // that backends this response writer.
  24. Naive() http.ResponseWriter
  25. // SetWriter sets the underline http.ResponseWriter
  26. // that this responseWriter should write on.
  27. SetWriter(underline http.ResponseWriter)
  28. // BeginResponse receives an http.ResponseWriter
  29. // and initialize or reset the response writer's field's values.
  30. BeginResponse(http.ResponseWriter)
  31. // EndResponse is the last function which is called right before the server sent the final response.
  32. //
  33. // Here is the place which we can make the last checks or do a cleanup.
  34. EndResponse()
  35. // IsHijacked reports whether this response writer's connection is hijacked.
  36. IsHijacked() bool
  37. // StatusCode returns the status code header value.
  38. StatusCode() int
  39. // Written should returns the total length of bytes that were being written to the client.
  40. // In addition iris provides some variables to help low-level actions:
  41. // NoWritten, means that nothing were written yet and the response writer is still live.
  42. // StatusCodeWritten, means that status code was written but no other bytes are written to the client, response writer may closed.
  43. // > 0 means that the reply was written and it's the total number of bytes were written.
  44. Written() int
  45. // SetWritten sets manually a value for written, it can be
  46. // NoWritten(-1) or StatusCodeWritten(0), > 0 means body length which is useless here.
  47. SetWritten(int)
  48. // SetBeforeFlush registers the unique callback which called exactly before the response is flushed to the client.
  49. SetBeforeFlush(cb func())
  50. // GetBeforeFlush returns (not execute) the before flush callback, or nil if not set by SetBeforeFlush.
  51. GetBeforeFlush() func()
  52. // FlushResponse should be called only once before EndResponse.
  53. // it tries to send the status code if not sent already
  54. // and calls the before flush callback, if any.
  55. //
  56. // FlushResponse can be called before EndResponse, but it should
  57. // be the last call of this response writer.
  58. FlushResponse()
  59. // clone returns a clone of this response writer
  60. // it copies the header, status code, headers and the beforeFlush finally returns a new ResponseRecorder.
  61. Clone() ResponseWriter
  62. // CopyTo writes a response writer (temp: status code, headers and body) to another response writer
  63. CopyTo(ResponseWriter)
  64. // Flusher indicates if `Flush` is supported by the client.
  65. //
  66. // The default HTTP/1.x and HTTP/2 ResponseWriter implementations
  67. // support Flusher, but ResponseWriter wrappers may not. Handlers
  68. // should always test for this ability at runtime.
  69. //
  70. // Note that even for ResponseWriters that support Flush,
  71. // if the client is connected through an HTTP proxy,
  72. // the buffered data may not reach the client until the response
  73. // completes.
  74. Flusher() (http.Flusher, bool)
  75. // Flush sends any buffered data to the client.
  76. Flush() // required by compress writer.
  77. }
  78. // ResponseWriterBodyReseter can be implemented by
  79. // response writers that supports response body overriding
  80. // (e.g. recorder and compressed).
  81. type ResponseWriterBodyReseter interface {
  82. // ResetBody should reset the body and reports back if it could reset successfully.
  83. ResetBody()
  84. }
  85. // ResponseWriterDisabler can be implemented
  86. // by response writers that can be disabled and restored to their previous state
  87. // (e.g. compressed).
  88. type ResponseWriterDisabler interface {
  89. // Disable should disable this type of response writer and fallback to the default one.
  90. Disable()
  91. }
  92. // ResponseWriterReseter can be implemented
  93. // by response writers that can clear the whole response
  94. // so a new handler can write into this from the beginning.
  95. // E.g. recorder, compressed (full) and common writer (status code and headers).
  96. type ResponseWriterReseter interface {
  97. // Reset should reset the whole response and reports
  98. // whether it could reset successfully.
  99. Reset() bool
  100. }
  101. // ResponseWriterWriteTo can be implemented
  102. // by response writers that needs a special
  103. // encoding before writing to their buffers.
  104. // E.g. a custom recorder that wraps a custom compressed one.
  105. //
  106. // Not used by the framework itself.
  107. type ResponseWriterWriteTo interface {
  108. WriteTo(dest io.Writer, p []byte)
  109. }
  110. // +------------------------------------------------------------+
  111. // | Response Writer Implementation |
  112. // +------------------------------------------------------------+
  113. var rpool = sync.Pool{New: func() interface{} { return &responseWriter{} }}
  114. // AcquireResponseWriter returns a new *ResponseWriter from the pool.
  115. // Releasing is done automatically when request and response is done.
  116. func AcquireResponseWriter() ResponseWriter {
  117. return rpool.Get().(*responseWriter)
  118. }
  119. func releaseResponseWriter(w ResponseWriter) {
  120. rpool.Put(w)
  121. }
  122. // ResponseWriter is the basic response writer,
  123. // it writes directly to the underline http.ResponseWriter
  124. type responseWriter struct {
  125. http.ResponseWriter
  126. statusCode int // the saved status code which will be used from the cache service
  127. // statusCodeSent bool // reply header has been (logically) written | no needed any more as we have a variable to catch total len of written bytes
  128. written int // the total size of bytes were written
  129. // yes only one callback, we need simplicity here because on FireStatusCode the beforeFlush events should NOT be cleared
  130. // but the response is cleared.
  131. // Sometimes is useful to keep the event,
  132. // so we keep one func only and let the user decide when he/she wants to override it with an empty func before the FireStatusCode (context's behavior)
  133. beforeFlush func()
  134. }
  135. var _ ResponseWriter = (*responseWriter)(nil)
  136. const (
  137. defaultStatusCode = http.StatusOK
  138. // NoWritten !=-1 => when nothing written before
  139. NoWritten = -1
  140. // StatusCodeWritten != 0 => when only status code written
  141. StatusCodeWritten = 0
  142. )
  143. // Naive returns the simple, underline and original http.ResponseWriter
  144. // that backends this response writer.
  145. func (w *responseWriter) Naive() http.ResponseWriter {
  146. return w.ResponseWriter
  147. }
  148. // BeginResponse receives an http.ResponseWriter
  149. // and initialize or reset the response writer's field's values.
  150. func (w *responseWriter) BeginResponse(underline http.ResponseWriter) {
  151. w.beforeFlush = nil
  152. w.written = NoWritten
  153. w.statusCode = defaultStatusCode
  154. w.SetWriter(underline)
  155. }
  156. // SetWriter sets the underline http.ResponseWriter
  157. // that this responseWriter should write on.
  158. func (w *responseWriter) SetWriter(underline http.ResponseWriter) {
  159. w.ResponseWriter = underline
  160. }
  161. // EndResponse is the last function which is called right before the server sent the final response.
  162. //
  163. // Here is the place which we can make the last checks or do a cleanup.
  164. func (w *responseWriter) EndResponse() {
  165. releaseResponseWriter(w)
  166. }
  167. // Reset clears headers, sets the status code to 200
  168. // and clears the cached body.
  169. //
  170. // Implements the `ResponseWriterReseter`.
  171. func (w *responseWriter) Reset() bool {
  172. if w.written > 0 {
  173. return false // if already written we can't reset this type of response writer.
  174. }
  175. h := w.Header()
  176. for k := range h {
  177. h[k] = nil
  178. }
  179. w.written = NoWritten
  180. w.statusCode = defaultStatusCode
  181. return true
  182. }
  183. // SetWritten sets manually a value for written, it can be
  184. // NoWritten(-1) or StatusCodeWritten(0), > 0 means body length which is useless here.
  185. func (w *responseWriter) SetWritten(n int) {
  186. if n >= NoWritten && n <= StatusCodeWritten {
  187. w.written = n
  188. }
  189. }
  190. // Written should returns the total length of bytes that were being written to the client.
  191. // In addition iris provides some variables to help low-level actions:
  192. // NoWritten, means that nothing were written yet and the response writer is still live.
  193. // StatusCodeWritten, means that status code were written but no other bytes are written to the client, response writer may closed.
  194. // > 0 means that the reply was written and it's the total number of bytes were written.
  195. func (w *responseWriter) Written() int {
  196. return w.written
  197. }
  198. // WriteHeader sends an HTTP response header with status code.
  199. // If WriteHeader is not called explicitly, the first call to Write
  200. // will trigger an implicit WriteHeader(http.StatusOK).
  201. // Thus explicit calls to WriteHeader are mainly used to
  202. // send error codes.
  203. func (w *responseWriter) WriteHeader(statusCode int) {
  204. w.statusCode = statusCode
  205. }
  206. func (w *responseWriter) tryWriteHeader() {
  207. if w.written == NoWritten { // before write, once.
  208. w.written = StatusCodeWritten
  209. w.ResponseWriter.WriteHeader(w.statusCode)
  210. }
  211. }
  212. // IsHijacked reports whether this response writer's connection is hijacked.
  213. func (w *responseWriter) IsHijacked() bool {
  214. // Note:
  215. // A zero-byte `ResponseWriter.Write` on a hijacked connection will
  216. // return `http.ErrHijacked` without any other side effects.
  217. _, err := w.ResponseWriter.Write(nil)
  218. return err == http.ErrHijacked
  219. }
  220. // Write writes to the client
  221. // If WriteHeader has not yet been called, Write calls
  222. // WriteHeader(http.StatusOK) before writing the data. If the Header
  223. // does not contain a Content-Type line, Write adds a Content-Type set
  224. // to the result of passing the initial 512 bytes of written data to
  225. // DetectContentType.
  226. //
  227. // Depending on the HTTP protocol version and the client, calling
  228. // Write or WriteHeader may prevent future reads on the
  229. // Request.Body. For HTTP/1.x requests, handlers should read any
  230. // needed request body data before writing the response. Once the
  231. // headers have been flushed (due to either an explicit Flusher.Flush
  232. // call or writing enough data to trigger a flush), the request body
  233. // may be unavailable. For HTTP/2 requests, the Go HTTP server permits
  234. // handlers to continue to read the request body while concurrently
  235. // writing the response. However, such behavior may not be supported
  236. // by all HTTP/2 clients. Handlers should read before writing if
  237. // possible to maximize compatibility.
  238. func (w *responseWriter) Write(contents []byte) (int, error) {
  239. w.tryWriteHeader()
  240. n, err := w.ResponseWriter.Write(contents)
  241. w.written += n
  242. return n, err
  243. }
  244. // StatusCode returns the status code header value
  245. func (w *responseWriter) StatusCode() int {
  246. return w.statusCode
  247. }
  248. func (w *responseWriter) GetBeforeFlush() func() {
  249. return w.beforeFlush
  250. }
  251. // SetBeforeFlush registers the unique callback which called exactly before the response is flushed to the client
  252. func (w *responseWriter) SetBeforeFlush(cb func()) {
  253. w.beforeFlush = cb
  254. }
  255. func (w *responseWriter) FlushResponse() {
  256. if w.beforeFlush != nil {
  257. w.beforeFlush()
  258. }
  259. w.tryWriteHeader()
  260. }
  261. // Clone returns a clone of this response writer
  262. // it copies the header, status code, headers and the beforeFlush finally returns a new ResponseRecorder.
  263. func (w *responseWriter) Clone() ResponseWriter {
  264. wc := &responseWriter{}
  265. wc.ResponseWriter = w.ResponseWriter
  266. wc.statusCode = w.statusCode
  267. wc.beforeFlush = w.beforeFlush
  268. wc.written = w.written
  269. return wc
  270. }
  271. // CopyTo writes a response writer (temp: status code, headers and body) to another response writer.
  272. func (w *responseWriter) CopyTo(to ResponseWriter) {
  273. // set the status code, failure status code are first class
  274. if w.statusCode >= 400 {
  275. to.WriteHeader(w.statusCode)
  276. }
  277. // append the headers
  278. for k, values := range w.Header() {
  279. for _, v := range values {
  280. if to.Header().Get(v) == "" {
  281. to.Header().Add(k, v)
  282. }
  283. }
  284. }
  285. // the body is not copied, this writer doesn't support recording
  286. }
  287. // ErrHijackNotSupported is returned by the Hijack method to
  288. // indicate that Hijack feature is not available.
  289. var ErrHijackNotSupported = errors.New("hijack is not supported by this ResponseWriter")
  290. // Hijack lets the caller take over the connection.
  291. // After a call to Hijack(), the HTTP server library
  292. // will not do anything else with the connection.
  293. //
  294. // It becomes the caller's responsibility to manage
  295. // and close the connection.
  296. //
  297. // The returned net.Conn may have read or write deadlines
  298. // already set, depending on the configuration of the
  299. // Server. It is the caller's responsibility to set
  300. // or clear those deadlines as needed.
  301. func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  302. if h, isHijacker := w.ResponseWriter.(http.Hijacker); isHijacker {
  303. w.written = StatusCodeWritten
  304. return h.Hijack()
  305. }
  306. return nil, nil, ErrHijackNotSupported
  307. }
  308. // Flusher indicates if `Flush` is supported by the client.
  309. //
  310. // The default HTTP/1.x and HTTP/2 ResponseWriter implementations
  311. // support Flusher, but ResponseWriter wrappers may not. Handlers
  312. // should always test for this ability at runtime.
  313. //
  314. // Note that even for ResponseWriters that support Flush,
  315. // if the client is connected through an HTTP proxy,
  316. // the buffered data may not reach the client until the response
  317. // completes.
  318. func (w *responseWriter) Flusher() (http.Flusher, bool) {
  319. flusher, canFlush := w.ResponseWriter.(http.Flusher)
  320. return flusher, canFlush
  321. }
  322. // Flush sends any buffered data to the client.
  323. func (w *responseWriter) Flush() {
  324. if flusher, ok := w.Flusher(); ok {
  325. // Flow: WriteHeader -> Flush -> Write -> Write -> Write....
  326. w.tryWriteHeader()
  327. flusher.Flush()
  328. }
  329. }