gin-contrib / cache

Gin middleware/handler to enable Cache
https://gin-gonic.github.io/gin
MIT License
378 stars 96 forks source link

Output always results in status code 200, should be cached #35

Closed hashworks closed 2 years ago

hashworks commented 6 years ago

Returning a body and any status code that is not 200 always results in a cache page with a 200 status code. This even occurs at AbortWithStatusJSON! The status code should be cached and any aborted request should not be cached.

package main

import (
    "github.com/gin-contrib/cache"
    "github.com/gin-contrib/cache/persistence"
    "github.com/gin-gonic/gin"
    "time"
)

func main() {
    gin.DisableConsoleColor()

    router := gin.Default()
    store := persistence.NewInMemoryStore(time.Minute)

    router.GET("/status500", cache.CachePage(store, time.Minute, func(c *gin.Context) {
        c.Status(500)
    }))

    router.GET("/string500", cache.CachePage(store, time.Minute, func(c *gin.Context) {
        c.String(500, "500 error")
    }))

    router.GET("/abort500", cache.CachePage(store, time.Minute, func(c *gin.Context) {
        c.AbortWithStatus(500)
    }))

    router.GET("/abortJSON500", cache.CachePage(store, time.Minute, func(c *gin.Context) {
        c.AbortWithStatusJSON(500, map[string]string{"foo": "bar"})
    }))

    router.GET("/teapot", cache.CachePage(store, time.Minute, func(c *gin.Context) {
        c.String(418, "I’m a teapot")
    }))

    router.Run("127.0.0.1:8000")
}
// Simply calling status without serving a body works:
[GIN] 2018/09/13 - 13:02:45 | 500 |       2.679µs |       127.0.0.1 | GET      /status500
[GIN] 2018/09/13 - 13:02:45 | 500 |       6.659µs |       127.0.0.1 | GET      /status500

// A string as a body doesn't, results in a cached 200:
[GIN] 2018/09/13 - 13:02:51 | 500 |      19.413µs |       127.0.0.1 | GET      /string500
[GIN] 2018/09/13 - 13:02:52 | 200 |       8.176µs |       127.0.0.1 | GET      /string500

// Simple abort works again, because it doesn't serve a body
[GIN] 2018/09/13 - 13:02:57 | 500 |       4.196µs |       127.0.0.1 | GET      /abort500
[GIN] 2018/09/13 - 13:02:59 | 500 |        3.75µs |       127.0.0.1 | GET      /abort500

// Aborting with JSON doesn't work as well, results in a cached 200:
[GIN] 2018/09/13 - 13:03:03 | 500 |      35.687µs |       127.0.0.1 | GET      /abortJSON500
[GIN] 2018/09/13 - 13:03:04 | 200 |      22.353µs |       127.0.0.1 | GET      /abortJSON500

// Any other status codes don't get cached as well:
[GIN] 2018/09/13 - 13:03:09 | 418 |       7.608µs |       127.0.0.1 | GET      /teapot
[GIN] 2018/09/13 - 13:03:10 | 200 |       6.878µs |       127.0.0.1 | GET      /teapot
hashworks commented 6 years ago

Pull request #39 partly resolves this, but this test still failes:

func TestCachePageStatus201(t *testing.T) {
    store := persistence.NewInMemoryStore(60 * time.Second)

    router := gin.New()
    router.GET("/cache_201", CachePage(store, time.Second*3, func(c *gin.Context) {
        c.String(201, fmt.Sprint(time.Now().UnixNano()))
    }))

    w1 := performRequest("GET", "/cache_201", router)
    time.Sleep(time.Millisecond * 500)
    w2 := performRequest("GET", "/cache_201", router)

    assert.Equal(t, 201, w1.Code)
    assert.Equal(t, 201, w2.Code)
    assert.Equal(t, w1.Body.String(), w2.Body.String())
}
--- FAIL: TestCachePageStatus201 (0.50s)
    Error Trace:    cache_test.go:190
    Error:      Not equal: 201 (expected)
                    != 200 (actual)

FAIL
exit status 1