61
62
type responseRecorder struct {
63
*ResponseWriterWrapper
64
- wroteHeader bool
65
- statusCode int
66
- buf *bytes.Buffer
64
+ wroteHeader bool
65
+ statusCode int
66
+ buf *bytes.Buffer
67
+ shouldBuffer func(status int) bool
68
+ stream bool
69
}
70
71
// NewResponseRecorder returns a new ResponseRecorder that can be
78
// responses by wrapping Write and WriteHeader methods instead of
79
// buffering whole response bodies.
80
//
81
+// Recorders optionally buffer the response. When the headers are
82
+// to be written, shouldBuffer will be called with the status
83
+// code that is being written. The rest of the headers can be read
84
+// from w.Header(). If shouldBuffer returns true, the response
85
+// will be buffered. You can know the response was buffered if
86
+// the Buffered() method returns true. If the response was not
87
+// buffered, Buffered() will return false and that means the
88
+// response bypassed the recorder and was written directly to the
89
+// underlying writer.
90
+//
91
// Before calling this function in a middleware handler, make a
92
// new buffer or obtain one from a pool (use the sync.Pool) type.
93
// Using a pool is generally recommended for performance gains;
97
// The returned recorder can be used in place of w when calling
98
// the next handler in the chain. When that handler returns, you
99
// can read the status code from the recorder's Status() method.
88
-// The response body fills buf, and the headers are available in
89
-// w.Header().
90
-func NewResponseRecorder(w http.ResponseWriter, buf *bytes.Buffer) ResponseRecorder {
100
+// The response body fills buf if it was buffered, and the headers
101
+// are available via w.Header().
102
+func NewResponseRecorder(w http.ResponseWriter, buf *bytes.Buffer, shouldBuffer func(status int) bool) ResponseRecorder {
103
return &responseRecorder{
104
ResponseWriterWrapper: &ResponseWriterWrapper{ResponseWriter: w},
105
buf: buf,
106
+ shouldBuffer: shouldBuffer,
107
}
108
}
109
113
}
114
rr.statusCode = statusCode
115
rr.wroteHeader = true
116
+
117
+ // decide whether we should buffer the response
118
+ if rr.shouldBuffer == nil {
119
+ return
120
+ }
121
+ rr.stream = !rr.shouldBuffer(rr.statusCode)
122
+ if rr.stream {
123
+ rr.ResponseWriterWrapper.WriteHeader(rr.statusCode)
124
+ }
125
}
126
127
func (rr *responseRecorder) Write(data []byte) (int, error) {
128
rr.WriteHeader(http.StatusOK)
129
+ if rr.stream {
130
+ return rr.ResponseWriterWrapper.Write(data)
131
+ }
132
return rr.buf.Write(data)
133
}
134
143
return rr.buf
144
}
145
146
+// Buffered returns whether rr has decided to buffer the response.
147
+func (rr *responseRecorder) Buffered() bool {
148
+ return !rr.stream
149
+}
150
+
151
// ResponseRecorder is a http.ResponseWriter that records
152
// responses instead of writing them to the client.
153
type ResponseRecorder interface {
154
HTTPInterfaces
155
Status() int
156
Buffer() *bytes.Buffer
157
+ Buffered() bool
158
}
159
160
// Interface guards