@@ -2,19 +2,24 @@ package gzip
22
33import (
44 "compress/gzip"
5+ "errors"
6+ "io"
57 "net/http"
68 "regexp"
79 "strings"
810
911 "github.com/gin-gonic/gin"
1012)
1113
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+ )
1823
1924// Option is an interface that defines a method to apply a configuration
2025// to a given config instance. Implementations of this interface can be
@@ -210,12 +215,53 @@ func DefaultDecompressHandle(c *gin.Context) {
210215 if c .Request .Body == nil {
211216 return
212217 }
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+
216223 return
217224 }
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+
218263 c .Request .Header .Del ("Content-Encoding" )
219264 c .Request .Header .Del ("Content-Length" )
220- c .Request .Body = r
265+
266+ c .Next ()
221267}
0 commit comments