gin-contrib / gzip

Gin middleware to enable GZIP support.
MIT License
330 stars 87 forks source link

If enable the gzip middleware, the gin server returns an incorrect response for 404 status by default #46

Open mstmdev opened 2 years ago

mstmdev commented 2 years ago

Enable the gzip middleware, that 404 response like this:

HTTP/1.1 404 Not Found
Vary: Accept-Encoding
Date: Wed, 29 Dec 2021 09:44:42 GMT
Content-Length: 0

Disable the gzip middleware, that 404 response like this:

HTTP/1.1 404 Not Found
Content-Type: text/plain
Date: Wed, 29 Dec 2021 09:47:08 GMT
Content-Length: 18

404 page not found

Because of the gz.Close() will writing the GZIP footer to c.Writer.

https://github.com/gin-contrib/gzip/blob/c784c8e8a75f6a922b41cc10783aa9b6a69a7b83/handler.go#L55-L60

So gin will not write default404Body in serveError func. We need to customize the gin.Engine.NoRoute that responds to the correct 404 content now.

https://github.com/gin-gonic/gin/blob/d062a6a6155236883f4c3292379ab94b1eac8b05/gin.go#L632-L637

runephilosof-karnovgroup commented 1 year ago

I see almost the same results.

runephilosof@fedora:~/code/go-test$ curl -i -H 'Accept-Encoding: gzip' localhost:9000/
HTTP/1.1 404 Not Found
Content-Encoding: gzip
Vary: Accept-Encoding
Date: Wed, 20 Sep 2023 12:18:32 GMT
Content-Length: 23

But the 23 bytes is just the gzip overhead for an empty string

~/code/go-test$ curl -H 'Accept-Encoding: gzip' localhost:9000/ --output foo.gz
~/code/go-test$ gunzip foo.gz
~/code/go-test$ ls -l foo
-rw-r--r--. 1 runephilosof runephilosof 0 Sep 20 14:22 foo

Using

package main

import (
    "fmt"
    "github.com/gin-contrib/gzip"
    "github.com/gin-gonic/gin"
    "log"
    "net/http"
    "time"
)

func main() {

    r := gin.Default()
    r.Use(func(c *gin.Context) {
        c.Writer.Header().Add("Vary", "Origin")
    }, gzip.Gzip(gzip.DefaultCompression))
    r.GET("/ping", func(c *gin.Context) {
        c.String(http.StatusOK, "pong "+fmt.Sprint(time.Now().Unix()))
    })

    // Listen and Server in 0.0.0.0:8080
    if err := r.Run(":9000"); err != nil {
        log.Fatal(err)
    }

}