mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 10:42:57 +00:00
71 lines
2.8 KiB
Go
71 lines
2.8 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// AssetCacheControl sets optimal Cache-Control headers for static assets served by this server.
|
|
// It only affects GET requests for well-known static prefixes and does not override
|
|
// cache headers explicitly set by handlers downstream (they can still modify after c.Next if needed).
|
|
func AssetCacheControl() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
// Only apply to GET requests
|
|
if c.Request.Method == http.MethodGet {
|
|
p := c.Request.URL.Path
|
|
lower := strings.ToLower(p)
|
|
switch {
|
|
// Specific: YouTube channel static cache can be cached longer (content changes infrequently)
|
|
case strings.HasPrefix(lower, "/cache/prefetch/") && strings.HasSuffix(lower, "youtube_channel.json"):
|
|
c.Header("Cache-Control", "public, max-age=3600") // 1 hour
|
|
case strings.HasPrefix(lower, "/dist/"):
|
|
// Fingerprinted build assets should be cached for a year and immutable
|
|
c.Header("Cache-Control", "public, max-age=31536000, immutable")
|
|
case strings.HasPrefix(lower, "/uploads/"):
|
|
// User uploads: cache for a week; allow clients to revalidate if replaced
|
|
// Heuristic: if file name appears fingerprinted (e.g., .<hash>.ext), use longer cache
|
|
base := filepath.Base(lower)
|
|
if looksFingerprinted(base) {
|
|
c.Header("Cache-Control", "public, max-age=31536000, immutable")
|
|
} else {
|
|
c.Header("Cache-Control", "public, max-age=604800") // 7 days
|
|
}
|
|
case strings.HasPrefix(lower, "/cache/"):
|
|
// Prefetched JSON and other generated cache files: short to medium cache
|
|
c.Header("Cache-Control", "public, max-age=300") // 5 minutes
|
|
}
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// looksFingerprinted checks if a filename contains a long hex-like segment before the extension
|
|
// e.g. logo.7eacd9f0bfa04928a9b6936140168f58.png
|
|
func looksFingerprinted(name string) bool {
|
|
dot := strings.LastIndexByte(name, '.')
|
|
if dot <= 0 || dot >= len(name)-1 {
|
|
return false
|
|
}
|
|
core := name[:dot]
|
|
// Find final segment after last dot/underscore/hyphen in core
|
|
lastSep := strings.LastIndexAny(core, "._-")
|
|
if lastSep < 0 || lastSep+1 >= len(core) {
|
|
return false
|
|
}
|
|
seg := core[lastSep+1:]
|
|
if len(seg) < 16 { // require at least 16 chars to treat as a hash
|
|
return false
|
|
}
|
|
// hex-like check
|
|
for i := 0; i < len(seg); i++ {
|
|
ch := seg[i]
|
|
if !((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f')) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|