-
- Notifications
You must be signed in to change notification settings - Fork 2.3k
Closed
Description
Issue Description
The status code is not written to the response writer when there is no content in the response. This is new as of 4.11.0 and possibly a result of #2267. Previously, writing of the header happened in the write header function. This was removed in favor of a delayed write.
Lines 139 to 146 in 60af056
| func (w *gzipResponseWriter) WriteHeader(code int) { | |
| w.Header().Del(echo.HeaderContentLength) // Issue #444 | |
| w.wroteHeader = true | |
| // Delay writing of the header until we know if we'll actually compress the response | |
| w.code = code | |
| } |
This delayed write only happens when a body is written. i.e. wroteBody == true
Lines 110 to 127 in 60af056
| if !grw.wroteBody { | |
| if res.Header().Get(echo.HeaderContentEncoding) == gzipScheme { | |
| res.Header().Del(echo.HeaderContentEncoding) | |
| } | |
| // We have to reset response to it's pristine state when | |
| // nothing is written to body or error is returned. | |
| // See issue #424, #407. | |
| res.Writer = rw | |
| w.Reset(io.Discard) | |
| } else if !grw.minLengthExceeded { | |
| // Write uncompressed response | |
| res.Writer = rw | |
| if grw.wroteHeader { | |
| grw.ResponseWriter.WriteHeader(grw.code) | |
| } | |
| grw.buffer.WriteTo(rw) | |
| w.Reset(io.Discard) | |
| } |
Checklist
- Dependencies installed
- No typos
- Searched existing issues and docs
Expected behaviour
The status code should be written to the response writer even though a body is not written to the response when gzip middleware is used
Actual behaviour
The status code is lost within the gzip middleware when a body is not written, resulting in a 200 response
Steps to reproduce
- Create a handler with the Gzip middleware
- Within the handler, write a non-200 response without writing a body
Working code to debug
package main import ( "encoding/json" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "log" "net/http" ) func main() { e := echo.New() some := map[string]string{"error": "missing"} someBytes, err := json.Marshal(some) if err != nil { panic(err) } // status is 200 not 404 e.GET("/get/default", func(ctx echo.Context) error { return ctx.NoContent(http.StatusNotFound) }, middleware.Gzip()) // status is 200 not 307 e.GET("/redirect", func(ctx echo.Context) error { return ctx.Redirect(http.StatusTemporaryRedirect, "/get/config/some") }, middleware.Gzip()) // works e.GET("/get/config/some", func(ctx echo.Context) error { return ctx.JSON(http.StatusBadRequest, some) }, middleware.GzipWithConfig(middleware.GzipConfig{MinLength: len(someBytes) + 10})) // status is 200 not 404 e.GET("/get/config/zero", func(ctx echo.Context) error { return ctx.NoContent(http.StatusNotFound) }, middleware.GzipWithConfig(middleware.GzipConfig{MinLength: 0})) log.Fatal(e.Start(":8080")) }Version/commit
4.11.0
Metadata
Metadata
Assignees
Labels
No labels