@@ -3,9 +3,12 @@ package middleware
3
3
import (
4
4
"bytes"
5
5
"compress/gzip"
6
- "github.com/labstack/echo/v4"
7
6
"io"
8
7
"io/ioutil"
8
+ "net/http"
9
+ "sync"
10
+
11
+ "github.com/labstack/echo/v4"
9
12
)
10
13
11
14
type (
@@ -32,27 +35,63 @@ func Decompress() echo.MiddlewareFunc {
32
35
//DecompressWithConfig decompresses request body based if content encoding type is set to "gzip" with config
33
36
func DecompressWithConfig (config DecompressConfig ) echo.MiddlewareFunc {
34
37
return func (next echo.HandlerFunc ) echo.HandlerFunc {
38
+ pool := gzipDecompressPool ()
35
39
return func (c echo.Context ) error {
36
40
if config .Skipper (c ) {
37
41
return next (c )
38
42
}
39
43
switch c .Request ().Header .Get (echo .HeaderContentEncoding ) {
40
44
case GZIPEncoding :
41
- gr , err := gzip .NewReader (c .Request ().Body )
42
- if err != nil {
45
+ b := c .Request ().Body
46
+
47
+ i := pool .Get ()
48
+ gr , ok := i .(* gzip.Reader )
49
+ if ! ok {
50
+ return echo .NewHTTPError (http .StatusInternalServerError , i .(error ).Error ())
51
+ }
52
+
53
+ if err := gr .Reset (b ); err != nil {
54
+ pool .Put (gr )
43
55
if err == io .EOF { //ignore if body is empty
44
56
return next (c )
45
57
}
46
58
return err
47
59
}
48
- defer gr .Close ()
49
60
var buf bytes.Buffer
50
61
io .Copy (& buf , gr )
62
+
63
+ gr .Close ()
64
+ pool .Put (gr )
65
+
66
+ b .Close () // http.Request.Body is closed by the Server, but because we are replacing it, it must be closed here
67
+
51
68
r := ioutil .NopCloser (& buf )
52
- defer r .Close ()
53
69
c .Request ().Body = r
54
70
}
55
71
return next (c )
56
72
}
57
73
}
58
74
}
75
+
76
+ func gzipDecompressPool () sync.Pool {
77
+ return sync.Pool {
78
+ New : func () interface {} {
79
+ // create with an empty reader (but with GZIP header)
80
+ w , err := gzip .NewWriterLevel (ioutil .Discard , gzip .BestSpeed )
81
+ if err != nil {
82
+ return err
83
+ }
84
+
85
+ b := new (bytes.Buffer )
86
+ w .Reset (b )
87
+ w .Flush ()
88
+ w .Close ()
89
+
90
+ r , err := gzip .NewReader (bytes .NewReader (b .Bytes ()))
91
+ if err != nil {
92
+ return err
93
+ }
94
+ return r
95
+ },
96
+ }
97
+ }
0 commit comments