lolly/internal/config/defaults.go
xfy 238fa20e41 docs(config): 在默认配置生成中添加已实现功能的注释示例
新增 client_max_body_size、try_files、next_upstream、error_page 等功能的配置注释

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-08 10:35:45 +08:00

465 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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{
Server: ServerConfig{
Listen: ":8080",
Name: "localhost",
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 120 * time.Second,
MaxConnsPerIP: 1000,
MaxRequestsPerConn: 10000,
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,
},
},
Security: SecurityConfig{
Access: AccessConfig{
Allow: []string{},
Deny: []string{},
Default: "allow",
},
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",
},
Headers: SecurityHeaders{
XFrameOptions: "DENY",
XContentTypeOptions: "nosniff",
ReferrerPolicy: "strict-origin-when-cross-origin",
},
},
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{
MaxIdleConnsPerHost: 32,
IdleConnTimeout: 90 * time.Second,
MaxConnsPerHost: 0, // 0 表示不限制
},
},
Monitoring: MonitoringConfig{
Status: StatusConfig{
Path: "/_status",
Allow: []string{"127.0.0.1"},
},
Pprof: PprofConfig{
Enabled: false,
Path: "/debug/pprof",
Allow: []string{"127.0.0.1"},
},
},
HTTP3: HTTP3Config{
Enabled: false,
Listen: ":443",
MaxStreams: 100,
IdleTimeout: 60 * time.Second,
Enable0RTT: false,
},
}
}
// 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("# 文档: https://github.com/xfy/lolly\n")
buf.WriteString("\n")
// server 配置
buf.WriteString("# 服务器配置(单服务器模式)\n")
buf.WriteString("server:\n")
fmt.Fprintf(&buf, " listen: \"%s\" # 监听地址\n", cfg.Server.Listen)
fmt.Fprintf(&buf, " name: \"%s\" # 服务器名称(虚拟主机匹配)\n", cfg.Server.Name)
fmt.Fprintf(&buf, " read_timeout: %ds # 读取超时0 表示不限制)\n", int(cfg.Server.ReadTimeout.Seconds()))
fmt.Fprintf(&buf, " write_timeout: %ds # 写入超时0 表示不限制)\n", int(cfg.Server.WriteTimeout.Seconds()))
fmt.Fprintf(&buf, " idle_timeout: %ds # 空闲超时0 表示不限制)\n", int(cfg.Server.IdleTimeout.Seconds()))
fmt.Fprintf(&buf, " max_conns_per_ip: %d # 每 IP 最大连接数0 表示不限制)\n", cfg.Server.MaxConnsPerIP)
fmt.Fprintf(&buf, " max_requests_per_conn: %d # 每连接最大请求数0 表示不限制)\n", cfg.Server.MaxRequestsPerConn)
fmt.Fprintf(&buf, " client_max_body_size: \"1MB\" # 请求体大小限制(支持单位: b, kb, mb, gb\n")
buf.WriteString("\n")
// static 配置
buf.WriteString(" # 静态文件服务配置(支持多个目录)\n")
buf.WriteString(" static:\n")
for _, st := range cfg.Server.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(" # 示例:额外的静态目录\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(" # 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(" # load_balance: round_robin # 负载均衡算法(有效值: round_robin, weighted_round_robin, least_conn, ip_hash, consistent_hash\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(" # 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(" # cache: # 代理缓存\n")
buf.WriteString(" # enabled: false\n")
buf.WriteString(" # max_age: 60s\n")
buf.WriteString(" # cache_lock: true # 防止缓存击穿\n")
buf.WriteString(" # stale_while_revalidate: 30s\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("\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.Server.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.Server.SSL.OCSPStapling)
buf.WriteString(" # hsts: # HTTP Strict Transport Security\n")
fmt.Fprintf(&buf, " # max_age: %d # 过期时间(秒)\n", cfg.Server.SSL.HSTS.MaxAge)
fmt.Fprintf(&buf, " # include_sub_domains: %v # 包含子域名\n", cfg.Server.SSL.HSTS.IncludeSubDomains)
fmt.Fprintf(&buf, " # preload: %v # 加入 HSTS 预加载列表\n", cfg.Server.SSL.HSTS.Preload)
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.Server.Security.Access.Default)
buf.WriteString(" trusted_proxies: [] # 可信代理 CIDR 列表,用于 X-Forwarded-For 解析\n")
buf.WriteString("\n")
buf.WriteString(" # 速率限制\n")
buf.WriteString(" rate_limit:\n")
fmt.Fprintf(&buf, " request_rate: %d # 每秒请求数0 表示不限制)\n", cfg.Server.Security.RateLimit.RequestRate)
fmt.Fprintf(&buf, " burst: %d # 突发上限\n", cfg.Server.Security.RateLimit.Burst)
fmt.Fprintf(&buf, " conn_limit: %d # 连接数限制\n", cfg.Server.Security.RateLimit.ConnLimit)
fmt.Fprintf(&buf, " key: \"%s\" # 限流 key 来源(有效值: ip, header\n", cfg.Server.Security.RateLimit.Key)
fmt.Fprintf(&buf, " algorithm: \"%s\" # 限流算法(有效值: token_bucket, sliding_window\n", cfg.Server.Security.RateLimit.Algorithm)
fmt.Fprintf(&buf, " sliding_window_mode: \"%s\" # 滑动窗口模式(有效值: approximate, precise仅 algorithm=sliding_window 时有效)\n", cfg.Server.Security.RateLimit.SlidingWindowMode)
fmt.Fprintf(&buf, " sliding_window: %d # 滑动窗口大小(秒,仅 algorithm=sliding_window 时有效)\n", cfg.Server.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.Server.Security.Auth.RequireTLS)
fmt.Fprintf(&buf, " algorithm: \"%s\" # 密码哈希算法(有效值: bcrypt, argon2id\n", cfg.Server.Security.Auth.Algorithm)
buf.WriteString(" users: [] # 用户列表\n")
fmt.Fprintf(&buf, " realm: \"%s\" # 认证域\n", cfg.Server.Security.Auth.Realm)
buf.WriteString("\n")
buf.WriteString(" # 安全头部\n")
buf.WriteString(" headers:\n")
fmt.Fprintf(&buf, " x_frame_options: \"%s\" # 防止点击劫持(有效值: DENY, SAMEORIGIN, 空表示禁用)\n", cfg.Server.Security.Headers.XFrameOptions)
fmt.Fprintf(&buf, " x_content_type_options: \"%s\" # 防止 MIME 嗅探有效值nosniff空表示禁用\n", cfg.Server.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.Server.Security.Headers.ReferrerPolicy)
buf.WriteString(" # content_security_policy: \"default-src 'self'\" # 内容安全策略 CSP\n")
buf.WriteString(" # permissions_policy: \"geolocation=(), microphone=()\" # 权限策略\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")
// 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.Server.Compression.Type)
fmt.Fprintf(&buf, " level: %d # 压缩级别(范围 0-90=不压缩1=最快9=最高压缩率)\n", cfg.Server.Compression.Level)
fmt.Fprintf(&buf, " min_size: %d # 最小压缩大小(字节,小于此值不压缩)\n", cfg.Server.Compression.MinSize)
fmt.Fprintf(&buf, " gzip_static: %v # 启用预压缩文件支持(自动查找 .gz/.br 文件)\n", cfg.Server.Compression.GzipStatic)
buf.WriteString(" gzip_static_extensions: # 预压缩文件扩展名\n")
for _, ext := range cfg.Server.Compression.GzipStaticExtensions {
fmt.Fprintf(&buf, " - \"%s\"\n", ext)
}
buf.WriteString(" types: # 可压缩的 MIME 类型\n")
for _, t := range cfg.Server.Compression.Types {
fmt.Fprintf(&buf, " - \"%s\"\n", t)
}
buf.WriteString("\n")
// servers 配置说明 - 完整示例
buf.WriteString("# 多虚拟主机模式(可选,每个虚拟主机支持完整的 server 配置)\n")
buf.WriteString("# servers:\n")
buf.WriteString("# - listen: \":8080\" # 监听地址\n")
buf.WriteString("# name: \"api.example.com\" # 服务器名称(用于虚拟主机匹配)\n")
buf.WriteString("# read_timeout: 30s # 读取超时0 表示不限制)\n")
buf.WriteString("# write_timeout: 30s # 写入超时0 表示不限制)\n")
buf.WriteString("# idle_timeout: 120s # 空闲超时0 表示不限制)\n")
buf.WriteString("# max_conns_per_ip: 1000 # 每 IP 最大连接数0 表示不限制)\n")
buf.WriteString("# max_requests_per_conn: 10000 # 每连接最大请求数0 表示不限制)\n")
buf.WriteString("# static: # 静态文件配置(支持多个目录)\n")
buf.WriteString("# - path: /\n")
buf.WriteString("# root: /var/www/api\n")
buf.WriteString("# index: [index.html]\n")
buf.WriteString("# proxy: # 反向代理配置\n")
buf.WriteString("# - path: /api\n")
buf.WriteString("# targets:\n")
buf.WriteString("# - url: http://backend:8080\n")
buf.WriteString("# load_balance: round_robin\n")
buf.WriteString("# ssl: # SSL/TLS 配置\n")
buf.WriteString("# cert: /path/to/api.cert.pem\n")
buf.WriteString("# key: /path/to/api.key.pem\n")
buf.WriteString("# protocols: [TLSv1.2, TLSv1.3]\n")
buf.WriteString("# hsts:\n")
buf.WriteString("# max_age: 31536000\n")
buf.WriteString("# include_sub_domains: true\n")
buf.WriteString("# security: # 安全配置\n")
buf.WriteString("# access:\n")
buf.WriteString("# default: allow\n")
buf.WriteString("# rate_limit:\n")
buf.WriteString("# request_rate: 100\n")
buf.WriteString("# headers:\n")
buf.WriteString("# x_frame_options: DENY\n")
buf.WriteString("# compression: # 响应压缩配置\n")
buf.WriteString("# type: gzip\n")
buf.WriteString("# level: 6\n")
buf.WriteString("# - listen: \":8443\" # 另一个虚拟主机\n")
buf.WriteString("# name: \"static.example.com\"\n")
buf.WriteString("# static:\n")
buf.WriteString("# - path: /\n")
buf.WriteString("# root: /var/www/static\n")
buf.WriteString("# index: [index.html, index.htm]\n")
buf.WriteString("# ssl:\n")
buf.WriteString("# cert: /path/to/static.cert.pem\n")
buf.WriteString("# key: /path/to/static.key.pem\n")
buf.WriteString("# compression:\n")
buf.WriteString("# type: gzip\n")
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=315360001年, include_sub_domains=true\n")
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\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, " max_idle_conns_per_host: %d # 每主机空闲连接\n", cfg.Performance.Transport.MaxIdleConnsPerHost)
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, " path: \"%s\" # 状态端点路径\n", cfg.Monitoring.Status.Path)
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)
}
return buf.Bytes(), nil
}