diff --git a/go.mod b/go.mod index 77ef130..fe3214d 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/gin-contrib/cors v1.7.2 github.com/gin-gonic/gin v1.12.0 - github.com/go-gost/core v0.6.0 + github.com/go-gost/core v0.6.1 github.com/go-gost/go-shadowsocks2 v0.1.4 github.com/go-gost/gosocks4 v0.1.0 github.com/go-gost/gosocks5 v0.5.0 diff --git a/go.sum b/go.sum index 1071c1a..8e9f048 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,8 @@ github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= -github.com/go-gost/core v0.6.0 h1:Y7jG5bI0QxdzDlMOyEtAYxCz+0GxAHKmaei667pRPWc= -github.com/go-gost/core v0.6.0/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A= +github.com/go-gost/core v0.6.1 h1:mBBvZpxIbrspuRsksj7YLHEiBGEc+sQBV3wDs4rX/AE= +github.com/go-gost/core v0.6.1/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A= github.com/go-gost/go-shadowsocks2 v0.1.4 h1:n2Po4TDKdLp1PsvhSiWFB/6S4e/YKZfsKJkA0PUa168= github.com/go-gost/go-shadowsocks2 v0.1.4/go.mod h1:866zFNNI3He6Wef1M/IvAjTal74WhcfKfBgRpTlkKys= github.com/go-gost/gosocks4 v0.1.0 h1:eAzev6qw4fzkFQKC9uCHLVNnnPdHyqCggbnfNN80Pmk= diff --git a/internal/util/httpcache/httpcache.go b/internal/util/httpcache/httpcache.go index 9bcea78..b934196 100644 --- a/internal/util/httpcache/httpcache.go +++ b/internal/util/httpcache/httpcache.go @@ -133,7 +133,17 @@ func (c *Cache) Cacheable(req *http.Request, resp *http.Response) bool { if !c.CacheableRequest(req) { return false } - return resp.StatusCode >= 200 && resp.StatusCode < 400 + if resp.StatusCode < 200 || resp.StatusCode >= 400 { + return false + } + // A Turbo/pjax short-circuit response carries only a handful of + // version tags (not the full page) and is meant to be merged with the + // client's already-rendered page. Caching it would serve a blank/partial + // page on a later hit. Never cache these. + if resp.Header.Get("X-Turbo-Short-Circuit") == "true" { + return false + } + return true } // TTLFor returns the TTL to apply for a response with the given status. @@ -184,10 +194,18 @@ func (c *Cache) Lookup(ctx context.Context, req *http.Request) (resp *http.Respo // Store saves a serialized response (as produced by resp.Write) under req's // key, using the TTL for status. func (c *Cache) Store(ctx context.Context, req *http.Request, data []byte, status int) error { + return c.StoreKey(ctx, Key(req.Method, req.Host, req.RequestURI), data, status) +} + +// StoreKey saves data under an explicit key using the TTL for status. +// Callers whose request identity is mutated before the response is stored +// (e.g. Host rewritten for mirror routing) must capture the pre-rewrite key +// and pass it here, so Lookup and Store agree on the same key. +func (c *Cache) StoreKey(ctx context.Context, key string, data []byte, status int) error { if c == nil { return nil } - return c.store.Set(ctx, Key(req.Method, req.Host, req.RequestURI), data, cache.WithTTL(c.TTLFor(status))) + return c.store.Set(ctx, key, data, cache.WithTTL(c.TTLFor(status))) } // TeeWriter wraps w so bytes written to it are also captured for caching, up