response.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package tango
  2. import (
  3. "bufio"
  4. "fmt"
  5. "net"
  6. "net/http"
  7. )
  8. // ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
  9. // the response. It is recommended that middleware handlers use this construct to wrap a responsewriter
  10. // if the functionality calls for it.
  11. type ResponseWriter interface {
  12. http.ResponseWriter
  13. http.Flusher
  14. // Status returns the status code of the response or 0 if the response has not been written.
  15. Status() int
  16. // Written returns whether or not the ResponseWriter has been written.
  17. Written() bool
  18. // Size returns the size of the response body.
  19. Size() int
  20. }
  21. // NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
  22. func NewResponseWriter(rw http.ResponseWriter) ResponseWriter {
  23. return &responseWriter{rw, 0, 0}
  24. }
  25. type responseWriter struct {
  26. http.ResponseWriter
  27. status int
  28. size int
  29. }
  30. func (rw *responseWriter) WriteHeader(s int) {
  31. rw.status = s
  32. rw.ResponseWriter.WriteHeader(s)
  33. }
  34. func (rw *responseWriter) Write(b []byte) (int, error) {
  35. if !rw.Written() {
  36. // The status will be StatusOK if WriteHeader has not been called yet
  37. rw.WriteHeader(http.StatusOK)
  38. }
  39. size, err := rw.ResponseWriter.Write(b)
  40. rw.size += size
  41. return size, err
  42. }
  43. func (rw *responseWriter) Status() int {
  44. return rw.status
  45. }
  46. func (rw *responseWriter) Size() int {
  47. return rw.size
  48. }
  49. func (rw *responseWriter) Written() bool {
  50. return rw.status != 0
  51. }
  52. func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  53. hijacker, ok := rw.ResponseWriter.(http.Hijacker)
  54. if !ok {
  55. return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
  56. }
  57. return hijacker.Hijack()
  58. }
  59. func (rw *responseWriter) CloseNotify() <-chan bool {
  60. return rw.ResponseWriter.(http.CloseNotifier).CloseNotify()
  61. }
  62. func (rw *responseWriter) Flush() {
  63. flusher, ok := rw.ResponseWriter.(http.Flusher)
  64. if ok {
  65. flusher.Flush()
  66. }
  67. }
  68. type Responser interface {
  69. SetResponse(ResponseWriter)
  70. }
  71. type HttpResponser interface {
  72. SetResponse(http.ResponseWriter)
  73. }
  74. type Resp struct {
  75. ResponseWriter
  76. }
  77. func (resp *Resp) SetResponse(r ResponseWriter) {
  78. resp.ResponseWriter = r
  79. }
  80. func Responses() HandlerFunc {
  81. return func(ctx *Context) {
  82. if action := ctx.Action(); action != nil {
  83. if s, ok := action.(Responser); ok {
  84. s.SetResponse(ctx)
  85. }
  86. }
  87. ctx.Next()
  88. }
  89. }