@@ -12,9 +12,15 @@ const (
12
12
maxResponseBodyInLogs = 4096 // At most 4k bytes from response bodies in our logs.
13
13
)
14
14
15
- // badResponseLoggingWriter writes the body of "bad" responses (i.e. 5xx
15
+ type badResponseLoggingWriter interface {
16
+ http.ResponseWriter
17
+ getStatusCode () int
18
+ getWriteError () error
19
+ }
20
+
21
+ // nonFlushingBadResponseLoggingWriter writes the body of "bad" responses (i.e. 5xx
16
22
// responses) to a buffer.
17
- type badResponseLoggingWriter struct {
23
+ type nonFlushingBadResponseLoggingWriter struct {
18
24
rw http.ResponseWriter
19
25
buffer io.Writer
20
26
logBody bool
@@ -23,27 +29,39 @@ type badResponseLoggingWriter struct {
23
29
writeError error // The error returned when downstream Write() fails.
24
30
}
25
31
26
- // newBadResponseLoggingWriter makes a new badResponseLoggingWriter.
27
- func newBadResponseLoggingWriter (rw http.ResponseWriter , buffer io.Writer ) * badResponseLoggingWriter {
28
- return & badResponseLoggingWriter {
32
+ // flushingBadResponseLoggingWriter is a badResponseLoggingWriter that
33
+ // implements http.Flusher.
34
+ type flushingBadResponseLoggingWriter struct {
35
+ nonFlushingBadResponseLoggingWriter
36
+ f http.Flusher
37
+ }
38
+
39
+ func newBadResponseLoggingWriter (rw http.ResponseWriter , buffer io.Writer ) badResponseLoggingWriter {
40
+ b := nonFlushingBadResponseLoggingWriter {
29
41
rw : rw ,
30
42
buffer : buffer ,
31
43
logBody : false ,
32
44
bodyBytesLeft : maxResponseBodyInLogs ,
33
45
statusCode : http .StatusOK ,
34
46
}
47
+
48
+ if f , ok := rw .(http.Flusher ); ok {
49
+ return & flushingBadResponseLoggingWriter {b , f }
50
+ }
51
+
52
+ return & b
35
53
}
36
54
37
55
// Header returns the header map that will be sent by WriteHeader.
38
56
// Implements ResponseWriter.
39
- func (b * badResponseLoggingWriter ) Header () http.Header {
57
+ func (b * nonFlushingBadResponseLoggingWriter ) Header () http.Header {
40
58
return b .rw .Header ()
41
59
}
42
60
43
61
// Write writes HTTP response data.
44
- func (b * badResponseLoggingWriter ) Write (data []byte ) (int , error ) {
62
+ func (b * nonFlushingBadResponseLoggingWriter ) Write (data []byte ) (int , error ) {
45
63
if b .statusCode == 0 {
46
- // WriteHeader has (probably) not been called, so we need to call it with StatusOK to fuflil the interface contract.
64
+ // WriteHeader has (probably) not been called, so we need to call it with StatusOK to fulfill the interface contract.
47
65
// https://godoc.org/net/http#ResponseWriter
48
66
b .WriteHeader (http .StatusOK )
49
67
}
@@ -58,7 +76,7 @@ func (b *badResponseLoggingWriter) Write(data []byte) (int, error) {
58
76
}
59
77
60
78
// WriteHeader writes the HTTP response header.
61
- func (b * badResponseLoggingWriter ) WriteHeader (statusCode int ) {
79
+ func (b * nonFlushingBadResponseLoggingWriter ) WriteHeader (statusCode int ) {
62
80
b .statusCode = statusCode
63
81
if statusCode >= 500 {
64
82
b .logBody = true
@@ -67,15 +85,23 @@ func (b *badResponseLoggingWriter) WriteHeader(statusCode int) {
67
85
}
68
86
69
87
// Hijack hijacks the first response writer that is a Hijacker.
70
- func (b * badResponseLoggingWriter ) Hijack () (net.Conn , * bufio.ReadWriter , error ) {
88
+ func (b * nonFlushingBadResponseLoggingWriter ) Hijack () (net.Conn , * bufio.ReadWriter , error ) {
71
89
hj , ok := b .rw .(http.Hijacker )
72
90
if ok {
73
91
return hj .Hijack ()
74
92
}
75
93
return nil , nil , fmt .Errorf ("badResponseLoggingWriter: can't cast underlying response writer to Hijacker" )
76
94
}
77
95
78
- func (b * badResponseLoggingWriter ) captureResponseBody (data []byte ) {
96
+ func (b * nonFlushingBadResponseLoggingWriter ) getStatusCode () int {
97
+ return b .statusCode
98
+ }
99
+
100
+ func (b * nonFlushingBadResponseLoggingWriter ) getWriteError () error {
101
+ return b .writeError
102
+ }
103
+
104
+ func (b * nonFlushingBadResponseLoggingWriter ) captureResponseBody (data []byte ) {
79
105
if len (data ) > b .bodyBytesLeft {
80
106
b .buffer .Write (data [:b .bodyBytesLeft ])
81
107
io .WriteString (b .buffer , "..." )
@@ -86,3 +112,7 @@ func (b *badResponseLoggingWriter) captureResponseBody(data []byte) {
86
112
b .bodyBytesLeft -= len (data )
87
113
}
88
114
}
115
+
116
+ func (b * flushingBadResponseLoggingWriter ) Flush () {
117
+ b .f .Flush ()
118
+ }
0 commit comments