// Package config 提供 YAML 配置文件的解析、验证和默认配置生成功能。 // // 该文件包含默认配置生成功能,包括: // - DefaultConfig 函数:返回带合理默认值的配置结构体 // - GenerateConfigYAML 函数:生成带注释的示例配置文件 // // 主要用途: // // 用于生成默认配置和示例配置文件,便于用户快速上手。 // // 注意事项: // - 默认值经过优化,适合大多数常见场景 // - 生成的 YAML 包含详细注释说明 // // 作者:xfy package config import ( "bytes" "fmt" "time" ) // DefaultConfig 返回带默认值的配置结构体。 // // 返回一个预填充了合理默认值的配置对象,包含服务器、 // SSL、安全、压缩、日志、性能和监控等各模块的默认设置。 // // 返回值: // - *Config: 带默认值的配置对象 // // 默认值说明: // - 监听地址: :8080 // - 超时: 读取/写入 30s,空闲 120s // - TLS: 仅支持 TLSv1.2 和 TLSv1.3 // - 安全头部: X-Frame-Options=DENY, X-Content-Type-Options=nosniff // - 压缩: gzip,级别 6,最小 1024 字节 func DefaultConfig() *Config { return &Config{ Servers: []ServerConfig{{ Listen: ":8080", Name: "localhost", ReadTimeout: 30 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 120 * time.Second, MaxConnsPerIP: 1000, MaxRequestsPerConn: 10000, ClientMaxBodySize: "10MB", // 高并发优化配置默认值 Concurrency: 256 * 1024, // 256K 最大并发连接 ReadBufferSize: 16 * 1024, // 16KB 读缓冲 WriteBufferSize: 16 * 1024, // 16KB 写缓冲 ReduceMemoryUsage: false, // 优先性能 CacheAPI: &CacheAPIConfig{ Enabled: false, Path: "/_cache/purge", Allow: []string{"127.0.0.1"}, Auth: CacheAPIAuthConfig{ Type: "none", 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{{ Path: "/", Root: "/var/www/html", Index: []string{"index.html", "index.htm"}, }}, SSL: SSLConfig{ Protocols: []string{"TLSv1.2", "TLSv1.3"}, OCSPStapling: false, HSTS: HSTSConfig{ MaxAge: 31536000, IncludeSubDomains: true, Preload: false, }, HTTP2: HTTP2Config{ Enabled: true, MaxConcurrentStreams: 128, MaxHeaderListSize: 1048576, // 1MB IdleTimeout: 120 * time.Second, PushEnabled: false, H2CEnabled: false, GracefulShutdownTimeout: 30 * time.Second, }, SessionTickets: SessionTicketsConfig{ Enabled: false, KeyFile: "", RotateInterval: 1 * time.Hour, RetainKeys: 3, }, ClientVerify: ClientVerifyConfig{ Enabled: false, Mode: "none", ClientCA: "", VerifyDepth: 1, CRL: "", }, }, Security: SecurityConfig{ Access: AccessConfig{ Allow: []string{}, Deny: []string{}, Default: "allow", GeoIP: GeoIPConfig{ CacheSize: 10000, CacheTTL: 3600 * time.Second, }, }, RateLimit: RateLimitConfig{ RequestRate: 0, Burst: 0, ConnLimit: 0, Key: "ip", Algorithm: "token_bucket", SlidingWindowMode: "approximate", SlidingWindow: 60, }, Auth: AuthConfig{ RequireTLS: true, Algorithm: "bcrypt", Realm: "Restricted Area", MinPasswordLength: 8, }, Headers: SecurityHeaders{ XFrameOptions: "DENY", XContentTypeOptions: "nosniff", ReferrerPolicy: "strict-origin-when-cross-origin", }, AuthRequest: AuthRequestConfig{ Timeout: 5 * time.Second, }, }, Compression: CompressionConfig{ Type: "gzip", Level: 6, MinSize: 1024, GzipStatic: false, GzipStaticExtensions: []string{".br", ".gz"}, Types: []string{ "text/html", "text/css", "text/javascript", "application/json", "application/javascript", }, }, }}, Logging: LoggingConfig{ Format: "text", Access: AccessLogConfig{ // 近似 nginx combined 格式 // nginx: $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" // lolly: $request 不含 HTTP 版本,$time 为 RFC3339 格式 Format: "$remote_addr - $remote_user [$time] \"$request\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\"", }, Error: ErrorLogConfig{ Level: "info", }, }, Performance: PerformanceConfig{ GoroutinePool: GoroutinePoolConfig{ Enabled: false, MaxWorkers: 1000, MinWorkers: 10, IdleTimeout: 60 * time.Second, }, FileCache: FileCacheConfig{ MaxEntries: 10000, MaxSize: 256 * 1024 * 1024, // 256MB Inactive: 20 * time.Second, }, Transport: TransportConfig{ IdleConnTimeout: 90 * time.Second, MaxConnsPerHost: 0, // 0 表示不限制 }, }, Monitoring: MonitoringConfig{ Status: StatusConfig{ Enabled: false, Path: "/_status", Format: "json", Allow: []string{"127.0.0.1", "localhost"}, }, Pprof: PprofConfig{ Enabled: false, Path: DefaultPprofPath, Allow: []string{"127.0.0.1"}, }, }, HTTP3: HTTP3Config{ Enabled: false, Listen: ":443", MaxStreams: 100, IdleTimeout: 60 * time.Second, Enable0RTT: false, }, Resolver: ResolverConfig{ Enabled: false, Addresses: []string{"8.8.8.8:53", "8.8.4.4:53"}, Valid: 30 * time.Second, Timeout: 5 * time.Second, IPv4: true, IPv6: false, CacheSize: 1024, }, Variables: VariablesConfig{ Set: map[string]string{}, }, Shutdown: ShutdownConfig{ GracefulTimeout: 30 * time.Second, FastTimeout: 5 * time.Second, }, } } // GenerateConfigYAML 生成带注释的默认配置 YAML。 // // 根据配置对象生成带详细注释的 YAML 配置文件内容, // 包含各配置项的说明和有效值提示。 // // 参数: // - cfg: 配置对象,用于填充 YAML 中的默认值 // // 返回值: // - []byte: 生成的 YAML 内容(包含注释) // - error: 当前实现始终返回 nil // // 注意事项: // - 生成的 YAML 包含中文注释,便于理解各配置项用途 // - 注释中包含有效值范围和默认值说明 func GenerateConfigYAML(cfg *Config) ([]byte, error) { // 手动构建带注释的 YAML var buf bytes.Buffer buf.WriteString("# Lolly 配置文件\n") buf.WriteString("\n") // mode 配置 buf.WriteString("# 运行模式配置\n") buf.WriteString("# mode: auto # 运行模式(有效值: single, vhost, multi_server, auto)\n") buf.WriteString("# auto: 自动推断模式(根据 servers 配置自动选择,默认)\n") buf.WriteString("# single: 单服务器模式(只有一个 server)\n") buf.WriteString("# vhost: 虚拟主机模式(多个 server 共享相同监听地址)\n") buf.WriteString("# multi_server: 多服务器模式(多个 server 监听不同地址)\n") buf.WriteString("\n") // servers 配置 buf.WriteString("# 服务器配置(多服务器模式)\n") buf.WriteString("servers:\n") buf.WriteString(" - # 服务器配置\n") fmt.Fprintf(&buf, " listen: \"%s\" # 监听地址\n", cfg.Servers[0].Listen) fmt.Fprintf(&buf, " name: \"%s\" # 服务器名称(虚拟主机匹配)\n", cfg.Servers[0].Name) buf.WriteString(" # server_names: # 多个 server_name(支持通配符和正则)\n") buf.WriteString(" # - \"example.com\" # 精确匹配\n") buf.WriteString(" # - \"*.example.com\" # 前缀通配(匹配 xxx.example.com)\n") buf.WriteString(" # - \"~^www\\.\" # 正则匹配(以 www. 开头)\n") buf.WriteString(" # unix_socket: # Unix socket 配置(监听 Unix 域套接字)\n") buf.WriteString(" # mode: 0666 # 文件权限\n") buf.WriteString(" # user: \"\" # 文件所有者(空表示当前用户)\n") buf.WriteString(" # group: \"\" # 文件组(空表示当前组)\n") buf.WriteString(" # default: false # 虚拟主机模式下标记为默认服务器(接收未匹配的请求)\n") fmt.Fprintf(&buf, " read_timeout: %ds # 读取超时(0 表示不限制)\n", int(cfg.Servers[0].ReadTimeout.Seconds())) fmt.Fprintf(&buf, " write_timeout: %ds # 写入超时(0 表示不限制)\n", int(cfg.Servers[0].WriteTimeout.Seconds())) fmt.Fprintf(&buf, " idle_timeout: %ds # 空闲超时(0 表示不限制)\n", int(cfg.Servers[0].IdleTimeout.Seconds())) fmt.Fprintf(&buf, " max_conns_per_ip: %d # 每 IP 最大连接数(0 表示不限制)\n", cfg.Servers[0].MaxConnsPerIP) fmt.Fprintf(&buf, " max_requests_per_conn: %d # 每连接最大请求数(0 表示不限制)\n", cfg.Servers[0].MaxRequestsPerConn) fmt.Fprintf(&buf, " client_max_body_size: \"%s\" # 请求体大小限制(支持单位: b, kb, mb, gb)\n", cfg.Servers[0].ClientMaxBodySize) buf.WriteString(" # 高并发优化配置(可选,未配置时使用默认值)\n") fmt.Fprintf(&buf, " # concurrency: %d # 最大并发连接数(默认 %d)\n", cfg.Servers[0].Concurrency, cfg.Servers[0].Concurrency) fmt.Fprintf(&buf, " # read_buffer_size: %d # 读缓冲区大小(字节,默认 %d)\n", cfg.Servers[0].ReadBufferSize, cfg.Servers[0].ReadBufferSize) fmt.Fprintf(&buf, " # write_buffer_size: %d # 写缓冲区大小(字节,默认 %d)\n", cfg.Servers[0].WriteBufferSize, cfg.Servers[0].WriteBufferSize) fmt.Fprintf(&buf, " # reduce_memory_usage: %v # 是否优先减少内存使用(默认 %v)\n", cfg.Servers[0].ReduceMemoryUsage, cfg.Servers[0].ReduceMemoryUsage) buf.WriteString(" # server_tokens: true # 是否在响应头中显示版本号(默认 true,false 隐藏 Server 头版本信息)\n") buf.WriteString("\n") // types 配置 buf.WriteString(" # MIME 类型配置\n") buf.WriteString(" # types:\n") buf.WriteString(" # default_type: \"application/octet-stream\" # 默认 MIME 类型(无法识别扩展名时使用)\n") buf.WriteString(" # map: # 自定义扩展名到 MIME 类型的映射\n") buf.WriteString(" # \".html\": \"text/html\"\n") buf.WriteString(" # \".css\": \"text/css\"\n") buf.WriteString(" # \".js\": \"application/javascript\"\n") buf.WriteString("\n") // limit_rate 配置 buf.WriteString(" # 响应速率限制配置(限制响应数据发送速率,防止单连接占用过多带宽)\n") buf.WriteString(" # limit_rate:\n") buf.WriteString(" # rate: 0 # 字节/秒(0 表示不限速)\n") buf.WriteString(" # burst: 0 # 突发流量字节数\n") buf.WriteString(" # large_file_threshold: 0 # 大文件阈值(字节),超过此大小采用特殊策略(0 表示不区分)\n") buf.WriteString(" # large_file_strategy: \"\" # 大文件策略(有效值: skip 跳过限速, coarse 粗粒度限速)\n") buf.WriteString("\n") // cache_api 配置 buf.WriteString(" # 缓存清理 API 配置(用于主动清理代理缓存)\n") buf.WriteString(" # cache_api:\n") fmt.Fprintf(&buf, " # enabled: %v # 是否启用缓存清理 API\n", cfg.Servers[0].CacheAPI.Enabled) fmt.Fprintf(&buf, " # path: \"%s\" # API 端点路径\n", cfg.Servers[0].CacheAPI.Path) buf.WriteString(" # allow: # 允许访问的 IP\n") for _, ip := range cfg.Servers[0].CacheAPI.Allow { fmt.Fprintf(&buf, " # - \"%s\"\n", ip) } buf.WriteString(" # auth: # 认证配置\n") fmt.Fprintf(&buf, " # type: \"%s\" # 认证类型(有效值: none, token)\n", cfg.Servers[0].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.Servers[0].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") fmt.Fprintf(&buf, " # max_concurrent_coroutines: %d # 最大并发协程数\n", cfg.Servers[0].Lua.GlobalSettings.MaxConcurrentCoroutines) fmt.Fprintf(&buf, " # coroutine_timeout: %ds # 协程执行超时\n", int(cfg.Servers[0].Lua.GlobalSettings.CoroutineTimeout.Seconds())) fmt.Fprintf(&buf, " # code_cache_size: %d # 字节码缓存条目数\n", cfg.Servers[0].Lua.GlobalSettings.CodeCacheSize) fmt.Fprintf(&buf, " # enable_file_watch: %v # 启用文件变更检测\n", cfg.Servers[0].Lua.GlobalSettings.EnableFileWatch) fmt.Fprintf(&buf, " # max_execution_time: %ds # 最大执行时间\n", int(cfg.Servers[0].Lua.GlobalSettings.MaxExecutionTime.Seconds())) fmt.Fprintf(&buf, " # coroutine_stack_size: %d # 协程栈大小(0=使用默认值)\n", cfg.Servers[0].Lua.GlobalSettings.CoroutineStackSize) fmt.Fprintf(&buf, " # coroutine_pool_warmup: %d # 协程池预热数量(0=不预热)\n", cfg.Servers[0].Lua.GlobalSettings.CoroutinePoolWarmup) fmt.Fprintf(&buf, " # minimize_stack_memory: %v # 最小化栈内存使用\n", cfg.Servers[0].Lua.GlobalSettings.MinimizeStackMemory) buf.WriteString("\n") // static 配置 buf.WriteString(" # 静态文件服务配置(支持多个目录)\n") buf.WriteString(" static:\n") for _, st := range cfg.Servers[0].Static { buf.WriteString(" - path: \"/\" # 匹配路径前缀\n") fmt.Fprintf(&buf, " root: \"%s\" # 静态文件根目录\n", st.Root) buf.WriteString(" index: # 索引文件\n") for _, idx := range st.Index { fmt.Fprintf(&buf, " - \"%s\"\n", idx) } buf.WriteString(" try_files: [] # SPA 部署示例: [\"$uri\", \"$uri/\", \"/index.html\"]\n") buf.WriteString(" try_files_pass: false # 内部重定向是否触发中间件\n") buf.WriteString(" symlink_check: false # 是否检查符号链接安全(防止路径遍历攻击)\n") buf.WriteString(" # location_type: \"\" # 位置匹配类型(有效值: exact, prefix, regex, regex_caseless, prefix_priority, named)\n") buf.WriteString(" # internal: false # 仅允许内部重定向访问\n") } buf.WriteString(" # 示例:额外的静态目录\n") buf.WriteString(" # - path: \"/assets/\"\n") buf.WriteString(" # root: \"/var/www/assets\"\n") buf.WriteString(" # index: [\"index.html\"]\n") buf.WriteString("\n") // proxy 配置示例 buf.WriteString(" # 反向代理配置\n") buf.WriteString(" # proxy:\n") buf.WriteString(" # - path: /api # 匹配路径前缀\n") buf.WriteString(" # location_type: \"prefix\" # 匹配类型(有效值: exact, prefix_priority, regex, regex_caseless, prefix, named)\n") buf.WriteString(" # location_name: \"\" # 命名 location 名称(仅 location_type=named 时使用,如 @fallback)\n") buf.WriteString(" # targets: # 后端目标列表\n") buf.WriteString(" # - url: http://backend1:8080\n") buf.WriteString(" # weight: 3 # 权重(加权轮询时有效)\n") buf.WriteString(" # - url: http://backend2:8080\n") buf.WriteString(" # weight: 1\n") buf.WriteString(" # max_conns: 0 # 单目标最大并发连接(0 为不限制)\n") buf.WriteString(" # max_fails: 1 # 最大失败次数\n") buf.WriteString(" # fail_timeout: \"10s\" # 失败超时时间\n") buf.WriteString(" # backup: false # 备份服务器标记(仅当主服务器不可用时使用)\n") buf.WriteString(" # down: false # 永久不可用标记\n") buf.WriteString(" # proxy_uri: \"\" # 代理传递的 URI 路径\n") buf.WriteString(" # load_balance: round_robin # 负载均衡算法(有效值: round_robin, weighted_round_robin, least_conn, ip_hash, consistent_hash, random)\n") buf.WriteString(" # hash_key: ip # 一致性哈希键(仅 load_balance=consistent_hash 时有效,有效值: ip, uri, header:X-Name)\n") buf.WriteString(" # virtual_nodes: 150 # 一致性哈希虚拟节点数(仅 load_balance=consistent_hash 时有效)\n") buf.WriteString(" # health_check: # 健康检查\n") buf.WriteString(" # interval: 10s\n") buf.WriteString(" # path: /health\n") buf.WriteString(" # timeout: 5s\n") buf.WriteString(" # timeout: # 超时配置\n") buf.WriteString(" # connect: 5s # 连接超时\n") buf.WriteString(" # read: 30s # 读取超时\n") buf.WriteString(" # write: 30s # 写入超时\n") buf.WriteString(" # buffering: # 代理缓冲配置\n") buf.WriteString(" # mode: \"default\" # 缓冲模式(有效值: default, on, off;off 为流式转发)\n") buf.WriteString(" # buffer_size: 0 # 响应缓冲区大小(字节,0 表示使用默认值)\n") buf.WriteString(" # proxy_bind: \"\" # 代理拨号绑定本地地址\n") buf.WriteString(" # internal: false # 仅允许内部重定向访问\n") buf.WriteString(" # headers: # 头部修改\n") buf.WriteString(" # set_request: {X-Custom: value}\n") buf.WriteString(" # set_response: {X-Server: lolly}\n") buf.WriteString(" # remove: [X-Powered-By]\n") buf.WriteString(" # hide_response: [] # 隐藏的响应头列表\n") buf.WriteString(" # pass_response: [] # 白名单传递的响应头\n") buf.WriteString(" # ignore_headers: [] # 完全忽略的头部(不传递给客户端也不记录)\n") buf.WriteString(" # cookie_domain: \"\" # Cookie 域重写\n") buf.WriteString(" # cookie_path: \"\" # Cookie 路径重写\n") buf.WriteString(" # cache: # 代理缓存\n") buf.WriteString(" # enabled: false\n") buf.WriteString(" # max_age: 60s\n") buf.WriteString(" # methods: [GET, HEAD] # 可缓存的 HTTP 方法(默认 GET, HEAD)\n") buf.WriteString(" # min_uses: 1 # 缓存阈值,请求次数达到此值才缓存(默认 1)\n") buf.WriteString(" # cache_lock: true # 防止缓存击穿\n") buf.WriteString(" # cache_lock_timeout: 5s # 缓存锁超时时间(默认 5s)\n") buf.WriteString(" # stale_while_revalidate: 30s\n") buf.WriteString(" # background_update_disable: false # 禁用后台更新(默认启用)\n") buf.WriteString(" # cache_ignore_headers: [] # 缓存时忽略的响应头\n") buf.WriteString(" # revalidate: false # 启用条件请求(默认关闭)\n") buf.WriteString(" # cache_valid: # 按 HTTP 状态码细分缓存时间(可选,未配置时使用 max_age)\n") buf.WriteString(" # ok: 10m # 200-299 缓存 10 分钟\n") buf.WriteString(" # redirect: 1h # 301/302 缓存 1 小时\n") buf.WriteString(" # not_found: 1m # 404 缓存 1 分钟\n") buf.WriteString(" # client_error: 0 # 其他 4xx 不缓存\n") buf.WriteString(" # server_error: 0 # 5xx 不缓存\n") buf.WriteString(" # proxy_ssl: # 上游 SSL 配置(加密到后端的连接)\n") buf.WriteString(" # enabled: false # 是否启用上游 TLS\n") buf.WriteString(" # server_name: \"\" # SNI 服务器名称\n") buf.WriteString(" # trusted_ca: \"\" # 信任的 CA 证书\n") buf.WriteString(" # client_cert: \"\" # 客户端证书(mTLS)\n") buf.WriteString(" # client_key: \"\" # 客户端私钥(mTLS)\n") buf.WriteString(" # min_version: \"TLSv1.2\" # 最小 TLS 版本\n") buf.WriteString(" # max_version: \"\" # 最大 TLS 版本(空表示不限制)\n") buf.WriteString(" # insecure_skip_verify: false # 跳过证书验证(仅测试用)\n") buf.WriteString(" # client_max_body_size: \"50MB\" # 此代理路径的请求体限制\n") buf.WriteString(" # next_upstream: # 故障转移配置\n") buf.WriteString(" # tries: 1 # 最大尝试次数(1 表示禁用故障转移)\n") buf.WriteString(" # http_codes: [502, 503, 504] # 触发重试的 HTTP 状态码\n") buf.WriteString(" # balancer_by_lua: # Lua 动态负载均衡(在 load_balance 基础上自定义选择逻辑)\n") buf.WriteString(" # enabled: false # 是否启用 Lua 负载均衡\n") buf.WriteString(" # script: \"\" # Lua 脚本路径,返回目标索引\n") buf.WriteString(" # fallback: \"round_robin\" # Lua 失败时的备用算法(有效值: round_robin, weighted_round_robin, least_conn, ip_hash, consistent_hash, random)\n") buf.WriteString(" # timeout: 5s # Lua 执行超时\n") buf.WriteString(" # redirect_rewrite: # Location/Refresh 头改写配置(代理响应重定向时改写 Location 头)\n") buf.WriteString(" # mode: \"default\" # 运行模式(有效值: default, off, custom)\n") buf.WriteString(" # # default: 自动从选中的 target URL 生成规则(运行时)\n") buf.WriteString(" # # off: 禁用改写\n") buf.WriteString(" # # custom: 使用 rules 列表(预编译)\n") buf.WriteString(" # rules: [] # 改写规则列表(仅 mode=\"custom\" 时使用)\n") buf.WriteString(" # # 示例规则(custom 模式):\n") buf.WriteString(" # # - pattern: \"http://localhost:8000/\" # 匹配模式(无 ~ 前缀为前缀匹配,~ 开头为正则)\n") buf.WriteString(" # # replacement: \"$scheme://$host:$server_port/\" # 替换目标(支持 $host, $scheme, $server_port 等变量)\n") buf.WriteString(" # # - pattern: \"~^http://[^/]+:8000/(.*)$\" # 正则匹配示例\n") buf.WriteString(" # # replacement: \"$scheme://$host/$1\" # 使用捕获组 $1\n") buf.WriteString("\n") // SSL 配置 buf.WriteString(" # SSL/TLS 配置\n") buf.WriteString(" # ssl:\n") buf.WriteString(" # cert: /path/to/cert.pem # 证书文件\n") buf.WriteString(" # key: /path/to/key.pem # 私钥文件\n") buf.WriteString(" # cert_chain: /path/to/chain.pem # 证书链文件\n") buf.WriteString(" # protocols: # TLS 版本(有效值: TLSv1.2, TLSv1.3)\n") for _, proto := range cfg.Servers[0].SSL.Protocols { fmt.Fprintf(&buf, " # - \"%s\"\n", proto) } buf.WriteString(" # ciphers: # 加密套件(仅 TLS 1.2 有效,TLS 1.3 使用内置套件)\n") buf.WriteString(" # - ECDHE-ECDSA-AES256-GCM-SHA384\n") buf.WriteString(" # - ECDHE-RSA-AES256-GCM-SHA384\n") buf.WriteString(" # - ECDHE-ECDSA-CHACHA20-POLY1305\n") buf.WriteString(" # - ECDHE-RSA-CHACHA20-POLY1305\n") buf.WriteString(" # # 拒绝不安全套件:含 RC4、DES、3DES、CBC 的配置将报错\n") fmt.Fprintf(&buf, " # ocsp_stapling: %v # OCSP Stapling\n", cfg.Servers[0].SSL.OCSPStapling) buf.WriteString(" # hsts: # HTTP Strict Transport Security\n") fmt.Fprintf(&buf, " # max_age: %d # 过期时间(秒)\n", cfg.Servers[0].SSL.HSTS.MaxAge) fmt.Fprintf(&buf, " # include_sub_domains: %v # 包含子域名\n", cfg.Servers[0].SSL.HSTS.IncludeSubDomains) fmt.Fprintf(&buf, " # preload: %v # 加入 HSTS 预加载列表\n", cfg.Servers[0].SSL.HSTS.Preload) buf.WriteString(" # session_tickets: # TLS Session Tickets 配置(TLS 1.3 会话恢复)\n") fmt.Fprintf(&buf, " # enabled: %v # 是否启用 Session Tickets\n", cfg.Servers[0].SSL.SessionTickets.Enabled) buf.WriteString(" # key_file: \"\" # 密钥存储文件路径(用于持久化密钥)\n") fmt.Fprintf(&buf, " # rotate_interval: %d # 密钥轮换间隔(秒),建议 1-24 小时\n", int(cfg.Servers[0].SSL.SessionTickets.RotateInterval.Seconds())) fmt.Fprintf(&buf, " # retain_keys: %d # 保留的历史密钥数量,建议 3-5 个\n", cfg.Servers[0].SSL.SessionTickets.RetainKeys) buf.WriteString(" # client_verify: # mTLS 客户端证书验证配置\n") buf.WriteString(" # enabled: false # 是否启用客户端证书验证\n") buf.WriteString(" # mode: \"none\" # 验证模式(有效值: none, request, require, optional_no_ca)\n") buf.WriteString(" # client_ca: \"\" # 客户端 CA 证书文件路径\n") buf.WriteString(" # verify_depth: 1 # 证书链验证深度\n") buf.WriteString(" # crl: \"\" # 证书撤销列表文件路径(可选)\n") buf.WriteString(" # http2: # HTTP/2 配置(需 SSL 证书)\n") fmt.Fprintf(&buf, " # enabled: %v # 是否启用 HTTP/2\n", cfg.Servers[0].SSL.HTTP2.Enabled) fmt.Fprintf(&buf, " # max_concurrent_streams: %d # 最大并发流数\n", cfg.Servers[0].SSL.HTTP2.MaxConcurrentStreams) fmt.Fprintf(&buf, " # max_header_list_size: %d # 最大头部列表大小(字节)\n", cfg.Servers[0].SSL.HTTP2.MaxHeaderListSize) fmt.Fprintf(&buf, " # idle_timeout: %ds # 空闲超时\n", int(cfg.Servers[0].SSL.HTTP2.IdleTimeout.Seconds())) fmt.Fprintf(&buf, " # push_enabled: %v # 是否启用 Server Push\n", cfg.Servers[0].SSL.HTTP2.PushEnabled) fmt.Fprintf(&buf, " # h2c_enabled: %v # 是否启用 H2C(明文 HTTP/2)\n", cfg.Servers[0].SSL.HTTP2.H2CEnabled) fmt.Fprintf(&buf, " # graceful_shutdown_timeout: %ds # HTTP/2 优雅关闭超时\n", int(cfg.Servers[0].SSL.HTTP2.GracefulShutdownTimeout.Seconds())) buf.WriteString("\n") // SSL 默认值说明(即使不启用也展示默认配置) buf.WriteString(" # SSL/TLS 默认配置说明(未配置证书时不启用)\n") buf.WriteString(" # 默认 TLS 协议: TLSv1.2, TLSv1.3(不支持 TLSv1.0/1.1)\n") buf.WriteString(" # 默认 HSTS 配置: max_age=31536000(1年), include_sub_domains=true\n") buf.WriteString("\n") // security 配置 buf.WriteString(" # 安全配置\n") buf.WriteString(" security:\n") buf.WriteString(" # IP 访问控制\n") buf.WriteString(" access:\n") buf.WriteString(" allow: [] # 允许的 IP/CIDR 列表\n") buf.WriteString(" deny: [] # 拒绝的 IP/CIDR 列表\n") fmt.Fprintf(&buf, " default: \"%s\" # 默认动作(有效值: allow, deny)\n", cfg.Servers[0].Security.Access.Default) buf.WriteString(" trusted_proxies: [] # 可信代理 CIDR 列表,用于 X-Forwarded-For 解析\n") buf.WriteString("\n") buf.WriteString(" # GeoIP 地理访问控制(基于 IP 所属国家/地区)\n") buf.WriteString(" geoip:\n") buf.WriteString(" enabled: false # 是否启用 GeoIP 访问控制\n") buf.WriteString(" database: \"\" # GeoIP 数据库文件路径(如 /usr/share/GeoIP/GeoLite2-Country.mmdb)\n") buf.WriteString(" default: \"allow\" # 未匹配时的默认动作(有效值: allow, deny)\n") buf.WriteString(" private_ip_behavior: \"bypass\" # 私有 IP 处理方式(有效值: bypass, apply_default, deny)\n") buf.WriteString(" allow_countries: [] # 允许的国家代码列表(如 [\"CN\", \"US\"])\n") buf.WriteString(" deny_countries: [] # 拒绝的国家代码列表\n") fmt.Fprintf(&buf, " cache_size: %d # GeoIP 查询缓存大小\n", cfg.Servers[0].Security.Access.GeoIP.CacheSize) fmt.Fprintf(&buf, " cache_ttl: %d # 缓存有效期(秒)\n", int(cfg.Servers[0].Security.Access.GeoIP.CacheTTL.Seconds())) buf.WriteString("\n") buf.WriteString(" # 速率限制\n") buf.WriteString(" rate_limit:\n") fmt.Fprintf(&buf, " request_rate: %d # 每秒请求数(0 表示不限制)\n", cfg.Servers[0].Security.RateLimit.RequestRate) fmt.Fprintf(&buf, " burst: %d # 突发上限\n", cfg.Servers[0].Security.RateLimit.Burst) fmt.Fprintf(&buf, " conn_limit: %d # 连接数限制\n", cfg.Servers[0].Security.RateLimit.ConnLimit) fmt.Fprintf(&buf, " key: \"%s\" # 限流 key 来源(有效值: ip, header)\n", cfg.Servers[0].Security.RateLimit.Key) fmt.Fprintf(&buf, " algorithm: \"%s\" # 限流算法(有效值: token_bucket, sliding_window)\n", cfg.Servers[0].Security.RateLimit.Algorithm) fmt.Fprintf(&buf, " sliding_window_mode: \"%s\" # 滑动窗口模式(有效值: approximate, precise,仅 algorithm=sliding_window 时有效)\n", cfg.Servers[0].Security.RateLimit.SlidingWindowMode) fmt.Fprintf(&buf, " sliding_window: %d # 滑动窗口大小(秒,仅 algorithm=sliding_window 时有效)\n", cfg.Servers[0].Security.RateLimit.SlidingWindow) buf.WriteString("\n") buf.WriteString(" # 认证配置(type 为空时禁用)\n") buf.WriteString(" auth:\n") buf.WriteString(" type: \"\" # 认证类型(有效值: basic,空表示禁用)\n") fmt.Fprintf(&buf, " require_tls: %v # 启用时强制 HTTPS\n", cfg.Servers[0].Security.Auth.RequireTLS) fmt.Fprintf(&buf, " algorithm: \"%s\" # 密码哈希算法(有效值: bcrypt, argon2id)\n", cfg.Servers[0].Security.Auth.Algorithm) buf.WriteString(" users: [] # 用户列表\n") fmt.Fprintf(&buf, " realm: \"%s\" # 认证域\n", cfg.Servers[0].Security.Auth.Realm) fmt.Fprintf(&buf, " min_password_length: %d # 密码最小长度\n", cfg.Servers[0].Security.Auth.MinPasswordLength) buf.WriteString("\n") buf.WriteString(" # 安全头部\n") buf.WriteString(" headers:\n") fmt.Fprintf(&buf, " x_frame_options: \"%s\" # 防止点击劫持(有效值: DENY, SAMEORIGIN, 空表示禁用)\n", cfg.Servers[0].Security.Headers.XFrameOptions) fmt.Fprintf(&buf, " x_content_type_options: \"%s\" # 防止 MIME 嗅探(有效值:nosniff,空表示禁用)\n", cfg.Servers[0].Security.Headers.XContentTypeOptions) fmt.Fprintf(&buf, " referrer_policy: \"%s\" # 引用策略(有效值: no-referrer, no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url)\n", cfg.Servers[0].Security.Headers.ReferrerPolicy) buf.WriteString(" content_security_policy: \"\" # 内容安全策略 CSP(空表示禁用)\n") buf.WriteString(" permissions_policy: \"\" # 权限策略(空表示禁用)\n") buf.WriteString("\n") buf.WriteString(" # 自定义错误页面\n") buf.WriteString(" error_page:\n") buf.WriteString(" pages: {} # 状态码到页面映射,如 {404: \"/errors/404.html\"}\n") buf.WriteString(" default: \"\" # 默认错误页面\n") buf.WriteString(" response_code: 0 # 响应状态码覆盖(0 表示使用原始状态码)\n") buf.WriteString("\n") buf.WriteString(" # 外部认证子请求配置(将认证委托给外部服务)\n") buf.WriteString(" auth_request:\n") buf.WriteString(" enabled: false # 是否启用外部认证\n") buf.WriteString(" uri: \"\" # 认证服务地址(支持相对路径或完整 URL)\n") buf.WriteString(" method: \"GET\" # 认证请求方法(有效值: GET, POST, HEAD)\n") fmt.Fprintf(&buf, " auth_timeout: %ds # 认证请求超时时间\n", int(cfg.Servers[0].Security.AuthRequest.Timeout.Seconds())) buf.WriteString(" headers: {} # 自定义认证请求头,如 {X-Original-Uri: \"$request_uri\"}\n") buf.WriteString(" forward_headers: [] # 需要转发的原请求头,默认包含 Cookie, Authorization, X-Forwarded-For\n") buf.WriteString("\n") // rewrite 配置示例 buf.WriteString(" # URL 重写规则\n") buf.WriteString(" # rewrite:\n") buf.WriteString(" # - pattern: \"^/old/(.*)$\" # 匹配模式(正则表达式)\n") buf.WriteString(" # replacement: /new/$1 # 替换目标\n") buf.WriteString(" # flag: last # 标志(有效值: last, redirect, permanent, break)\n") buf.WriteString("\n") // compression 配置 buf.WriteString(" # 响应压缩配置\n") buf.WriteString(" compression:\n") fmt.Fprintf(&buf, " type: \"%s\" # 压缩类型(有效值: gzip, brotli, both,空表示禁用)\n", cfg.Servers[0].Compression.Type) fmt.Fprintf(&buf, " level: %d # 压缩级别(范围 0-9,0=不压缩,1=最快,9=最高压缩率)\n", cfg.Servers[0].Compression.Level) fmt.Fprintf(&buf, " min_size: %d # 最小压缩大小(字节,小于此值不压缩)\n", cfg.Servers[0].Compression.MinSize) fmt.Fprintf(&buf, " gzip_static: %v # 启用预压缩文件支持(自动查找 .gz/.br 文件)\n", cfg.Servers[0].Compression.GzipStatic) buf.WriteString(" gzip_static_extensions: # 预压缩文件扩展名\n") for _, ext := range cfg.Servers[0].Compression.GzipStaticExtensions { fmt.Fprintf(&buf, " - \"%s\"\n", ext) } buf.WriteString(" types: # 可压缩的 MIME 类型\n") for _, t := range cfg.Servers[0].Compression.Types { fmt.Fprintf(&buf, " - \"%s\"\n", t) } buf.WriteString("\n") // shutdown 配置 buf.WriteString("# 服务器关闭配置\n") buf.WriteString("shutdown:\n") fmt.Fprintf(&buf, " graceful_timeout: %ds # 优雅停止超时(SIGQUIT),等待活跃请求完成(0=使用默认30s)\n", int(cfg.Shutdown.GracefulTimeout.Seconds())) fmt.Fprintf(&buf, " fast_timeout: %ds # 快速停止超时(SIGINT/SIGTERM,0=使用默认5s)\n", int(cfg.Shutdown.FastTimeout.Seconds())) buf.WriteString("\n") // stream 配置 buf.WriteString("# TCP/UDP Stream 代理配置(可选)\n") buf.WriteString("# stream:\n") buf.WriteString("# - listen: \"3306\" # 监听地址\n") buf.WriteString("# protocol: \"tcp\" # 协议类型(有效值: tcp, udp)\n") buf.WriteString("# upstream:\n") buf.WriteString("# targets: # 上游目标列表\n") buf.WriteString("# - addr: \"mysql1:3306\" # 目标地址\n") buf.WriteString("# weight: 3 # 权重(加权轮询时有效)\n") buf.WriteString("# - addr: \"mysql2:3306\"\n") buf.WriteString("# weight: 1\n") buf.WriteString("# load_balance: \"round_robin\" # 负载均衡算法(有效值: round_robin, weighted_round_robin, least_conn, ip_hash, consistent_hash, random)\n") buf.WriteString("# ssl: # 服务端 SSL 配置(仅 TCP 支持)\n") buf.WriteString("# enabled: false # 是否启用 TLS 终端\n") buf.WriteString("# cert: \"/path/to/cert.pem\" # 服务器证书文件\n") buf.WriteString("# key: \"/path/to/key.pem\" # 服务器私钥文件\n") buf.WriteString("# protocols: [\"TLSv1.2\", \"TLSv1.3\"] # TLS 协议版本\n") buf.WriteString("# ciphers: [] # 加密套件(仅 TLS 1.2 有效)\n") buf.WriteString("# client_ca: \"\" # 客户端 CA 证书(mTLS)\n") buf.WriteString("# verify_depth: 1 # 证书链验证深度\n") buf.WriteString("# proxy_ssl: # 上游 SSL 配置(加密到后端的连接)\n") buf.WriteString("# enabled: false # 是否启用上游 TLS\n") buf.WriteString("# verify: false # 是否验证上游证书\n") buf.WriteString("# trusted_ca: \"\" # 信任的 CA 证书\n") buf.WriteString("# server_name: \"\" # SNI 服务器名称\n") buf.WriteString("# cert: \"\" # 客户端证书(mTLS)\n") buf.WriteString("# key: \"\" # 客户端私钥(mTLS)\n") buf.WriteString("# protocols: [] # TLS 协议版本\n") buf.WriteString("# session_reuse: false # 是否复用 SSL 会话\n") buf.WriteString("\n") // logging 配置 buf.WriteString("# 日志配置\n") buf.WriteString("logging:\n") fmt.Fprintf(&buf, " format: \"%s\" # 全局日志格式(有效值: text, json),控制启动/停止日志格式\n", cfg.Logging.Format) buf.WriteString(" access:\n") buf.WriteString(" path: \"\" # 日志文件路径(空表示输出到 stdout)\n") fmt.Fprintf(&buf, " format: '%s' # 访问日志格式,近似 nginx combined\n", cfg.Logging.Access.Format) buf.WriteString(" # 支持变量: $remote_addr, $remote_user, $request, $status, $body_bytes_sent, $request_time, $http_referer, $http_user_agent, $time\n") buf.WriteString(" # 特殊值 \"json\" 输出结构化 JSON\n") buf.WriteString(" error:\n") buf.WriteString(" path: \"\" # 日志文件路径(空表示输出到 stderr)\n") fmt.Fprintf(&buf, " level: \"%s\" # 日志级别(有效值: debug, info, warn, error,级别越高日志越少)\n", cfg.Logging.Error.Level) buf.WriteString("\n") // performance 配置 buf.WriteString("# 性能配置\n") buf.WriteString("performance:\n") buf.WriteString(" goroutine_pool: # Goroutine 池(处理并发请求)\n") fmt.Fprintf(&buf, " enabled: %v # 是否启用\n", cfg.Performance.GoroutinePool.Enabled) fmt.Fprintf(&buf, " max_workers: %d # 最大 worker 数\n", cfg.Performance.GoroutinePool.MaxWorkers) fmt.Fprintf(&buf, " min_workers: %d # 最小 worker 数(预热)\n", cfg.Performance.GoroutinePool.MinWorkers) fmt.Fprintf(&buf, " idle_timeout: %ds # 空闲超时\n", int(cfg.Performance.GoroutinePool.IdleTimeout.Seconds())) buf.WriteString(" file_cache: # 静态文件缓存\n") fmt.Fprintf(&buf, " max_entries: %d # 最大缓存条目\n", cfg.Performance.FileCache.MaxEntries) fmt.Fprintf(&buf, " max_size: %d # 内存上限(字节,%dMB)\n", cfg.Performance.FileCache.MaxSize, cfg.Performance.FileCache.MaxSize/1024/1024) fmt.Fprintf(&buf, " inactive: %ds # 未访问淘汰时间\n", int(cfg.Performance.FileCache.Inactive.Seconds())) buf.WriteString(" transport: # HTTP Transport 连接池\n") fmt.Fprintf(&buf, " idle_conn_timeout: %ds # 空闲超时\n", int(cfg.Performance.Transport.IdleConnTimeout.Seconds())) fmt.Fprintf(&buf, " max_conns_per_host: %d # 每主机最大连接(0 表示不限制)\n", cfg.Performance.Transport.MaxConnsPerHost) buf.WriteString("\n") // HTTP3 配置 buf.WriteString("# HTTP/3 (QUIC) 配置(需要 SSL 证书)\n") buf.WriteString("http3:\n") fmt.Fprintf(&buf, " enabled: %v # 是否启用 HTTP/3\n", cfg.HTTP3.Enabled) fmt.Fprintf(&buf, " listen: \"%s\" # UDP 监听地址\n", cfg.HTTP3.Listen) fmt.Fprintf(&buf, " max_streams: %d # 最大并发流\n", cfg.HTTP3.MaxStreams) fmt.Fprintf(&buf, " idle_timeout: %ds # 空闲超时\n", int(cfg.HTTP3.IdleTimeout.Seconds())) fmt.Fprintf(&buf, " enable_0rtt: %v # 启用 0-RTT(早期数据,可能存在安全风险)\n", cfg.HTTP3.Enable0RTT) buf.WriteString("\n") // monitoring 配置 buf.WriteString("# 监控配置\n") buf.WriteString("monitoring:\n") buf.WriteString(" status:\n") fmt.Fprintf(&buf, " enabled: %v # 是否启用状态端点\n", cfg.Monitoring.Status.Enabled) 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") for _, ip := range cfg.Monitoring.Status.Allow { fmt.Fprintf(&buf, " - \"%s\"\n", ip) } buf.WriteString(" pprof: # pprof 性能分析端点(用于 PGO 优化)\n") fmt.Fprintf(&buf, " enabled: %v # 是否启用(生产环境仅在收集 profile 时启用)\n", cfg.Monitoring.Pprof.Enabled) fmt.Fprintf(&buf, " path: \"%s\" # 端点路径前缀\n", cfg.Monitoring.Pprof.Path) buf.WriteString(" allow: # 允许访问的 IP\n") for _, ip := range cfg.Monitoring.Pprof.Allow { fmt.Fprintf(&buf, " - \"%s\"\n", ip) } buf.WriteString("\n") // resolver 配置 buf.WriteString("# DNS 解析器配置(用于后端域名动态解析)\n") buf.WriteString("resolver:\n") fmt.Fprintf(&buf, " enabled: %v # 是否启用 DNS 解析器\n", cfg.Resolver.Enabled) buf.WriteString(" addresses: # DNS 服务器地址列表\n") buf.WriteString(" - \"8.8.8.8:53\"\n") buf.WriteString(" - \"8.8.4.4:53\"\n") fmt.Fprintf(&buf, " valid: %ds # 缓存有效期(TTL),建议 30s-300s\n", int(cfg.Resolver.Valid.Seconds())) fmt.Fprintf(&buf, " timeout: %ds # DNS 查询超时\n", int(cfg.Resolver.Timeout.Seconds())) fmt.Fprintf(&buf, " ipv4: %v # 是否查询 IPv4 地址\n", cfg.Resolver.IPv4) fmt.Fprintf(&buf, " ipv6: %v # 是否查询 IPv6 地址\n", cfg.Resolver.IPv6) fmt.Fprintf(&buf, " cache_size: %d # 缓存最大条目数(0 表示不限制)\n", cfg.Resolver.CacheSize) buf.WriteString("\n") // variables 配置 buf.WriteString("# 自定义变量配置(全局变量,应用于所有虚拟主机)\n") buf.WriteString("variables:\n") buf.WriteString(" set: {} # 自定义变量集合,如 {app_name: \"lolly\"}\n") buf.WriteString(" # 注意:变量名只允许字母、数字、下划线,不能与内置变量冲突\n") buf.WriteString(" # 不能以 arg_、http_、cookie_ 开头(这些是动态变量前缀)\n") buf.WriteString("\n") // include 配置 buf.WriteString("# 配置文件拆分(include 机制)\n") buf.WriteString("# include:\n") buf.WriteString("# - path: \"conf.d/*.yaml\" # 相对路径 + glob 模式\n") buf.WriteString("# - path: \"sites/example.yaml\" # 单个文件引入\n") buf.WriteString("# 支持循环检测和深度限制(最大 10 层)\n") return buf.Bytes(), nil }