fix(server,app,proxy,resolver,middleware,lua): add nil guards and safe defaults

- server: reject Start() when config is nil to prevent panic
- app_common: guard empty Servers slice in initHTTP2/3 and logServerAddresses
- proxy/health: handle nil HealthCheckConfig with defaults
- resolver: handle nil ResolverConfig by returning noopResolver
- middleware/headers: skip UpdateConfig when cfg is nil
- middleware/sliding_window: enforce minimum window duration of 1s
- lua/api_log: map EMERG/ALERT/CRIT to Error() instead of Fatal()
  to prevent Lua scripts from killing the entire server process
This commit is contained in:
xfy 2026-06-11 16:23:04 +08:00
parent 818aa23739
commit e733273139
7 changed files with 19 additions and 4 deletions

View File

@ -94,6 +94,9 @@ func (a *App) initVariables() {
func (a *App) logServerAddresses() { func (a *App) logServerAddresses() {
a.logger.LogStartup("Config loaded successfully", map[string]string{"config_path": a.cfgPath}) a.logger.LogStartup("Config loaded successfully", map[string]string{"config_path": a.cfgPath})
if len(a.cfg.Servers) == 0 {
return
}
mode := a.cfg.GetMode() mode := a.cfg.GetMode()
if mode == config.ServerModeMultiServer { if mode == config.ServerModeMultiServer {
for i, srv := range a.cfg.Servers { for i, srv := range a.cfg.Servers {
@ -173,7 +176,7 @@ func (a *App) initStreamServers() {
// initHTTP3 starts the HTTP/3 server if enabled. // initHTTP3 starts the HTTP/3 server if enabled.
func (a *App) initHTTP3() { func (a *App) initHTTP3() {
if !a.cfg.HTTP3.Enabled || a.cfg.Servers[0].SSL.Cert == "" { if len(a.cfg.Servers) == 0 || !a.cfg.HTTP3.Enabled || a.cfg.Servers[0].SSL.Cert == "" {
return return
} }
@ -199,7 +202,7 @@ func (a *App) initHTTP3() {
// initHTTP2 starts the HTTP/2 server if enabled. // initHTTP2 starts the HTTP/2 server if enabled.
func (a *App) initHTTP2() { func (a *App) initHTTP2() {
if !a.cfg.Servers[0].SSL.HTTP2.Enabled || a.cfg.Servers[0].SSL.Cert == "" { if len(a.cfg.Servers) == 0 || !a.cfg.Servers[0].SSL.HTTP2.Enabled || a.cfg.Servers[0].SSL.Cert == "" {
return return
} }

View File

@ -248,7 +248,7 @@ func (api *ngxLogAPI) luaLog(L *glua.LState) int {
if api.logger != nil { if api.logger != nil {
switch level { switch level {
case LogEmerg, LogAlert, LogCrit: case LogEmerg, LogAlert, LogCrit:
api.logger.Fatal().Msg(msg) api.logger.Error().Str("lua_level", "critical").Msg(msg)
case LogErr: case LogErr:
api.logger.Error().Msg(msg) api.logger.Error().Msg(msg)
case LogWarn: case LogWarn:

View File

@ -211,6 +211,9 @@ func formatHSTSValue(maxAge int, includeSubDomains bool, preload bool) string {
// 参数: // 参数:
// - cfg: 新的安全头配置 // - cfg: 新的安全头配置
func (sh *HeadersMiddleware) UpdateConfig(cfg *config.SecurityHeaders) { func (sh *HeadersMiddleware) UpdateConfig(cfg *config.SecurityHeaders) {
if cfg == nil {
return
}
sh.mu.Lock() sh.mu.Lock()
sh.config = cfg sh.config = cfg
sh.formatHSTS() sh.formatHSTS()

View File

@ -87,6 +87,9 @@ type windowCounter struct {
// 返回值: // 返回值:
// - *SlidingWindowLimiter: 创建的限流器实例 // - *SlidingWindowLimiter: 创建的限流器实例
func NewSlidingWindowLimiter(window time.Duration, limit int, precise bool) *SlidingWindowLimiter { func NewSlidingWindowLimiter(window time.Duration, limit int, precise bool) *SlidingWindowLimiter {
if window <= 0 {
window = time.Second
}
s := &SlidingWindowLimiter{ s := &SlidingWindowLimiter{
window: window, window: window,
limit: limit, limit: limit,

View File

@ -78,6 +78,9 @@ type HealthChecker struct {
// //
// 返回的 HealthChecker 尚未启动;调用 Start() 开始健康检查。 // 返回的 HealthChecker 尚未启动;调用 Start() 开始健康检查。
func NewHealthChecker(targets []*loadbalance.Target, cfg *config.HealthCheckConfig) *HealthChecker { func NewHealthChecker(targets []*loadbalance.Target, cfg *config.HealthCheckConfig) *HealthChecker {
if cfg == nil {
cfg = &config.HealthCheckConfig{}
}
interval := cfg.Interval interval := cfg.Interval
if interval <= 0 { if interval <= 0 {
interval = 10 * time.Second interval = 10 * time.Second

View File

@ -131,7 +131,7 @@ type DNSCacheEntry struct {
// 返回值: // 返回值:
// - Resolver: DNS 解析器接口实现,禁用时返回 noopResolver // - Resolver: DNS 解析器接口实现,禁用时返回 noopResolver
func New(cfg *config.ResolverConfig) Resolver { func New(cfg *config.ResolverConfig) Resolver {
if !cfg.Enabled { if cfg == nil || !cfg.Enabled {
return &noopResolver{} return &noopResolver{}
} }

View File

@ -268,6 +268,9 @@ func (s *Server) GetHandler() fasthttp.RequestHandler {
// - 调用前需确保配置已正确加载 // - 调用前需确保配置已正确加载
// - Goroutine池和文件缓存根据配置自动启用 // - Goroutine池和文件缓存根据配置自动启用
func (s *Server) Start() error { func (s *Server) Start() error {
if s.config == nil {
return fmt.Errorf("server config is nil")
}
logging.Init(s.config.Logging.Error.Level, s.config.Logging.Format) logging.Init(s.config.Logging.Error.Level, s.config.Logging.Format)
// 记录启动时间 // 记录启动时间