@@ -2,19 +2,24 @@ package gzip
2
2
3
3
import (
4
4
"compress/gzip"
5
+ "errors"
6
+ "io"
5
7
"net/http"
6
8
"regexp"
7
9
"strings"
8
10
9
11
"github.com/gin-gonic/gin"
10
12
)
11
13
12
- // DefaultExcludedExtentions is a predefined list of file extensions that should be excluded from gzip compression.
13
- // These extensions typically represent image files that are already compressed
14
- // and do not benefit from additional compression.
15
- var DefaultExcludedExtentions = NewExcludedExtensions ([]string {
16
- ".png" , ".gif" , ".jpeg" , ".jpg" ,
17
- })
14
+ var (
15
+ // DefaultExcludedExtentions is a predefined list of file extensions that should be excluded from gzip compression.
16
+ // These extensions typically represent image files that are already compressed
17
+ // and do not benefit from additional compression.
18
+ DefaultExcludedExtentions = NewExcludedExtensions ([]string {
19
+ ".png" , ".gif" , ".jpeg" , ".jpg" ,
20
+ })
21
+ UnsupportedContentEncoding = errors .New ("Unsupported content encoding" )
22
+ )
18
23
19
24
// Option is an interface that defines a method to apply a configuration
20
25
// to a given config instance. Implementations of this interface can be
@@ -210,12 +215,53 @@ func DefaultDecompressHandle(c *gin.Context) {
210
215
if c .Request .Body == nil {
211
216
return
212
217
}
213
- r , err := gzip .NewReader (c .Request .Body )
214
- if err != nil {
215
- _ = c .AbortWithError (http .StatusBadRequest , err )
218
+
219
+ contentEncodingField := strings .Split (strings .ToLower (c .GetHeader ("Content-Encoding" )), "," )
220
+ if len (contentEncodingField ) == 0 { // nothing to decompress
221
+ c .Next ()
222
+
216
223
return
217
224
}
225
+
226
+ toClose := make ([]io.Closer , 0 , len (contentEncodingField ))
227
+ defer func () {
228
+ for i := len (toClose ); i > 0 ; i -- {
229
+ toClose [i - 1 ].Close ()
230
+ }
231
+ }()
232
+
233
+ // parses multiply gzips like
234
+ // Content-Encoding: gzip, gzip, gzip
235
+ // allowed by RFC
236
+ for i := 0 ; i < len (contentEncodingField ); i ++ {
237
+ trimmedValue := strings .TrimSpace (contentEncodingField [i ])
238
+
239
+ if trimmedValue == "" {
240
+ continue
241
+ }
242
+
243
+ if trimmedValue != "gzip" {
244
+ // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.2
245
+ // An origin server MAY respond with a status code of 415 (Unsupported
246
+ // Media Type) if a representation in the request message has a content
247
+ // coding that is not acceptable.
248
+ _ = c .AbortWithError (http .StatusUnsupportedMediaType , UnsupportedContentEncoding )
249
+ }
250
+
251
+ r , err := gzip .NewReader (c .Request .Body )
252
+ if err != nil {
253
+ _ = c .AbortWithError (http .StatusBadRequest , err )
254
+
255
+ return
256
+ }
257
+
258
+ toClose = append (toClose , c .Request .Body )
259
+
260
+ c .Request .Body = r
261
+ }
262
+
218
263
c .Request .Header .Del ("Content-Encoding" )
219
264
c .Request .Header .Del ("Content-Length" )
220
- c .Request .Body = r
265
+
266
+ c .Next ()
221
267
}
0 commit comments