fix(config): 添加缺失的 Lua 配置默认值

- 补充 LuaMiddlewareConfig 默认配置
- 添加 Status.Format 字段默认值
- 简化验证逻辑

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
xfy 2026-04-13 13:15:31 +08:00
parent 742e261fdc
commit 75b0d0758b
2 changed files with 54 additions and 38 deletions

View File

@ -54,6 +54,17 @@ func DefaultConfig() *Config {
Token: "", Token: "",
}, },
}, },
Lua: &LuaMiddlewareConfig{
Enabled: false,
Scripts: []LuaScriptConfig{},
GlobalSettings: LuaGlobalSettings{
MaxConcurrentCoroutines: 1000,
CoroutineTimeout: 30 * time.Second,
CodeCacheSize: 1000,
EnableFileWatch: true,
MaxExecutionTime: 30 * time.Second,
},
},
Static: []StaticConfig{{ Static: []StaticConfig{{
Path: "/", Path: "/",
Root: "/var/www/html", Root: "/var/www/html",
@ -164,8 +175,9 @@ func DefaultConfig() *Config {
}, },
Monitoring: MonitoringConfig{ Monitoring: MonitoringConfig{
Status: StatusConfig{ Status: StatusConfig{
Path: "/_status", Path: "/_status",
Allow: []string{"127.0.0.1"}, Format: "text",
Allow: []string{"127.0.0.1"},
}, },
Pprof: PprofConfig{ Pprof: PprofConfig{
Enabled: false, Enabled: false,
@ -235,6 +247,37 @@ func GenerateConfigYAML(cfg *Config) ([]byte, error) {
fmt.Fprintf(&buf, " client_max_body_size: \"1MB\" # 请求体大小限制(支持单位: b, kb, mb, gb\n") fmt.Fprintf(&buf, " client_max_body_size: \"1MB\" # 请求体大小限制(支持单位: b, kb, mb, gb\n")
buf.WriteString("\n") buf.WriteString("\n")
// cache_api 配置
buf.WriteString(" # 缓存清理 API 配置(用于主动清理代理缓存)\n")
buf.WriteString(" # cache_api:\n")
fmt.Fprintf(&buf, " # enabled: %v # 是否启用缓存清理 API\n", cfg.Server.CacheAPI.Enabled)
fmt.Fprintf(&buf, " # path: \"%s\" # API 端点路径\n", cfg.Server.CacheAPI.Path)
buf.WriteString(" # allow: # 允许访问的 IP\n")
for _, ip := range cfg.Server.CacheAPI.Allow {
fmt.Fprintf(&buf, " # - \"%s\"\n", ip)
}
buf.WriteString(" # auth: # 认证配置\n")
fmt.Fprintf(&buf, " # type: \"%s\" # 认证类型(有效值: none, token\n", cfg.Server.CacheAPI.Auth.Type)
buf.WriteString(" # token: \"\" # 认证令牌(支持环境变量 ${CACHE_API_TOKEN}\n")
buf.WriteString("\n")
// lua 配置
buf.WriteString(" # Lua 中间件配置(在请求处理流程中嵌入 Lua 脚本)\n")
buf.WriteString(" # lua:\n")
fmt.Fprintf(&buf, " # enabled: %v # 是否启用 Lua 中间件\n", cfg.Server.Lua.Enabled)
buf.WriteString(" # scripts: # Lua 脚本列表\n")
buf.WriteString(" # - path: \"/scripts/auth.lua\" # 脚本路径\n")
buf.WriteString(" # phase: \"access\" # 执行阶段(有效值: rewrite, access, content, log, header_filter, body_filter\n")
buf.WriteString(" # timeout: 10s # 执行超时\n")
buf.WriteString(" # enabled: true # 是否启用此脚本\n")
buf.WriteString(" # global_settings: # 全局设置\n")
buf.WriteString(" # max_concurrent_coroutines: 1000 # 最大并发协程数\n")
buf.WriteString(" # coroutine_timeout: 30s # 协程执行超时\n")
buf.WriteString(" # code_cache_size: 1000 # 字节码缓存条目数\n")
buf.WriteString(" # enable_file_watch: true # 启用文件变更检测\n")
buf.WriteString(" # max_execution_time: 30s # 最大执行时间\n")
buf.WriteString("\n")
// static 配置 // static 配置
buf.WriteString(" # 静态文件服务配置(支持多个目录)\n") buf.WriteString(" # 静态文件服务配置(支持多个目录)\n")
buf.WriteString(" static:\n") buf.WriteString(" static:\n")
@ -328,6 +371,7 @@ func GenerateConfigYAML(cfg *Config) ([]byte, error) {
fmt.Fprintf(&buf, " # idle_timeout: %ds # 空闲超时\n", int(cfg.Server.SSL.HTTP2.IdleTimeout.Seconds())) fmt.Fprintf(&buf, " # idle_timeout: %ds # 空闲超时\n", int(cfg.Server.SSL.HTTP2.IdleTimeout.Seconds()))
fmt.Fprintf(&buf, " # push_enabled: %v # 是否启用 Server Push\n", cfg.Server.SSL.HTTP2.PushEnabled) fmt.Fprintf(&buf, " # push_enabled: %v # 是否启用 Server Push\n", cfg.Server.SSL.HTTP2.PushEnabled)
fmt.Fprintf(&buf, " # h2c_enabled: %v # 是否启用 H2C明文 HTTP/2\n", cfg.Server.SSL.HTTP2.H2CEnabled) fmt.Fprintf(&buf, " # h2c_enabled: %v # 是否启用 H2C明文 HTTP/2\n", cfg.Server.SSL.HTTP2.H2CEnabled)
fmt.Fprintf(&buf, " # graceful_shutdown_timeout: %ds # HTTP/2 优雅关闭超时\n", int(cfg.Server.SSL.HTTP2.GracefulShutdownTimeout.Seconds()))
buf.WriteString("\n") buf.WriteString("\n")
// security 配置 // security 配置
@ -548,6 +592,7 @@ func GenerateConfigYAML(cfg *Config) ([]byte, error) {
buf.WriteString("monitoring:\n") buf.WriteString("monitoring:\n")
buf.WriteString(" status:\n") buf.WriteString(" status:\n")
fmt.Fprintf(&buf, " path: \"%s\" # 状态端点路径\n", cfg.Monitoring.Status.Path) fmt.Fprintf(&buf, " path: \"%s\" # 状态端点路径\n", cfg.Monitoring.Status.Path)
fmt.Fprintf(&buf, " format: \"%s\" # 输出格式(有效值: text, json, html\n", cfg.Monitoring.Status.Format)
buf.WriteString(" allow: # 允许访问的 IP\n") buf.WriteString(" allow: # 允许访问的 IP\n")
for _, ip := range cfg.Monitoring.Status.Allow { for _, ip := range cfg.Monitoring.Status.Allow {
fmt.Fprintf(&buf, " - \"%s\"\n", ip) fmt.Fprintf(&buf, " - \"%s\"\n", ip)

View File

@ -21,6 +21,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"slices"
"strings" "strings"
"rua.plus/lolly/internal/loadbalance" "rua.plus/lolly/internal/loadbalance"
@ -29,10 +30,8 @@ import (
// ValidateEnum 验证值是否在有效枚举列表中 // ValidateEnum 验证值是否在有效枚举列表中
func ValidateEnum(value string, validValues []string, fieldName string) error { func ValidateEnum(value string, validValues []string, fieldName string) error {
for _, v := range validValues { if slices.Contains(validValues, value) {
if value == v { return nil
return nil
}
} }
return fmt.Errorf("无效的 %s: %s仅支持 %v", fieldName, value, validValues) return fmt.Errorf("无效的 %s: %s仅支持 %v", fieldName, value, validValues)
} }
@ -760,14 +759,7 @@ func validateRewrite(r *RewriteRule) error {
// 验证标志 // 验证标志
validFlags := []string{"", "last", "redirect", "permanent", "break"} validFlags := []string{"", "last", "redirect", "permanent", "break"}
valid := false if !slices.Contains(validFlags, r.Flag) {
for _, f := range validFlags {
if r.Flag == f {
valid = true
break
}
}
if !valid {
return fmt.Errorf("无效的 flag: %s仅支持 last, redirect, permanent, break", r.Flag) return fmt.Errorf("无效的 flag: %s仅支持 last, redirect, permanent, break", r.Flag)
} }
@ -819,14 +811,7 @@ func validateLogging(l *LoggingConfig) error {
func validateSecurityHeaders(h *SecurityHeaders) error { func validateSecurityHeaders(h *SecurityHeaders) error {
// 验证 X-Frame-Options // 验证 X-Frame-Options
validFrameOptions := []string{"", "DENY", "SAMEORIGIN"} validFrameOptions := []string{"", "DENY", "SAMEORIGIN"}
valid := false if !slices.Contains(validFrameOptions, h.XFrameOptions) {
for _, opt := range validFrameOptions {
if h.XFrameOptions == opt {
valid = true
break
}
}
if !valid {
return fmt.Errorf("无效的 x_frame_options: %s仅支持 DENY, SAMEORIGIN 或空)", h.XFrameOptions) return fmt.Errorf("无效的 x_frame_options: %s仅支持 DENY, SAMEORIGIN 或空)", h.XFrameOptions)
} }
@ -836,14 +821,7 @@ func validateSecurityHeaders(h *SecurityHeaders) error {
"origin-when-cross-origin", "same-origin", "strict-origin", "origin-when-cross-origin", "same-origin", "strict-origin",
"strict-origin-when-cross-origin", "unsafe-url", "strict-origin-when-cross-origin", "unsafe-url",
} }
valid = false if !slices.Contains(validReferrerPolicies, h.ReferrerPolicy) {
for _, policy := range validReferrerPolicies {
if h.ReferrerPolicy == policy {
valid = true
break
}
}
if !valid {
return fmt.Errorf("无效的 referrer_policy: %s", h.ReferrerPolicy) return fmt.Errorf("无效的 referrer_policy: %s", h.ReferrerPolicy)
} }
@ -1023,14 +1001,7 @@ func validateLua(l *LuaMiddlewareConfig) error {
// 验证阶段值 // 验证阶段值
validPhases := []string{"rewrite", "access", "content", "log", "header_filter", "body_filter"} validPhases := []string{"rewrite", "access", "content", "log", "header_filter", "body_filter"}
valid := false if !slices.Contains(validPhases, script.Phase) {
for _, phase := range validPhases {
if script.Phase == phase {
valid = true
break
}
}
if !valid {
return fmt.Errorf("scripts[%d].phase 无效: %s仅支持 rewrite, access, content, log, header_filter, body_filter", i, script.Phase) return fmt.Errorf("scripts[%d].phase 无效: %s仅支持 rewrite, access, content, log, header_filter, body_filter", i, script.Phase)
} }