response_writer.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. package context
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "net"
  7. "net/http"
  8. "sync"
  9. "github.com/kataras/iris/core/errors"
  10. )
  11. // ResponseWriter interface is used by the context to serve an HTTP handler to
  12. // construct an HTTP response.
  13. //
  14. // Note: Only this ResponseWriter is an interface in order to be able
  15. // for developers to change the response writer of the Context via `context.ResetResponseWriter`.
  16. // The rest of the response writers implementations (ResponseRecorder & GzipResponseWriter) are coupled to the internal
  17. // ResponseWriter implementation(*responseWriter).
  18. //
  19. // A ResponseWriter may not be used after the Handler
  20. // has returned.
  21. type ResponseWriter interface {
  22. http.ResponseWriter
  23. http.Flusher
  24. http.Hijacker
  25. http.CloseNotifier
  26. http.Pusher
  27. // Naive returns the simple, underline and original http.ResponseWriter
  28. // that backends this response writer.
  29. Naive() http.ResponseWriter
  30. // BeginResponse receives an http.ResponseWriter
  31. // and initialize or reset the response writer's field's values.
  32. BeginResponse(http.ResponseWriter)
  33. // EndResponse is the last function which is called right before the server sent the final response.
  34. //
  35. // Here is the place which we can make the last checks or do a cleanup.
  36. EndResponse()
  37. // Writef formats according to a format specifier and writes to the response.
  38. //
  39. // Returns the number of bytes written and any write error encountered.
  40. Writef(format string, a ...interface{}) (n int, err error)
  41. // WriteString writes a simple string to the response.
  42. //
  43. // Returns the number of bytes written and any write error encountered.
  44. WriteString(s string) (n int, err error)
  45. // StatusCode returns the status code header value.
  46. StatusCode() int
  47. // Written should returns the total length of bytes that were being written to the client.
  48. // In addition iris provides some variables to help low-level actions:
  49. // NoWritten, means that nothing were written yet and the response writer is still live.
  50. // StatusCodeWritten, means that status code were written but no other bytes are written to the client, response writer may closed.
  51. // > 0 means that the reply was written and it's the total number of bytes were written.
  52. Written() int
  53. // SetWritten sets manually a value for written, it can be
  54. // NoWritten(-1) or StatusCodeWritten(0), > 0 means body length which is useless here.
  55. SetWritten(int)
  56. // SetBeforeFlush registers the unique callback which called exactly before the response is flushed to the client.
  57. SetBeforeFlush(cb func())
  58. // GetBeforeFlush returns (not execute) the before flush callback, or nil if not setted by SetBeforeFlush.
  59. GetBeforeFlush() func()
  60. // FlushResponse should be called only once before EndResponse.
  61. // it tries to send the status code if not sent already
  62. // and calls the before flush callback, if any.
  63. //
  64. // FlushResponse can be called before EndResponse, but it should
  65. // be the last call of this response writer.
  66. FlushResponse()
  67. // clone returns a clone of this response writer
  68. // it copies the header, status code, headers and the beforeFlush finally returns a new ResponseRecorder.
  69. Clone() ResponseWriter
  70. // WiteTo writes a response writer (temp: status code, headers and body) to another response writer
  71. WriteTo(ResponseWriter)
  72. // Flusher indicates if `Flush` is supported by the client.
  73. //
  74. // The default HTTP/1.x and HTTP/2 ResponseWriter implementations
  75. // support Flusher, but ResponseWriter wrappers may not. Handlers
  76. // should always test for this ability at runtime.
  77. //
  78. // Note that even for ResponseWriters that support Flush,
  79. // if the client is connected through an HTTP proxy,
  80. // the buffered data may not reach the client until the response
  81. // completes.
  82. Flusher() (http.Flusher, bool)
  83. // CloseNotifier indicates if the protocol supports the underline connection closure notification.
  84. CloseNotifier() (http.CloseNotifier, bool)
  85. }
  86. // +------------------------------------------------------------+
  87. // | Response Writer Implementation |
  88. // +------------------------------------------------------------+
  89. var rpool = sync.Pool{New: func() interface{} { return &responseWriter{} }}
  90. // AcquireResponseWriter returns a new *ResponseWriter from the pool.
  91. // Releasing is done automatically when request and response is done.
  92. func AcquireResponseWriter() ResponseWriter {
  93. return rpool.Get().(*responseWriter)
  94. }
  95. func releaseResponseWriter(w ResponseWriter) {
  96. rpool.Put(w)
  97. }
  98. // ResponseWriter is the basic response writer,
  99. // it writes directly to the underline http.ResponseWriter
  100. type responseWriter struct {
  101. http.ResponseWriter
  102. statusCode int // the saved status code which will be used from the cache service
  103. // statusCodeSent bool // reply header has been (logically) written | no needed any more as we have a variable to catch total len of written bytes
  104. written int // the total size of bytes were written
  105. // yes only one callback, we need simplicity here because on FireStatusCode the beforeFlush events should NOT be cleared
  106. // but the response is cleared.
  107. // Sometimes is useful to keep the event,
  108. // 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)
  109. beforeFlush func()
  110. }
  111. var _ ResponseWriter = (*responseWriter)(nil)
  112. const (
  113. defaultStatusCode = http.StatusOK
  114. // NoWritten !=-1 => when nothing written before
  115. NoWritten = -1
  116. // StatusCodeWritten != 0 => when only status code written
  117. StatusCodeWritten = 0
  118. )
  119. // Naive returns the simple, underline and original http.ResponseWriter
  120. // that backends this response writer.
  121. func (w *responseWriter) Naive() http.ResponseWriter {
  122. return w.ResponseWriter
  123. }
  124. // BeginResponse receives an http.ResponseWriter
  125. // and initialize or reset the response writer's field's values.
  126. func (w *responseWriter) BeginResponse(underline http.ResponseWriter) {
  127. w.beforeFlush = nil
  128. w.written = NoWritten
  129. w.statusCode = defaultStatusCode
  130. w.ResponseWriter = underline
  131. }
  132. // EndResponse is the last function which is called right before the server sent the final response.
  133. //
  134. // Here is the place which we can make the last checks or do a cleanup.
  135. func (w *responseWriter) EndResponse() {
  136. releaseResponseWriter(w)
  137. }
  138. // SetWritten sets manually a value for written, it can be
  139. // NoWritten(-1) or StatusCodeWritten(0), > 0 means body length which is useless here.
  140. func (w *responseWriter) SetWritten(n int) {
  141. if n >= NoWritten && n <= StatusCodeWritten {
  142. w.written = n
  143. }
  144. }
  145. // Written should returns the total length of bytes that were being written to the client.
  146. // In addition iris provides some variables to help low-level actions:
  147. // NoWritten, means that nothing were written yet and the response writer is still live.
  148. // StatusCodeWritten, means that status code were written but no other bytes are written to the client, response writer may closed.
  149. // > 0 means that the reply was written and it's the total number of bytes were written.
  150. func (w *responseWriter) Written() int {
  151. return w.written
  152. }
  153. // WriteHeader sends an HTTP response header with status code.
  154. // If WriteHeader is not called explicitly, the first call to Write
  155. // will trigger an implicit WriteHeader(http.StatusOK).
  156. // Thus explicit calls to WriteHeader are mainly used to
  157. // send error codes.
  158. func (w *responseWriter) WriteHeader(statusCode int) {
  159. w.statusCode = statusCode
  160. }
  161. func (w *responseWriter) tryWriteHeader() {
  162. if w.written == NoWritten { // before write, once.
  163. w.written = StatusCodeWritten
  164. w.ResponseWriter.WriteHeader(w.statusCode)
  165. }
  166. }
  167. // Write writes to the client
  168. // If WriteHeader has not yet been called, Write calls
  169. // WriteHeader(http.StatusOK) before writing the data. If the Header
  170. // does not contain a Content-Type line, Write adds a Content-Type set
  171. // to the result of passing the initial 512 bytes of written data to
  172. // DetectContentType.
  173. //
  174. // Depending on the HTTP protocol version and the client, calling
  175. // Write or WriteHeader may prevent future reads on the
  176. // Request.Body. For HTTP/1.x requests, handlers should read any
  177. // needed request body data before writing the response. Once the
  178. // headers have been flushed (due to either an explicit Flusher.Flush
  179. // call or writing enough data to trigger a flush), the request body
  180. // may be unavailable. For HTTP/2 requests, the Go HTTP server permits
  181. // handlers to continue to read the request body while concurrently
  182. // writing the response. However, such behavior may not be supported
  183. // by all HTTP/2 clients. Handlers should read before writing if
  184. // possible to maximize compatibility.
  185. func (w *responseWriter) Write(contents []byte) (int, error) {
  186. w.tryWriteHeader()
  187. n, err := w.ResponseWriter.Write(contents)
  188. w.written += n
  189. return n, err
  190. }
  191. // Writef formats according to a format specifier and writes to the response.
  192. //
  193. // Returns the number of bytes written and any write error encountered.
  194. func (w *responseWriter) Writef(format string, a ...interface{}) (n int, err error) {
  195. return fmt.Fprintf(w, format, a...)
  196. }
  197. // WriteString writes a simple string to the response.
  198. //
  199. // Returns the number of bytes written and any write error encountered.
  200. func (w *responseWriter) WriteString(s string) (int, error) {
  201. w.tryWriteHeader()
  202. n, err := io.WriteString(w.ResponseWriter, s)
  203. w.written += n
  204. return n, err
  205. }
  206. // StatusCode returns the status code header value
  207. func (w *responseWriter) StatusCode() int {
  208. return w.statusCode
  209. }
  210. func (w *responseWriter) GetBeforeFlush() func() {
  211. return w.beforeFlush
  212. }
  213. // SetBeforeFlush registers the unique callback which called exactly before the response is flushed to the client
  214. func (w *responseWriter) SetBeforeFlush(cb func()) {
  215. w.beforeFlush = cb
  216. }
  217. func (w *responseWriter) FlushResponse() {
  218. if w.beforeFlush != nil {
  219. w.beforeFlush()
  220. }
  221. w.tryWriteHeader()
  222. }
  223. // Clone returns a clone of this response writer
  224. // it copies the header, status code, headers and the beforeFlush finally returns a new ResponseRecorder.
  225. func (w *responseWriter) Clone() ResponseWriter {
  226. wc := &responseWriter{}
  227. wc.ResponseWriter = w.ResponseWriter
  228. wc.statusCode = w.statusCode
  229. wc.beforeFlush = w.beforeFlush
  230. wc.written = w.written
  231. return wc
  232. }
  233. // WriteTo writes a response writer (temp: status code, headers and body) to another response writer.
  234. func (w *responseWriter) WriteTo(to ResponseWriter) {
  235. // set the status code, failure status code are first class
  236. if w.statusCode >= 400 {
  237. to.WriteHeader(w.statusCode)
  238. }
  239. // append the headers
  240. if w.Header() != nil {
  241. for k, values := range w.Header() {
  242. for _, v := range values {
  243. if to.Header().Get(v) == "" {
  244. to.Header().Add(k, v)
  245. }
  246. }
  247. }
  248. }
  249. // the body is not copied, this writer doesn't support recording
  250. }
  251. // Hijack lets the caller take over the connection.
  252. // After a call to Hijack(), the HTTP server library
  253. // will not do anything else with the connection.
  254. //
  255. // It becomes the caller's responsibility to manage
  256. // and close the connection.
  257. //
  258. // The returned net.Conn may have read or write deadlines
  259. // already set, depending on the configuration of the
  260. // Server. It is the caller's responsibility to set
  261. // or clear those deadlines as needed.
  262. func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  263. if h, isHijacker := w.ResponseWriter.(http.Hijacker); isHijacker {
  264. w.written = StatusCodeWritten
  265. return h.Hijack()
  266. }
  267. return nil, nil, errors.New("hijack is not supported by this ResponseWriter")
  268. }
  269. // Flusher indicates if `Flush` is supported by the client.
  270. //
  271. // The default HTTP/1.x and HTTP/2 ResponseWriter implementations
  272. // support Flusher, but ResponseWriter wrappers may not. Handlers
  273. // should always test for this ability at runtime.
  274. //
  275. // Note that even for ResponseWriters that support Flush,
  276. // if the client is connected through an HTTP proxy,
  277. // the buffered data may not reach the client until the response
  278. // completes.
  279. func (w *responseWriter) Flusher() (http.Flusher, bool) {
  280. flusher, canFlush := w.ResponseWriter.(http.Flusher)
  281. return flusher, canFlush
  282. }
  283. // Flush sends any buffered data to the client.
  284. func (w *responseWriter) Flush() {
  285. if flusher, ok := w.Flusher(); ok {
  286. flusher.Flush()
  287. }
  288. }
  289. // ErrPushNotSupported is returned by the Push method to
  290. // indicate that HTTP/2 Push support is not available.
  291. var ErrPushNotSupported = errors.New("push feature is not supported by this ResponseWriter")
  292. // Push initiates an HTTP/2 server push. This constructs a synthetic
  293. // request using the given target and options, serializes that request
  294. // into a PUSH_PROMISE frame, then dispatches that request using the
  295. // server's request handler. If opts is nil, default options are used.
  296. //
  297. // The target must either be an absolute path (like "/path") or an absolute
  298. // URL that contains a valid host and the same scheme as the parent request.
  299. // If the target is a path, it will inherit the scheme and host of the
  300. // parent request.
  301. //
  302. // The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
  303. // Push may or may not detect these invalid pushes; however, invalid
  304. // pushes will be detected and canceled by conforming clients.
  305. //
  306. // Handlers that wish to push URL X should call Push before sending any
  307. // data that may trigger a request for URL X. This avoids a race where the
  308. // client issues requests for X before receiving the PUSH_PROMISE for X.
  309. //
  310. // Push returns ErrPushNotSupported if the client has disabled push or if push
  311. // is not supported on the underlying connection.
  312. func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
  313. if pusher, isPusher := w.ResponseWriter.(http.Pusher); isPusher {
  314. err := pusher.Push(target, opts)
  315. if err != nil && err.Error() == http.ErrNotSupported.ErrorString {
  316. return ErrPushNotSupported
  317. }
  318. return err
  319. }
  320. return ErrPushNotSupported
  321. }
  322. // CloseNotifier indicates if the protocol supports the underline connection closure notification.
  323. func (w *responseWriter) CloseNotifier() (http.CloseNotifier, bool) {
  324. notifier, supportsCloseNotify := w.ResponseWriter.(http.CloseNotifier)
  325. return notifier, supportsCloseNotify
  326. }
  327. // CloseNotify returns a channel that receives at most a
  328. // single value (true) when the client connection has gone
  329. // away.
  330. //
  331. // CloseNotify may wait to notify until Request.Body has been
  332. // fully read.
  333. //
  334. // After the Handler has returned, there is no guarantee
  335. // that the channel receives a value.
  336. //
  337. // If the protocol is HTTP/1.1 and CloseNotify is called while
  338. // processing an idempotent request (such a GET) while
  339. // HTTP/1.1 pipelining is in use, the arrival of a subsequent
  340. // pipelined request may cause a value to be sent on the
  341. // returned channel. In practice HTTP/1.1 pipelining is not
  342. // enabled in browsers and not seen often in the wild. If this
  343. // is a problem, use HTTP/2 or only use CloseNotify on methods
  344. // such as POST.
  345. func (w *responseWriter) CloseNotify() <-chan bool {
  346. if notifier, ok := w.CloseNotifier(); ok {
  347. return notifier.CloseNotify()
  348. }
  349. ch := make(chan bool, 1)
  350. return ch
  351. }