mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-06 23:56:37 +08:00
feat(option): add sw offline
fix(openresty): scope sw injection per cert partition fix(lint): satisfy revive and biome format for sw offline feature docs: sw offline scope changelog fix(frontend): use scoped query key for sw scope zones fix(frontend): hide preview link in sw contact page editor feat(frontend): add sw scope domain picker and contact page fields refactor(frontend): generalize html editor workspace for reuse feat(openresty): scope sw offline injection by route domains feat(openresty): add sw offline domains snapshot field feat(option): add sw offline domains scope option docs: fill html editor workspace generalization detail docs: sw offline scope implementation plan docs: sw offline scope design test(openresty): assert single merged access block in sw enabled servers fix(openresty): restrict sw intercept to https server blocks fix(openresty): version sw offline cache by html content fix(agent): escape redir in sw challenge page to prevent xss fix(agent): return sw.runtime module table and add lua spec docs: sw offline fallback changelog fix(frontend): memoize option map to preserve unsaved contact page edits feat(frontend): add response pages module with contact page tab feat(agent): ship sw offline lua assets and placeholder substitution feat(config): wire sw offline options into config snapshot feat(openresty): render sw offline assets and challenge intercept feat(openresty): add sw offline ConfigSnapshot fields and placeholder feat(db): seed sw offline options feat(option): add sw offline config keys and validation docs: add service worker offline fallback implementation plan docs: adopt global-option pattern for SW offline fallback (matches origin error page) docs: unify offline contact page with error pages as response pages docs: service worker offline fallback design (issue #23)
This commit is contained in:
@@ -14,7 +14,10 @@ import (
|
||||
openrestyrender "github.com/Rain-kl/Wavelet/pkg/render/openresty"
|
||||
)
|
||||
|
||||
const maxOriginErrorPageHTMLBytes = 256 << 10 // 256 KiB
|
||||
const (
|
||||
maxOriginErrorPageHTMLBytes = 256 << 10 // 256 KiB
|
||||
maxSWOfflineDomains = 1000
|
||||
)
|
||||
|
||||
var openRestyOptionValidators = map[string]func(key, value string) error{
|
||||
model.ConfigKeyOpenRestyDefaultServerReturnStatus: validateOpenRestyDefaultServerReturnStatus,
|
||||
@@ -62,13 +65,16 @@ var openRestyOptionValidators = map[string]func(key, value string) error{
|
||||
model.ConfigKeyOriginErrorPageStatusCodes: validateOriginErrorPageStatusCodes,
|
||||
model.ConfigKeyOriginErrorPageHTML: validateOriginErrorPageHTML,
|
||||
model.ConfigKeyOriginErrorPageGetOnly: validateBooleanOption,
|
||||
model.ConfigKeySWOfflineEnabled: validateBooleanOption,
|
||||
model.ConfigKeySWOfflineHTML: validateSWOfflineHTML,
|
||||
model.ConfigKeySWOfflineDomains: validateSWOfflineDomains,
|
||||
}
|
||||
|
||||
var openRestyDefaultLimitRatePattern = regexp.MustCompile(`^\d+[kKmM]?$`)
|
||||
|
||||
func validateOpenRestyOption(key, value string) error {
|
||||
// HTML 按原始字节长度校验,避免 TrimSpace 影响上限判断
|
||||
if key == model.ConfigKeyOriginErrorPageHTML {
|
||||
if key == model.ConfigKeyOriginErrorPageHTML || key == model.ConfigKeySWOfflineHTML {
|
||||
return validateOriginErrorPageHTML(key, value)
|
||||
}
|
||||
trimmed := strings.TrimSpace(value)
|
||||
@@ -247,3 +253,29 @@ func validateOriginErrorPageHTML(key, value string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateSWOfflineHTML(key, value string) error {
|
||||
return validateOriginErrorPageHTML(key, value)
|
||||
}
|
||||
|
||||
func validateSWOfflineDomains(key, value string) error {
|
||||
var domains []string
|
||||
if err := json.Unmarshal([]byte(value), &domains); err != nil {
|
||||
return fmt.Errorf("%s 必须为 JSON 字符串数组", key)
|
||||
}
|
||||
if len(domains) > maxSWOfflineDomains {
|
||||
return fmt.Errorf("%s 最多支持 %d 个域名", key, maxSWOfflineDomains)
|
||||
}
|
||||
seen := make(map[string]struct{}, len(domains))
|
||||
for _, raw := range domains {
|
||||
domain := strings.ToLower(strings.TrimSpace(raw))
|
||||
if domain == "" {
|
||||
return fmt.Errorf("%s 包含空域名", key)
|
||||
}
|
||||
if _, ok := seen[domain]; ok {
|
||||
return fmt.Errorf("%s 包含重复域名 %s", key, domain)
|
||||
}
|
||||
seen[domain] = struct{}{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user