Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
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
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
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
//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)
|
||||
}
|
||||
Reference in New Issue
Block a user