- logging: 补充包文档说明 - pool: 修复 workers 计数器并发安全 (atomic 操作) - stream: 完善注释与错误处理 - handler/static: 添加预压缩文件支持接口 - loadbalance: 补充算法注释 - vhost: 改进虚拟主机路由逻辑 - ssl: 优化证书加载注释 - main: 补充启动流程注释 Co-Authored-By: Claude <noreply@anthropic.com>
131 lines
3.3 KiB
Go
131 lines
3.3 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 创建虚拟主机管理器。
|
||
//
|
||
// 返回值:
|
||
// - *VHostManager: 新创建的管理器实例
|
||
func NewVHostManager() *VHostManager {
|
||
return &VHostManager{
|
||
hosts: make(map[string]*VirtualHost),
|
||
}
|
||
}
|
||
|
||
// AddHost 添加虚拟主机。
|
||
//
|
||
// 参数:
|
||
// - name: 虚拟主机名称(域名)
|
||
// - handler: 请求处理器
|
||
func (v *VHostManager) AddHost(name string, handler fasthttp.RequestHandler) {
|
||
v.hosts[name] = &VirtualHost{
|
||
name: name,
|
||
handler: handler,
|
||
}
|
||
}
|
||
|
||
// SetDefault 设置默认主机。
|
||
//
|
||
// 参数:
|
||
// - handler: 默认主机的请求处理器
|
||
func (v *VHostManager) SetDefault(handler fasthttp.RequestHandler) {
|
||
v.defaultHost = &VirtualHost{
|
||
name: "default",
|
||
handler: handler,
|
||
}
|
||
}
|
||
|
||
// Handler 返回虚拟主机选择器。
|
||
//
|
||
// 返回值:
|
||
// - fasthttp.RequestHandler: 根据 Host 头分发请求的处理器
|
||
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
|
||
}
|