Files
李建琦 6d655c9903
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
2026-08-21 18:30:13 +08:00

54 lines
1.6 KiB
Go

//go:build embed || unit
package web
import (
"net/http"
"path"
"strings"
)
// Vite emits content-hashed filenames under assets/, so the backend can apply
// immutable caching without relying on a reverse proxy to classify paths.
const staticAssetsCacheControl = "public, max-age=31536000, immutable"
// isFingerprintedEmbeddedAssetPath reports whether a cleaned URL path refers to
// a Vite asset whose filename contains the default eight-character build hash.
func isFingerprintedEmbeddedAssetPath(cleanPath string) bool {
cleanPath = strings.TrimPrefix(cleanPath, "/")
if !strings.HasPrefix(cleanPath, "assets/") {
return false
}
filename := path.Base(cleanPath)
extension := path.Ext(filename)
stem := strings.TrimSuffix(filename, extension)
const fingerprintLength = 8
delimiterIndex := len(stem) - fingerprintLength - 1
if extension == "" || delimiterIndex < 1 || stem[delimiterIndex] != '-' {
return false
}
// Vite hashes use URL-safe characters and are stable for immutable caching.
fingerprint := stem[delimiterIndex+1:]
for _, char := range fingerprint {
if (char >= 'a' && char <= 'z') ||
(char >= 'A' && char <= 'Z') ||
(char >= '0' && char <= '9') ||
char == '_' || char == '-' {
continue
}
return false
}
return true
}
// applyStaticAssetCacheHeaders sets Cache-Control for long-cacheable static paths.
// index.html / SPA routes must keep no-cache and are not handled here.
func applyStaticAssetCacheHeaders(header http.Header, cleanPath string) {
if header == nil || !isFingerprintedEmbeddedAssetPath(cleanPath) {
return
}
header.Set("Cache-Control", staticAssetsCacheControl)
}