Skip to content

Commit b47abdb

Browse files
committed
Fixed #424, #427
Signed-off-by: Vishal Rana <vr@labstack.com>
1 parent 576dfeb commit b47abdb

File tree

4 files changed

+51
-115
lines changed

4 files changed

+51
-115
lines changed

echo.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,7 @@ type (
131131
}
132132
)
133133

134-
//--------------
135134
// HTTP methods
136-
//--------------
137135
const (
138136
CONNECT = "CONNECT"
139137
DELETE = "DELETE"
@@ -146,9 +144,7 @@ const (
146144
TRACE = "TRACE"
147145
)
148146

149-
//-------------
150147
// Media types
151-
//-------------
152148
const (
153149
ApplicationJSON = "application/json"
154150
ApplicationJSONCharsetUTF8 = ApplicationJSON + "; " + CharsetUTF8
@@ -167,16 +163,12 @@ const (
167163
OctetStream = "application/octet-stream"
168164
)
169165

170-
//---------
171166
// Charset
172-
//---------
173167
const (
174168
CharsetUTF8 = "charset=utf-8"
175169
)
176170

177-
//---------
178171
// Headers
179-
//---------
180172
const (
181173
AcceptEncoding = "Accept-Encoding"
182174
Authorization = "Authorization"
@@ -207,9 +199,7 @@ var (
207199
}
208200
)
209201

210-
//--------
211202
// Errors
212-
//--------
213203
var (
214204
ErrUnsupportedMediaType = NewHTTPError(http.StatusUnsupportedMediaType)
215205
ErrNotFound = NewHTTPError(http.StatusNotFound)
@@ -219,9 +209,7 @@ var (
219209
ErrInvalidRedirectCode = errors.New("invalid redirect status code")
220210
)
221211

222-
//----------------
223212
// Error handlers
224-
//----------------
225213
var (
226214
notFoundHandler = HandlerFunc(func(c Context) error {
227215
return ErrNotFound

middleware/compress.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,22 @@ func GzipFromConfig(config GzipConfig) echo.MiddlewareFunc {
4848
return echo.HandlerFunc(func(c echo.Context) error {
4949
c.Response().Header().Add(echo.Vary, echo.AcceptEncoding)
5050
if strings.Contains(c.Request().Header().Get(echo.AcceptEncoding), scheme) {
51-
w := pool.Get().(*gzip.Writer)
52-
w.Reset(c.Response().Writer())
51+
rw := c.Response().Writer()
52+
gw := pool.Get().(*gzip.Writer)
53+
gw.Reset(rw)
5354
defer func() {
54-
w.Close()
55-
pool.Put(w)
56-
w.Close()
55+
if c.Response().Size() == 0 {
56+
// We have to reset response to it's pristine state when
57+
// nothing is written to body or error is returned.
58+
// See issue #424, #407.
59+
c.Response().SetWriter(rw)
60+
c.Response().Header().Del(echo.ContentEncoding)
61+
gw.Reset(ioutil.Discard)
62+
}
63+
gw.Close()
64+
pool.Put(gw)
5765
}()
58-
g := gzipResponseWriter{Response: c.Response(), Writer: w}
66+
g := gzipResponseWriter{Response: c.Response(), Writer: gw}
5967
c.Response().Header().Set(echo.ContentEncoding, scheme)
6068
c.Response().SetWriter(g)
6169
}

middleware/compress_test.go

Lines changed: 36 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,21 @@ package middleware
33
import (
44
"bytes"
55
"compress/gzip"
6+
"io/ioutil"
7+
"net/http"
68
"testing"
79

810
"github.com/labstack/echo"
911
"github.com/labstack/echo/test"
1012
"github.com/stretchr/testify/assert"
1113
)
1214

13-
type closeNotifyingRecorder struct {
14-
*test.ResponseRecorder
15-
closed chan bool
16-
}
17-
18-
func newCloseNotifyingRecorder() *closeNotifyingRecorder {
19-
return &closeNotifyingRecorder{
20-
test.NewResponseRecorder(),
21-
make(chan bool, 1),
22-
}
23-
}
24-
25-
func (c *closeNotifyingRecorder) close() {
26-
c.closed <- true
27-
}
28-
29-
func (c *closeNotifyingRecorder) CloseNotify() <-chan bool {
30-
return c.closed
31-
}
32-
3315
func TestGzip(t *testing.T) {
3416
e := echo.New()
3517
req := test.NewRequest(echo.GET, "/", nil)
3618
rec := test.NewResponseRecorder()
3719
c := echo.NewContext(req, rec, e)
20+
3821
// Skip if no Accept-Encoding header
3922
h := Gzip()(echo.HandlerFunc(func(c echo.Context) error {
4023
c.Response().Write([]byte("test")) // For Content-Type sniffing
@@ -50,7 +33,6 @@ func TestGzip(t *testing.T) {
5033

5134
// Gzip
5235
h.Handle(c)
53-
// assert.Equal(t, http.StatusOK, rec.Status())
5436
assert.Equal(t, "gzip", rec.Header().Get(echo.ContentEncoding))
5537
assert.Contains(t, rec.Header().Get(echo.ContentType), echo.TextPlain)
5638
r, err := gzip.NewReader(rec.Body)
@@ -62,79 +44,37 @@ func TestGzip(t *testing.T) {
6244
}
6345
}
6446

65-
// func TestGzipFlush(t *testing.T) {
66-
// res := test.NewResponseRecorder()
67-
// buf := new(bytes.Buffer)
68-
// w := gzip.NewWriter(buf)
69-
// gw := gzipWriter{Writer: w, ResponseWriter: res}
70-
//
71-
// n0 := buf.Len()
72-
// if n0 != 0 {
73-
// t.Fatalf("buffer size = %d before writes; want 0", n0)
74-
// }
75-
//
76-
// if err := gw.Flush(); err != nil {
77-
// t.Fatal(err)
78-
// }
79-
//
80-
// n1 := buf.Len()
81-
// if n1 == 0 {
82-
// t.Fatal("no data after first flush")
83-
// }
84-
//
85-
// gw.Write([]byte("x"))
86-
//
87-
// n2 := buf.Len()
88-
// if n1 != n2 {
89-
// t.Fatalf("after writing a single byte, size changed from %d to %d; want no change", n1, n2)
90-
// }
91-
//
92-
// if err := gw.Flush(); err != nil {
93-
// t.Fatal(err)
94-
// }
95-
//
96-
// n3 := buf.Len()
97-
// if n2 == n3 {
98-
// t.Fatal("Flush didn't flush any data")
99-
// }
100-
// }
47+
func TestGzipNoContent(t *testing.T) {
48+
e := echo.New()
49+
req := test.NewRequest(echo.GET, "/", nil)
50+
rec := test.NewResponseRecorder()
51+
c := echo.NewContext(req, rec, e)
52+
h := Gzip()(echo.HandlerFunc(func(c echo.Context) error {
53+
return c.NoContent(http.StatusOK)
54+
}))
55+
h.Handle(c)
56+
57+
assert.Empty(t, rec.Header().Get(echo.ContentEncoding))
58+
assert.Empty(t, rec.Header().Get(echo.ContentType))
59+
b, err := ioutil.ReadAll(rec.Body)
60+
if assert.NoError(t, err) {
61+
assert.Equal(t, 0, len(b))
62+
}
63+
}
64+
65+
func TestGzipErrorReturned(t *testing.T) {
66+
e := echo.New()
67+
e.Use(Gzip())
68+
e.Get("/", echo.HandlerFunc(func(c echo.Context) error {
69+
return echo.NewHTTPError(http.StatusInternalServerError, "error")
70+
}))
71+
req := test.NewRequest(echo.GET, "/", nil)
72+
rec := test.NewResponseRecorder()
73+
e.ServeHTTP(req, rec)
10174

102-
// func TestGzipCloseNotify(t *testing.T) {
103-
// rec := newCloseNotifyingRecorder()
104-
// buf := new(bytes.Buffer)
105-
// w := gzip.NewWriter(buf)
106-
// gw := gzipWriter{Writer: w, ResponseWriter: rec}
107-
// closed := false
108-
// notifier := gw.CloseNotify()
109-
// rec.close()
110-
//
111-
// select {
112-
// case <-notifier:
113-
// closed = true
114-
// case <-time.After(time.Second):
115-
// }
116-
//
117-
// assert.Equal(t, closed, true)
118-
// }
119-
//
120-
// func BenchmarkGzip(b *testing.B) {
121-
// b.StopTimer()
122-
// b.ReportAllocs()
123-
//
124-
// h := func(c echo.Context) error {
125-
// c.Response().Write([]byte("test")) // For Content-Type sniffing
126-
// return nil
127-
// }
128-
// req, _ := http.NewRequest(echo.GET, "/", nil)
129-
// req.Header().Set(echo.AcceptEncoding, "gzip")
130-
//
131-
// b.StartTimer()
132-
//
133-
// for i := 0; i < b.N; i++ {
134-
// e := echo.New()
135-
// res := test.NewResponseRecorder()
136-
// c := echo.NewContext(req, res, e)
137-
// Gzip()(h)(c)
138-
// }
139-
//
140-
// }
75+
assert.Empty(t, rec.Header().Get(echo.ContentEncoding))
76+
b, err := ioutil.ReadAll(rec.Body)
77+
if assert.NoError(t, err) {
78+
assert.Equal(t, "error", string(b))
79+
}
80+
}

middleware/logger.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func LoggerFromConfig(config LoggerConfig) echo.MiddlewareFunc {
7878

7979
start := time.Now()
8080
if err := next.Handle(c); err != nil {
81-
return err
81+
c.Error(err)
8282
}
8383
stop := time.Now()
8484
method := []byte(req.Method())

0 commit comments

Comments
 (0)