Micro & pluggable web framework for Go
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.0KB

  1. // Copyright 2015 The Tango Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package tango
  5. import (
  6. "bufio"
  7. "fmt"
  8. "net"
  9. "net/http"
  10. )
  11. // ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
  12. // the response. It is recommended that middleware handlers use this construct to wrap a responsewriter
  13. // if the functionality calls for it.
  14. type ResponseWriter interface {
  15. http.ResponseWriter
  16. http.Flusher
  17. http.Hijacker
  18. // Status returns the status code of the response or 0 if the response has not been written.
  19. Status() int
  20. // Written returns whether or not the ResponseWriter has been written.
  21. Written() bool
  22. // Size returns the size of the response body.
  23. Size() int
  24. }
  25. type responseWriter struct {
  26. http.ResponseWriter
  27. status int
  28. size int
  29. }
  30. func (rw *responseWriter) reset(w http.ResponseWriter) {
  31. rw.ResponseWriter = w
  32. rw.status = 0
  33. rw.size = 0
  34. }
  35. func (rw *responseWriter) WriteHeader(s int) {
  36. rw.status = s
  37. rw.ResponseWriter.WriteHeader(s)
  38. }
  39. func (rw *responseWriter) Write(b []byte) (int, error) {
  40. if !rw.Written() {
  41. // The status will be StatusOK if WriteHeader has not been called yet
  42. rw.WriteHeader(http.StatusOK)
  43. }
  44. size, err := rw.ResponseWriter.Write(b)
  45. rw.size += size
  46. return size, err
  47. }
  48. func (rw *responseWriter) Status() int {
  49. return rw.status
  50. }
  51. func (rw *responseWriter) Size() int {
  52. return rw.size
  53. }
  54. func (rw *responseWriter) Written() bool {
  55. return rw.status != 0
  56. }
  57. func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  58. hijacker, ok := rw.ResponseWriter.(http.Hijacker)
  59. if !ok {
  60. return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
  61. }
  62. return hijacker.Hijack()
  63. }
  64. func (rw *responseWriter) CloseNotify() <-chan bool {
  65. return rw.ResponseWriter.(http.CloseNotifier).CloseNotify()
  66. }
  67. func (rw *responseWriter) Flush() {
  68. flusher, ok := rw.ResponseWriter.(http.Flusher)
  69. if ok {
  70. flusher.Flush()
  71. }
  72. }