lolly/internal/config/proxy_config.go
xfy911 65aaba4e59 docs(config): add package comments for config module
- Add package documentation for cache, monitoring, performance, proxy,
  security, server, ssl, and variable config files
- Include author attribution (xfy)
2026-06-03 15:28:53 +08:00

461 lines
14 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 配置文件的解析、验证和默认配置生成功能。
//
// 包含代理配置相关的结构体,用于配置反向代理行为。
//
// 作者xfy
package config
import (
"strconv"
"strings"
"time"
)
// ProxyConfig 反向代理配置,支持负载均衡和健康检查。
//
// 用于将请求转发到后端服务器,支持多种负载均衡算法
// 和健康检查机制。
//
// 注意事项:
// - Path 使用前缀匹配,较长路径优先匹配
// - 至少配置一个 Target 才能正常工作
// - 负载均衡算法支持round_robin、weighted_round_robin、least_conn、ip_hash、consistent_hash、random
// - 一致性哈希需要配置 HashKey
//
// 使用示例:
//
// proxy:
// - path: "/api/"
// targets:
// - url: "http://backend1:8080"
// weight: 3
// - url: "http://backend2:8080"
// weight: 1
// load_balance: "weighted_round_robin"
// health_check:
// interval: 10s
// path: "/health"
type ProxyConfig struct {
// 指针类型字段(按大小排列)
RedirectRewrite *RedirectRewriteConfig `yaml:"redirect_rewrite"`
ProxySSL *ProxySSLConfig `yaml:"proxy_ssl"`
CacheValid *ProxyCacheValidConfig `yaml:"cache_valid"`
Buffering *ProxyBufferingConfig `yaml:"buffering"`
// 切片字段
Targets []ProxyTarget `yaml:"targets"`
// 字符串字段
Path string `yaml:"path"`
LoadBalance string `yaml:"load_balance"`
HashKey string `yaml:"hash_key"`
ClientMaxBodySize string `yaml:"client_max_body_size"`
ProxyBind string `yaml:"proxy_bind"`
// 结构体字段
Headers ProxyHeaders `yaml:"headers"`
BalancerByLua BalancerByLuaConfig `yaml:"balancer_by_lua"`
HealthCheck HealthCheckConfig `yaml:"health_check"`
NextUpstream NextUpstreamConfig `yaml:"next_upstream"`
Cache ProxyCacheConfig `yaml:"cache"`
Timeout ProxyTimeout `yaml:"timeout"`
// 基本类型字段
VirtualNodes int `yaml:"virtual_nodes"`
// LocationType 位置匹配类型
// 可选值exact、prefix_priority、regex、regex_caseless、prefix、named
LocationType string `yaml:"location_type"`
// LocationName 位置名称
// 仅当 LocationType 为 named 时使用,用于命名位置块
LocationName string `yaml:"location_name"`
// Internal 仅允许内部访问
// 设置为 true 时,该位置仅允许内部重定向访问
Internal bool `yaml:"internal"`
}
// ProxyBufferingConfig 代理缓冲配置。
//
// 控制代理响应的缓冲行为:
// - "default" 或 "on": 缓冲响应到内存/临时文件
// - "off": 流式转发响应,不缓冲
//
// 使用示例:
//
// buffering:
// mode: "off"
type ProxyBufferingConfig struct {
// Mode 缓冲模式
// 可选值:"default"(默认缓冲), "on"(强制缓冲), "off"(关闭缓冲)
Mode string `yaml:"mode"`
// BufferSize 响应缓冲区大小(字节)
// 0 表示使用默认值
BufferSize int `yaml:"buffer_size"`
// Buffers 多缓冲区配置字符串
// 格式:"数量 大小" 或 "数量1 大小1 数量2 大小2 ..."
// 例如:"8 16k" 表示 8 个 16KB 缓冲区
// 例如:"4 4k 8 16k" 表示 4 个 4KB + 8 个 16KB 缓冲区
Buffers string `yaml:"buffers"`
// BufferCount 缓冲区数量(解析后)
BufferCount int `yaml:"-"`
// BufferSizeEach 每个缓冲区大小(字节,解析后)
BufferSizeEach int `yaml:"-"`
}
// ParseBuffers 解析 Buffers 配置字符串。
//
// 支持格式:
// - "8 16k" → 8 个 16KB 缓冲区
// - "4 4k" → 4 个 4KB 缓冲区
//
// 大小单位:
// - k 或 K: KB (1024 字节)
// - m 或 M: MB (1024 * 1024 字节)
// - 无单位: 字节
func (c *ProxyBufferingConfig) ParseBuffers() {
if c.Buffers == "" {
// 向后兼容:使用 BufferSize
if c.BufferSize > 0 {
c.BufferCount = 1
c.BufferSizeEach = c.BufferSize
}
return
}
parts := strings.Fields(c.Buffers)
if len(parts) < 2 {
return // 无效格式
}
count, err := strconv.Atoi(parts[0])
if err != nil || count <= 0 {
return // 无效数量
}
sizeEach, err := parseSize(parts[1])
if err != nil || sizeEach <= 0 {
return // 无效大小
}
c.BufferCount = count
c.BufferSizeEach = sizeEach
}
// BalancerByLuaConfig Lua 负载均衡配置
//
// 使用 Lua 脚本动态选择后端目标,支持自定义负载均衡逻辑。
//
// 注意事项:
// - Script 为 Lua 脚本文件路径
// - Timeout 控制脚本执行超时
// - Fallback 指定 Lua 失败时的备用算法
//
// 使用示例:
//
// balancer_by_lua:
// enabled: true
// script: "/etc/lolly/scripts/balancer.lua"
// timeout: 100ms
// fallback: "round_robin"
type BalancerByLuaConfig struct {
// Script Lua 脚本路径
Script string `yaml:"script"`
// Fallback 失败时使用的默认负载均衡算法
// 默认值: "round_robin"
Fallback string `yaml:"fallback"`
// Timeout 执行超时
// 默认值: 100ms
Timeout time.Duration `yaml:"timeout"`
// Enabled 是否启用
Enabled bool `yaml:"enabled"`
}
// ProxyTarget 后端目标配置。
//
// 定义单个后端服务器的地址和权重。
//
// 注意事项:
// - URL 必须包含协议http:// 或 https://
// - Weight 仅在 weighted_round_robin 算法下生效
//
// 使用示例:
//
// targets:
// - url: "http://backend1:8080"
// weight: 3
// - url: "http://backend2:8080"
// weight: 1
type ProxyTarget struct {
// URL 后端地址
// 格式:"http://host:port" 或 "https://host:port"
URL string `yaml:"url"`
// Weight 权重
// 用于加权轮询算法,值越大分配的请求越多
Weight int `yaml:"weight"`
// MaxConns 最大并发连接数
// 0 表示不限制
MaxConns int `yaml:"max_conns"`
// MaxFails 最大失败次数
// 在 FailTimeout 期间失败次数达到此值后标记为不可用
// 0 表示不进行被动失败检测
MaxFails int `yaml:"max_fails"`
// FailTimeout 失败超时时间
// 达到 MaxFails 后,目标在此时间内被视为不可用
FailTimeout time.Duration `yaml:"fail_timeout"`
// Backup 备份服务器
// 仅当所有非备份服务器不可用时才使用
Backup bool `yaml:"backup"`
// Down 标记服务器为永久不可用
Down bool `yaml:"down"`
// ProxyURI 代理传递的 URI 路径
// 设置后替换请求路径,支持 nginx proxy_pass URI 语义
ProxyURI string `yaml:"proxy_uri"`
}
// HealthCheckConfig 健康检查配置。
//
// 定期检查后端服务器的健康状态,自动剔除不健康的节点。
//
// 注意事项:
// - Interval 不宜设置过小,避免增加后端负担
// - Path 应该是轻量级的健康检查端点
// - 超时时间应小于检查间隔
//
// 使用示例:
//
// health_check:
// interval: 10s
// path: "/health"
// timeout: 5s
type HealthCheckConfig struct {
Path string `yaml:"path"`
Interval time.Duration `yaml:"interval"`
Timeout time.Duration `yaml:"timeout"`
Match *HealthMatchConfig `yaml:"match"` // 健康检查匹配配置
SlowStart time.Duration `yaml:"slow_start"` // 慢启动时间
}
// HealthMatchConfig 健康检查匹配配置。
type HealthMatchConfig struct {
Status []string `yaml:"status"` // 状态码范围列表
Body string `yaml:"body"` // 响应体正则表达式
Headers map[string]string `yaml:"headers"` // 响应头匹配
}
// ProxyTimeout 代理超时配置。
//
// 控制代理请求的各个阶段超时。
//
// 注意事项:
// - Connect 超时包括 DNS 解析和 TCP 连接建立
// - Read 和 Write 超时分别控制响应读取和请求发送
// - 超时时间需要根据后端服务响应时间调整
//
// 使用示例:
//
// timeout:
// dial: 5s # TCP 连接建立超时
// connect: 30s # 总连接超时(含 DNS/TLS
// read: 30s
// write: 30s
type ProxyTimeout struct {
// Dial TCP 连接建立超时
// 建立 TCP 连接的超时时间(不含 DNS 和 TLS
Dial time.Duration `yaml:"dial"`
// Connect 总连接超时
// 从开始连接到连接可用的总超时时间(含 DNS 和 TLS
Connect time.Duration `yaml:"connect"`
// Read 读取超时
// 从后端读取响应的超时
Read time.Duration `yaml:"read"`
// Write 写入超时
// 向后端发送请求的超时
Write time.Duration `yaml:"write"`
}
// ProxyHeaders 代理请求/响应头配置。
//
// 在代理转发过程中修改 HTTP 头部。
//
// 注意事项:
// - SetRequest 添加/修改发送到后端的请求头
// - SetResponse 添加/修改返回给客户端的响应头
// - Remove 会删除指定的请求头(在发送到后端之前)
//
// 使用示例:
//
// headers:
// set_request:
// X-Forwarded-For: "$remote_addr"
// X-Real-IP: "$remote_addr"
// set_response:
// X-Proxy-By: "lolly"
// remove:
// - "X-Internal-Header"
type ProxyHeaders struct {
// SetRequest 设置请求头
// 发送到后端的请求中添加或覆盖的头部
SetRequest map[string]string `yaml:"set_request"`
// SetResponse 设置响应头
// 返回给客户端的响应中添加或覆盖的头部
SetResponse map[string]string `yaml:"set_response"`
// Remove 移除的头部
// 从发送到后端的请求中移除的头部列表
Remove []string `yaml:"remove"`
// HideResponse 隐藏的响应头
// 从返回给客户端的响应中移除的头部列表
HideResponse []string `yaml:"hide_response"`
// PassResponse 允许传递的响应头
// 仅传递列出的头部,其他全部隐藏(白名单模式)
PassResponse []string `yaml:"pass_response"`
// IgnoreHeaders 忽略的头部
// 代理时完全忽略这些头部,不转发到后端也不返回给客户端
IgnoreHeaders []string `yaml:"ignore_headers"`
// CookieDomain Cookie 域重写
// 将响应中 Set-Cookie 的 domain 替换为此值
CookieDomain string `yaml:"cookie_domain"`
// CookiePath Cookie 路径重写
// 将响应中 Set-Cookie 的 path 替换为此值
CookiePath string `yaml:"cookie_path"`
// SetForwardedHost 控制 X-Forwarded-Host 头的设置
// nil (默认): 设置 X-Forwarded-Host向后兼容
// true: 显式设置 X-Forwarded-Host
// false: 不设置 X-Forwarded-Host
SetForwardedHost *bool `yaml:"set_forwarded_host"`
// SetForwardedProto 控制 X-Forwarded-Proto 头的设置
// nil (默认): 设置 X-Forwarded-Proto向后兼容
// true: 显式设置 X-Forwarded-Proto
// false: 不设置 X-Forwarded-Proto
SetForwardedProto *bool `yaml:"set_forwarded_proto"`
}
// ProxySSLConfig 上游 SSL/TLS 配置。
//
// 配置代理连接上游服务器时的 TLS 行为,支持自定义 CA、客户端证书mTLS
// SNI 和 TLS 版本控制。
//
// 注意事项:
// - Enabled 为 true 时启用自定义 TLS 配置
// - TrustedCA 用于验证上游服务器证书
// - ClientCert + ClientKey 用于 mTLS 客户端认证
// - InsecureSkipVerify 仅用于测试,生产环境禁用
//
// 使用示例:
//
// proxy_ssl:
// enabled: true
// server_name: "api.internal"
// trusted_ca: "/etc/ssl/ca/upstream-ca.crt"
// client_cert: "/etc/ssl/client.crt"
// client_key: "/etc/ssl/client.key"
// min_version: "TLSv1.2"
type ProxySSLConfig struct {
// 字符串字段
ServerName string `yaml:"server_name"`
TrustedCA string `yaml:"trusted_ca"`
ClientCert string `yaml:"client_cert"`
ClientKey string `yaml:"client_key"`
MinVersion string `yaml:"min_version"`
MaxVersion string `yaml:"max_version"`
// 布尔字段
Enabled bool `yaml:"enabled"`
InsecureSkipVerify bool `yaml:"insecure_skip_verify"`
}
// RedirectRewriteConfig Location/Refresh 头改写配置
//
// 用于配置代理响应中 Location 和 Refresh 头的改写行为。
//
// 注意事项:
// - Mode 支持 "default"、"off"、"custom" 三种模式
// - 未配置或空字符串时默认为 "default" 模式
// - "custom" 模式必须配置至少一条规则
//
// 使用示例:
//
// redirect_rewrite:
// mode: "default" # 或 "off" 或 "custom"
// rules:
// - pattern: "http://backend:8000/"
// replacement: "$scheme://$host:$server_port/"
type RedirectRewriteConfig struct {
// Mode 运行模式: "default" | "off" | "custom"
// default: 自动从选中的 target URL 生成规则(运行时)
// off: 禁用改写
// custom: 使用 Rules 列表(预编译)
// 未配置或空字符串时默认为 "default"
Mode string `yaml:"mode"`
// Rules 改写规则列表,仅在 Mode="custom" 时使用
Rules []RedirectRewriteRule `yaml:"rules"`
}
// RedirectRewriteRule 单条改写规则
//
// 定义 Location/Refresh 头改写的匹配模式和替换目标。
//
// 注意事项:
// - Pattern 以 ~ 开头表示正则,~* 表示大小写不敏感
// - 无 ~ 前缀时使用前缀匹配语义
// - Replacement 支持变量展开($host, $scheme, $server_port 等)
//
// 使用示例:
//
// rules:
// - pattern: "http://backend:8000/"
// replacement: "$scheme://$host:$server_port/"
// - pattern: "~^http://[^/]+:8000/(.*)$"
// replacement: "$scheme://$host/$1"
type RedirectRewriteRule struct {
// Pattern 匹配模式,支持正则(以 ~ 开头)或精确匹配
// 示例: "http://localhost:8000/" 或 "~^http://[^/]+:8000/"
Pattern string `yaml:"pattern"`
// Replacement 替换目标,支持变量展开
// 示例: "$scheme://$host:$server_port/" 或 "/"
Replacement string `yaml:"replacement"`
}
// NextUpstreamConfig 故障转移配置,定义后端失败时的自动重试行为。
//
// 当后端返回特定错误状态码或连接失败时,自动尝试下一个可用后端。
//
// 注意事项:
// - Tries 为 1 时禁用故障转移
// - 空 NextUpstream 使用默认值Tries=1禁用故障转移
// - 建议根据后端数量合理设置 Tries 值
//
// 使用示例:
//
// next_upstream:
// tries: 3
// http_codes: [502, 503, 504]
type NextUpstreamConfig struct {
HTTPCodes []int `yaml:"http_codes"`
Tries int `yaml:"tries"`
}