@@ -40,7 +40,8 @@ type WriteFlusher interface {
40
40
}
41
41
42
42
type CompressResponseWriter struct {
43
- ServerResponse
43
+ Header ServerHeader
44
+ OriginalWriter io.Writer
44
45
compressWriter WriteFlusher
45
46
compressionType string
46
47
headersWritten bool
@@ -52,20 +53,20 @@ type CompressResponseWriter struct {
52
53
// CompressFilter does compresssion of response body in gzip/deflate if
53
54
// `results.compressed=true` in the app.conf
54
55
func CompressFilter (c * Controller , fc []Filter ) {
55
- fc [0 ](c , fc [1 :])
56
56
if Config .BoolDefault ("results.compressed" , false ) {
57
57
if c .Response .Status != http .StatusNoContent && c .Response .Status != http .StatusNotModified {
58
- writer := CompressResponseWriter {c .Response .Out , nil , "" , false , make (chan bool , 1 ), nil , false }
59
- writer .DetectCompressionType (c .Request , c .Response )
60
- w , ok := c .Response .Out .(http.CloseNotifier )
61
- if ok {
62
- writer .parentNotify = w .CloseNotify ()
58
+ if found , compressType , compressWriter := detectCompressionType (c .Request , c .Response ); found {
59
+ writer := CompressResponseWriter {c .Response .Out .Header (), c .Response .Out .GetWriter (), compressWriter , compressType , false , make (chan bool , 1 ), nil , false }
60
+ if w , ok := c .Response .Out .(http.CloseNotifier ); ok {
61
+ writer .parentNotify = w .CloseNotify ()
62
+ }
63
+ c .Response .Out .SetWriter (& writer )
63
64
}
64
- c .Response .Out .SetWriter (& writer )
65
65
} else {
66
66
TRACE .Printf ("Compression disabled for response status (%d)" , c .Response .Status )
67
67
}
68
68
}
69
+ fc [0 ](c , fc [1 :])
69
70
}
70
71
71
72
func (c CompressResponseWriter ) CloseNotify () <- chan bool {
@@ -77,16 +78,16 @@ func (c CompressResponseWriter) CloseNotify() <-chan bool {
77
78
78
79
func (c * CompressResponseWriter ) prepareHeaders () {
79
80
if c .compressionType != "" {
80
- responseMime := c .Header () .Get ("Content-Type" )
81
+ responseMime := c .Header .Get ("Content-Type" )
81
82
responseMime = strings .TrimSpace (strings .SplitN (responseMime , ";" , 2 )[0 ])
82
83
shouldEncode := false
83
84
84
- if c .Header () .Get ("Content-Encoding" ) == "" {
85
+ if c .Header .Get ("Content-Encoding" ) == "" {
85
86
for _ , compressableMime := range compressableMimes {
86
87
if responseMime == compressableMime {
87
88
shouldEncode = true
88
- c .Header () .Set ("Content-Encoding" , c .compressionType )
89
- c .Header () .Del ("Content-Length" )
89
+ c .Header .Set ("Content-Encoding" , c .compressionType )
90
+ c .Header .Del ("Content-Length" )
90
91
break
91
92
}
92
93
}
@@ -102,15 +103,14 @@ func (c *CompressResponseWriter) prepareHeaders() {
102
103
func (c * CompressResponseWriter ) WriteHeader (status int ) {
103
104
c .headersWritten = true
104
105
c .prepareHeaders ()
105
- c .ServerResponse . Header () .SetStatus (status )
106
+ c .Header .SetStatus (status )
106
107
}
107
108
108
109
func (c * CompressResponseWriter ) Close () error {
109
110
if c .compressionType != "" {
110
- _ = c .compressWriter .Close ()
111
- }
112
- if w , ok := c .ServerResponse .GetWriter ().(io.Closer ); ok {
113
- _ = w .Close ()
111
+ if err := c .compressWriter .Close (); err != nil {
112
+ ERROR .Println ("Error closing compress writer" , err )
113
+ }
114
114
}
115
115
// Non-blocking write to the closenotifier, if we for some reason should
116
116
// get called multiple times
@@ -139,17 +139,15 @@ func (c *CompressResponseWriter) Write(b []byte) (int, error) {
139
139
c .prepareHeaders ()
140
140
c .headersWritten = true
141
141
}
142
-
143
142
if c .compressionType != "" {
144
143
return c .compressWriter .Write (b )
145
144
}
146
-
147
- return c .ServerResponse .GetWriter ().Write (b )
145
+ return c .OriginalWriter .Write (b )
148
146
}
149
147
150
- // DetectCompressionType method detects the comperssion type
148
+ // DetectCompressionType method detects the compression type
151
149
// from header "Accept-Encoding"
152
- func ( c * CompressResponseWriter ) DetectCompressionType ( req * Request , resp * Response ) {
150
+ func detectCompressionType ( req * Request , resp * Response ) ( found bool , compressionType string , compressionKind WriteFlusher ) {
153
151
if Config .BoolDefault ("results.compressed" , false ) {
154
152
acceptedEncodings := strings .Split (req .In .GetHeader ().Get ("Accept-Encoding" ), "," )
155
153
@@ -216,13 +214,16 @@ func (c *CompressResponseWriter) DetectCompressionType(req *Request, resp *Respo
216
214
return
217
215
}
218
216
219
- c . compressionType = compressionTypes [chosenEncoding ]
217
+ compressionType = compressionTypes [chosenEncoding ]
220
218
221
- switch c . compressionType {
219
+ switch compressionType {
222
220
case "gzip" :
223
- c .compressWriter = gzip .NewWriter (resp .Out .GetWriter ())
221
+ compressionKind = gzip .NewWriter (resp .Out .GetWriter ())
222
+ found = true
224
223
case "deflate" :
225
- c .compressWriter = zlib .NewWriter (resp .Out .GetWriter ())
224
+ compressionKind = zlib .NewWriter (resp .Out .GetWriter ())
225
+ found = true
226
226
}
227
227
}
228
+ return
228
229
}
0 commit comments