- 集成一致性哈希负载均衡到 proxy.go,支持 hash_key 和 virtual_nodes 配置 - 集成滑动窗口限流算法到 ratelimit.go,支持 algorithm 选择 - 应用 Transport 连接池配置到 createHostClient - 集成 HSTS 配置到安全头部中间件 - 补充 config.example.yaml 缺失配置(http3、gzip_static、sliding_window) Co-Authored-By: Claude <noreply@anthropic.com>
118 lines
2.9 KiB
Go
118 lines
2.9 KiB
Go
// Package server 提供 HTTP 服务器的核心实现,支持单服务器和虚拟主机两种运行模式。
|
||
//
|
||
// 该文件包含虚拟主机管理相关的核心逻辑,包括:
|
||
// - 虚拟主机管理器的创建和配置
|
||
// - 基于 Host 头的请求分发
|
||
// - 默认主机 fallback 机制
|
||
//
|
||
// 主要用途:
|
||
//
|
||
// 用于支持多域名虚拟主机场景,根据请求的 Host 头分发到不同的处理器。
|
||
//
|
||
// 注意事项:
|
||
// - 所有方法均为并发安全
|
||
// - 未匹配的 Host 头请求由默认主机处理
|
||
//
|
||
// 作者:xfy
|
||
package server
|
||
|
||
import (
|
||
"github.com/valyala/fasthttp"
|
||
)
|
||
|
||
// VHostManager 虚拟主机管理器。
|
||
//
|
||
// 管理多个虚拟主机,根据请求的 Host 头分发到对应的处理器。
|
||
// 支持默认主机作为未匹配请求的 fallback。
|
||
type VHostManager struct {
|
||
// hosts 虚拟主机映射,按 server name 索引
|
||
hosts map[string]*VirtualHost
|
||
|
||
// defaultHost 默认主机,处理未匹配的 Host 头请求
|
||
defaultHost *VirtualHost
|
||
}
|
||
|
||
// VirtualHost 虚拟主机。
|
||
//
|
||
// 代表一个虚拟主机配置,包含名称和对应的请求处理器。
|
||
type VirtualHost struct {
|
||
// name 虚拟主机名称(域名)
|
||
name string
|
||
|
||
// handler 请求处理器
|
||
handler fasthttp.RequestHandler
|
||
}
|
||
|
||
// NewVHostManager 创建虚拟主机管理器
|
||
func NewVHostManager() *VHostManager {
|
||
return &VHostManager{
|
||
hosts: make(map[string]*VirtualHost),
|
||
}
|
||
}
|
||
|
||
// AddHost 添加虚拟主机
|
||
func (v *VHostManager) AddHost(name string, handler fasthttp.RequestHandler) {
|
||
v.hosts[name] = &VirtualHost{
|
||
name: name,
|
||
handler: handler,
|
||
}
|
||
}
|
||
|
||
// SetDefault 设置默认主机
|
||
func (v *VHostManager) SetDefault(handler fasthttp.RequestHandler) {
|
||
v.defaultHost = &VirtualHost{
|
||
name: "default",
|
||
handler: handler,
|
||
}
|
||
}
|
||
|
||
// Handler 返回虚拟主机选择器
|
||
func (v *VHostManager) Handler() fasthttp.RequestHandler {
|
||
return func(ctx *fasthttp.RequestCtx) {
|
||
host := stripPort(string(ctx.Host()))
|
||
|
||
if vhost, ok := v.hosts[host]; ok {
|
||
vhost.handler(ctx)
|
||
} else if v.defaultHost != nil {
|
||
v.defaultHost.handler(ctx)
|
||
} else {
|
||
ctx.Error("Host not found", fasthttp.StatusNotFound)
|
||
}
|
||
}
|
||
}
|
||
|
||
// stripPort 从 Host 头中移除端口号。
|
||
//
|
||
// 支持 IPv4 和 IPv6 格式:
|
||
// - example.com:8080 -> example.com
|
||
// - [::1]:8080 -> [::1]
|
||
// - [2001:db8::1]:443 -> [2001:db8::1]
|
||
// - example.com -> example.com
|
||
func stripPort(host string) string {
|
||
// 空字符串直接返回
|
||
if len(host) == 0 {
|
||
return host
|
||
}
|
||
|
||
// IPv6 格式:以 '[' 开头,找 ']:' 作为分隔点
|
||
if host[0] == '[' {
|
||
// 查找 ']:' 分隔符
|
||
for i := 0; i < len(host)-1; i++ {
|
||
if host[i] == ']' && host[i+1] == ':' {
|
||
return host[:i+1] // 返回包含 ']' 的部分,如 "[::1]"
|
||
}
|
||
}
|
||
// 没有 ']:' 分隔符,可能是纯 IPv6 地址(如 "[::1]")
|
||
return host
|
||
}
|
||
|
||
// IPv4 或域名格式:找第一个 ':' 作为分隔点
|
||
for i := 0; i < len(host); i++ {
|
||
if host[i] == ':' {
|
||
return host[:i]
|
||
}
|
||
}
|
||
|
||
return host
|
||
}
|