httpcache: guard Turbo short-circuit responses, add StoreKey

Cacheable() now refuses X-Turbo-Short-Circuit responses (partial <meta>
payloads meant to merge client-side, would serve blank pages on later
hits). StoreKey() lets callers whose request identity is rewritten before
store (e.g. mirror Host routing) pin the key so Lookup and Store agree.

Bump github.com/go-gost/core to v0.6.1.
This commit is contained in:
ginuerzh
2026-08-29 09:23:26 +08:00
parent 2299c43bb7
commit 14fed91c62
3 changed files with 23 additions and 5 deletions
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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=
+20 -2
View File
@@ -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 <meta>
// 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