1
1
package middleware
2
2
3
3
import (
4
- "bytes"
5
4
"compress/gzip"
6
5
"io"
7
- "io/ioutil"
8
6
"net/http"
9
7
"sync"
10
8
@@ -43,26 +41,7 @@ type DefaultGzipDecompressPool struct {
43
41
}
44
42
45
43
func (d * DefaultGzipDecompressPool ) gzipDecompressPool () sync.Pool {
46
- return sync.Pool {
47
- New : func () interface {} {
48
- // create with an empty reader (but with GZIP header)
49
- w , err := gzip .NewWriterLevel (ioutil .Discard , gzip .BestSpeed )
50
- if err != nil {
51
- return err
52
- }
53
-
54
- b := new (bytes.Buffer )
55
- w .Reset (b )
56
- w .Flush ()
57
- w .Close ()
58
-
59
- r , err := gzip .NewReader (bytes .NewReader (b .Bytes ()))
60
- if err != nil {
61
- return err
62
- }
63
- return r
64
- },
65
- }
44
+ return sync.Pool {New : func () interface {} { return new (gzip.Reader ) }}
66
45
}
67
46
68
47
//Decompress decompresses request body based if content encoding type is set to "gzip" with default config
@@ -82,38 +61,38 @@ func DecompressWithConfig(config DecompressConfig) echo.MiddlewareFunc {
82
61
83
62
return func (next echo.HandlerFunc ) echo.HandlerFunc {
84
63
pool := config .GzipDecompressPool .gzipDecompressPool ()
64
+
85
65
return func (c echo.Context ) error {
86
66
if config .Skipper (c ) {
87
67
return next (c )
88
68
}
89
- switch c .Request ().Header .Get (echo .HeaderContentEncoding ) {
90
- case GZIPEncoding :
91
- b := c .Request ().Body
92
-
93
- i := pool .Get ()
94
- gr , ok := i .(* gzip.Reader )
95
- if ! ok {
96
- return echo .NewHTTPError (http .StatusInternalServerError , i .(error ).Error ())
97
- }
98
69
99
- if err := gr .Reset (b ); err != nil {
100
- pool .Put (gr )
101
- if err == io .EOF { //ignore if body is empty
102
- return next (c )
103
- }
104
- return err
105
- }
106
- var buf bytes.Buffer
107
- io .Copy (& buf , gr )
70
+ if c .Request ().Header .Get (echo .HeaderContentEncoding ) != GZIPEncoding {
71
+ return next (c )
72
+ }
108
73
109
- gr .Close ()
110
- pool .Put (gr )
74
+ i := pool .Get ()
75
+ gr , ok := i .(* gzip.Reader )
76
+ if ! ok || gr == nil {
77
+ return echo .NewHTTPError (http .StatusInternalServerError , i .(error ).Error ())
78
+ }
79
+ defer pool .Put (gr )
111
80
112
- b .Close () // http.Request.Body is closed by the Server, but because we are replacing it, it must be closed here
81
+ b := c .Request ().Body
82
+ defer b .Close ()
113
83
114
- r := ioutil .NopCloser (& buf )
115
- c .Request ().Body = r
84
+ if err := gr .Reset (b ); err != nil {
85
+ if err == io .EOF { //ignore if body is empty
86
+ return next (c )
87
+ }
88
+ return err
116
89
}
90
+
91
+ // only Close gzip reader if it was set to a proper gzip source otherwise it will panic on close.
92
+ defer gr .Close ()
93
+
94
+ c .Request ().Body = gr
95
+
117
96
return next (c )
118
97
}
119
98
}
0 commit comments