package service import ( "path/filepath" "regexp" "strings" ) // CertSet SSL 证书配置 type CertSet struct { CertFile string KeyFile string } // CallConfig 下游服务调用配置 type CallConfig struct { Timeout int // 超时时间 (ms) Token string // 访问凭证 Http2 bool // 是否强制使用 HTTP/2 (H2C) SSL bool // 是否使用 HTTPS/WSS } // ServiceConfig 核心服务配置 type ServiceConfig struct { App string // 应用名称。优先从环境变量 DISCOVER_APP 获取,若为空则自动通过代码检测。 Register string // 发现服务注册中心地址。支持 Redis URL 或 Redis 配置名称。 Weight int // 当前节点在发现服务中的权重 (默认 100) Calls map[string]CallConfig // 依赖的下游服务调用配置 Listen string // 监听端口(|隔开多个监听)(,隔开多个选项),例如 80,http|443|443:h2|127.0.0.1:8080,h2c SSL map[string]*CertSet // SSL 证书配置,key 为域名 NoLogGets bool // 不记录 GET 请求的日志 NoLogHeaders string // 不记录请求头中包含的这些字段,多个字段用逗号分隔 LogInputArrayNum int // 请求字段中容器类型在日志打印个数限制 LogInputFieldSize int // 请求字段中单个字段在日志打印长度限制 NoLogOutputFields string // 不记录响应字段中包含的这些字段 LogOutputArrayNum int // 响应字段中容器类型在日志打印个数限制 LogOutputFieldSize int // 响应字段中单个字段在日志打印长度限制 Compress bool // 是否启用压缩 CompressMinSize int // 启用压缩的最小长度 CompressMaxSize int // 启用压缩的最大长度 CheckDomain string // 心跳检测时使用域名 AccessTokens map[string]*int // 指定 Access-Token 验证及其对应的 auth-level RedirectTimeout int // Proxy 和 Discover 发起请求时的超时时间 (ms) AcceptXRealIpWithoutRequestId bool // 是否允许头部没有携带请求ID的 X-Real-IP 信息 StatisticTime bool // 是否开启请求时间统计 StatisticTimeInterval int // 统计时间间隔 (ms) MaxUploadSize int64 // 最大上传文件大小 (Bytes) Cpu int // CPU 占用的核数限制 Memory int // 内存限制 (MB) CookieScope string // Session Cookie 有效范围: host|domain|topDomain SessionWithoutCookie bool // Session 禁用 Cookie DeviceWithoutCookie bool // 设备ID禁用 Cookie IdServer string // Redis 服务器连接 (用于全局唯一 ID 生成) IndexFiles []string // 静态文件索引文件 IndexDir bool // 访问目录时显示文件列表 ReadTimeout int // 读取请求的超时时间 (ms) ReadHeaderTimeout int // 读取请求头的超时时间 (ms) WriteTimeout int // 响应写入的超时时间 (ms) IdleTimeout int // 连接空闲超时时间 (ms) MaxHeaderBytes int // 请求头的最大字节数 MaxHandlers int // 每个连接的最大处理程序数量 MaxConcurrentStreams uint32 // 每个连接的最大并发流数量 MaxDecoderHeaderTableSize uint32 // 解码器头表的最大大小 MaxEncoderHeaderTableSize uint32 // 编码器头表的最大大小 MaxReadFrameSize uint32 // 单个帧的最大读取大小 MaxUploadBufferPerConnection int32 // 每个连接的最大上传缓冲区大小 MaxUploadBufferPerStream int32 // 每个流的最大上传缓冲区大小 StopTimeout int // 停止服务的超时时间 (ms) // 从配置文件中加载的静态路由策略 (按 Host 分组,全局配置用 "" 或 "*") Proxies map[string][]ProxyRule Rewrites map[string][]RewriteRule Statics map[string]map[string]string } var Config = ServiceConfig{} // ApplyConfig 将 ServiceConfig 中的路由策略应用到内部的文件级策略中 func ApplyConfig() { hostPoliciesLock.Lock() defer hostPoliciesLock.Unlock() // 清理旧的 file 策略 fileProxies = make(map[string][]*proxyType) fileRewrites = make(map[string][]*rewriteType) for host, rules := range Config.Proxies { if host == "*" { host = "" } newProxies := make([]*proxyType, 0, len(rules)) for _, r := range rules { p := &proxyType{authLevel: r.AuthLevel, fromPath: r.Path, toApp: r.ToApp, toPath: r.ToPath} if strings.ContainsRune(r.Path, '(') { matcher, err := regexp.Compile("^" + r.Path + "$") if err == nil { p.matcher = matcher } } newProxies = append(newProxies, p) } fileProxies[host] = newProxies rebuildProxiesUnderLock(host) } for host, rules := range Config.Rewrites { if host == "*" { host = "" } newRewrites := make([]*rewriteType, 0, len(rules)) for _, r := range rules { s := &rewriteType{fromPath: r.Path, toPath: r.ToPath} if strings.ContainsRune(r.Path, '(') { matcher, err := regexp.Compile("^" + r.Path + "$") if err == nil { s.matcher = matcher } } newRewrites = append(newRewrites, s) } fileRewrites[host] = newRewrites rebuildRewritesUnderLock(host) } staticsByHostLock.Lock() defer staticsByHostLock.Unlock() fileStatics = make(map[string]map[string]*string) for host, config := range Config.Statics { if host == "*" { host = "" } newStatics := make(map[string]*string, len(config)) for path, rootPath := range config { rp := rootPath if !filepath.IsAbs(rp) { if absPath, err := filepath.Abs(rp); err == nil { rp = absPath } } newStatics[path] = &rp } fileStatics[host] = newStatics rebuildStaticsUnderLock(host) } }