refactor(variable): 重命名核心类型移除冗余前缀
VariableContext → Context VariableStore → Store ReleaseVariableContext → ReleaseContext (别名保留向后兼容) 提取硬编码字符串为命名常量 sslProtocolNone Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7a2b1d7e03
commit
0731dc46e4
@ -1,6 +1,7 @@
|
||||
// builtin.go - 内置变量定义
|
||||
// Package variable 提供 nginx 风格的内置变量支持,用于日志、代理和重写规则。
|
||||
//
|
||||
// 提供 18 个 nginx 风格的内置变量,用于日志、代理和重写规则。
|
||||
// 包含 18 个内置变量常量、动态变量获取函数($arg_name、$http_name、$cookie_name)
|
||||
// 以及 Context 池管理。
|
||||
//
|
||||
// 作者:xfy
|
||||
package variable
|
||||
@ -132,7 +133,7 @@ func init() {
|
||||
})
|
||||
|
||||
// 9. $server_name - 服务器名称
|
||||
// 注意:这个变量需要从 VariableContext 获取
|
||||
// 注意:这个变量需要从 Context 获取
|
||||
RegisterBuiltin(&BuiltinVariable{
|
||||
Name: VarServerName,
|
||||
Description: "服务器名称",
|
||||
@ -167,7 +168,7 @@ func init() {
|
||||
})
|
||||
|
||||
// 11. $status - HTTP 状态码
|
||||
// 需要从 VariableContext 获取
|
||||
// 需要从 Context 获取
|
||||
RegisterBuiltin(&BuiltinVariable{
|
||||
Name: VarStatus,
|
||||
Description: "HTTP 响应状态码",
|
||||
@ -182,7 +183,7 @@ func init() {
|
||||
})
|
||||
|
||||
// 12. $body_bytes_sent - 响应体大小
|
||||
// 需要从 VariableContext 获取
|
||||
// 需要从 Context 获取
|
||||
RegisterBuiltin(&BuiltinVariable{
|
||||
Name: VarBodyBytesSent,
|
||||
Description: "发送的响应体字节数",
|
||||
@ -197,7 +198,7 @@ func init() {
|
||||
})
|
||||
|
||||
// 13. $request_time - 请求处理时间
|
||||
// 需要从 VariableContext 获取
|
||||
// 需要从 Context 获取
|
||||
RegisterBuiltin(&BuiltinVariable{
|
||||
Name: VarRequestTime,
|
||||
Description: "请求处理时间(秒)",
|
||||
@ -215,7 +216,7 @@ func init() {
|
||||
RegisterBuiltin(&BuiltinVariable{
|
||||
Name: VarTimeLocal,
|
||||
Description: "本地时间(格式:02/Jan/2024:15:04:05 +0800)",
|
||||
Getter: func(ctx *fasthttp.RequestCtx) string {
|
||||
Getter: func(_ *fasthttp.RequestCtx) string {
|
||||
return time.Now().Format("02/Jan/2006:15:04:05 +0800")
|
||||
},
|
||||
})
|
||||
@ -224,7 +225,7 @@ func init() {
|
||||
RegisterBuiltin(&BuiltinVariable{
|
||||
Name: VarTimeISO8601,
|
||||
Description: "ISO8601 格式时间",
|
||||
Getter: func(ctx *fasthttp.RequestCtx) string {
|
||||
Getter: func(_ *fasthttp.RequestCtx) string {
|
||||
return time.Now().Format(time.RFC3339)
|
||||
},
|
||||
})
|
||||
|
||||
@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
// TestVariableInAccessLog 测试访问日志中的变量展开
|
||||
func TestVariableInAccessLog(t *testing.T) {
|
||||
func TestVariableInAccessLog(_ *testing.T) {
|
||||
// 创建测试请求上下文
|
||||
cfg := &config.LoggingConfig{
|
||||
Access: config.AccessLogConfig{
|
||||
@ -91,8 +91,8 @@ func TestVariableCompatibility(t *testing.T) {
|
||||
// 设置响应信息(模拟日志场景)
|
||||
variable.SetResponseInfoInContext(ctx, 201, 2048, 100000000) // 100ms
|
||||
|
||||
vc := variable.NewVariableContext(ctx)
|
||||
defer variable.ReleaseVariableContext(vc)
|
||||
vc := variable.NewContext(ctx)
|
||||
defer variable.ReleaseContext(vc)
|
||||
|
||||
tests := []struct {
|
||||
template string
|
||||
@ -129,8 +129,8 @@ func TestVariableExpansionPerformance(t *testing.T) {
|
||||
ctx.Request.Header.SetMethod("GET")
|
||||
ctx.Request.Header.SetHost("api.example.com")
|
||||
|
||||
vc := variable.NewVariableContext(ctx)
|
||||
defer variable.ReleaseVariableContext(vc)
|
||||
vc := variable.NewContext(ctx)
|
||||
defer variable.ReleaseContext(vc)
|
||||
|
||||
// 常见日志格式模板
|
||||
template := "$remote_addr - $remote_user [$time_local] \"$request_method $request_uri $scheme\" $status $body_bytes_sent \"$http_user_agent\""
|
||||
@ -160,8 +160,8 @@ func TestMixedVariableFormats(t *testing.T) {
|
||||
ctx.Request.Header.SetMethod("GET")
|
||||
ctx.Request.Header.SetHost("example.com")
|
||||
|
||||
vc := variable.NewVariableContext(ctx)
|
||||
defer variable.ReleaseVariableContext(vc)
|
||||
vc := variable.NewContext(ctx)
|
||||
defer variable.ReleaseContext(vc)
|
||||
|
||||
tests := []struct {
|
||||
template string
|
||||
@ -188,8 +188,8 @@ func TestUndefinedVariableInIntegration(t *testing.T) {
|
||||
ctx := &fasthttp.RequestCtx{}
|
||||
ctx.Request.SetRequestURI("/test")
|
||||
|
||||
vc := variable.NewVariableContext(ctx)
|
||||
defer variable.ReleaseVariableContext(vc)
|
||||
vc := variable.NewContext(ctx)
|
||||
defer variable.ReleaseContext(vc)
|
||||
|
||||
// 未定义变量应该保持原样
|
||||
template := "$host $undefined_var $uri"
|
||||
@ -213,14 +213,14 @@ func TestVariableContextReuse(t *testing.T) {
|
||||
ctx2.Request.Header.SetHost("second.com")
|
||||
|
||||
// 使用第一个上下文
|
||||
vc1 := variable.NewVariableContext(ctx1)
|
||||
vc1 := variable.NewContext(ctx1)
|
||||
result1 := vc1.Expand("$host$uri")
|
||||
variable.ReleaseVariableContext(vc1)
|
||||
variable.ReleaseContext(vc1)
|
||||
|
||||
// 复用(从池中获取)用于第二个上下文
|
||||
vc2 := variable.NewVariableContext(ctx2)
|
||||
vc2 := variable.NewContext(ctx2)
|
||||
result2 := vc2.Expand("$host$uri")
|
||||
variable.ReleaseVariableContext(vc2)
|
||||
variable.ReleaseContext(vc2)
|
||||
|
||||
// 验证结果正确
|
||||
if result1 != "first.com/first" {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// pool.go - VariableContext 池管理
|
||||
// Package variable 提供 sync.Pool 用于复用 Context,减少 GC 压力。
|
||||
//
|
||||
// 提供 sync.Pool 复用 VariableContext,减少 GC 压力。
|
||||
// 包含池统计信息、Get/Put 包装方法和统计重置功能。
|
||||
//
|
||||
// 作者:xfy
|
||||
package variable
|
||||
@ -39,9 +39,9 @@ func GetPool() *sync.Pool {
|
||||
return &pool
|
||||
}
|
||||
|
||||
// PoolGet 从池中获取 VariableContext(包装方法,用于统计)
|
||||
func PoolGet(ctx *fasthttp.RequestCtx) *VariableContext {
|
||||
vc := pool.Get().(*VariableContext)
|
||||
// PoolGet 从池中获取 Context(包装方法,用于统计)
|
||||
func PoolGet(ctx *fasthttp.RequestCtx) *Context {
|
||||
vc := pool.Get().(*Context)
|
||||
|
||||
// 初始化
|
||||
vc.ctx = ctx
|
||||
@ -67,8 +67,8 @@ func PoolGet(ctx *fasthttp.RequestCtx) *VariableContext {
|
||||
return vc
|
||||
}
|
||||
|
||||
// PoolPut 将 VariableContext 放回池中(包装方法,用于统计)
|
||||
func PoolPut(vc *VariableContext) {
|
||||
// PoolPut 将 Context 放回池中(包装方法,用于统计)
|
||||
func PoolPut(vc *Context) {
|
||||
if vc == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -31,6 +31,8 @@ const (
|
||||
VarSSLClientNotAfter = "ssl_client_notafter"
|
||||
VarSSLClientDNS = "ssl_client_s_dn"
|
||||
VarSSLClientEmail = "ssl_client_email"
|
||||
|
||||
sslProtocolNone = "NONE"
|
||||
)
|
||||
|
||||
// init 注册 SSL 变量
|
||||
@ -125,12 +127,12 @@ func init() {
|
||||
// - "NONE": 未提供证书
|
||||
func GetSSLClientVerify(ctx *fasthttp.RequestCtx) string {
|
||||
if ctx == nil {
|
||||
return "NONE"
|
||||
return sslProtocolNone
|
||||
}
|
||||
|
||||
// 检查是否有 TLS 连接信息
|
||||
if !ctx.IsTLS() {
|
||||
return "NONE"
|
||||
return sslProtocolNone
|
||||
}
|
||||
|
||||
// 从 UserValue 获取验证状态(由连接处理器设置)
|
||||
@ -145,7 +147,7 @@ func GetSSLClientVerify(ctx *fasthttp.RequestCtx) string {
|
||||
return "SUCCESS"
|
||||
}
|
||||
|
||||
return "NONE"
|
||||
return sslProtocolNone
|
||||
}
|
||||
|
||||
// GetSSLClientSerial 获取客户端证书序列号。
|
||||
@ -283,7 +285,7 @@ func calculateFingerprint(raw []byte) string {
|
||||
// - *pem.Block: 解析后的 PEM 块
|
||||
// - []byte: 剩余数据
|
||||
//
|
||||
// nolint:unused // 保留用于未来 SSL 变量解析功能
|
||||
//nolint:unused // 保留用于未来 SSL 变量解析功能
|
||||
func parsePEMCertificate(pemData []byte) (*pem.Block, []byte) {
|
||||
return pem.Decode(pemData)
|
||||
}
|
||||
|
||||
@ -25,8 +25,8 @@ import (
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
// VariableStore 变量存储接口
|
||||
type VariableStore interface {
|
||||
// Store 变量存储接口
|
||||
type Store interface {
|
||||
// Get 获取变量值
|
||||
Get(name string) (string, bool)
|
||||
// Set 设置变量值(用于自定义变量)
|
||||
@ -40,8 +40,8 @@ type BuiltinVariable struct {
|
||||
Getter func(ctx *fasthttp.RequestCtx) string
|
||||
}
|
||||
|
||||
// VariableContext 变量上下文,绑定到请求
|
||||
type VariableContext struct {
|
||||
// Context 变量上下文,绑定到请求
|
||||
type Context struct {
|
||||
ctx *fasthttp.RequestCtx
|
||||
store map[string]string // 自定义变量存储
|
||||
cache map[string]string // 内置变量缓存
|
||||
@ -57,10 +57,10 @@ type VariableContext struct {
|
||||
upstreamHeaderTime float64 // 上游首字节时间(秒)
|
||||
}
|
||||
|
||||
// pool 用于复用 VariableContext
|
||||
// pool 用于复用 Context
|
||||
var pool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &VariableContext{
|
||||
return &Context{
|
||||
store: make(map[string]string),
|
||||
cache: make(map[string]string),
|
||||
}
|
||||
@ -124,9 +124,9 @@ func GetBuiltin(name string) *BuiltinVariable {
|
||||
return builtinVars[name]
|
||||
}
|
||||
|
||||
// NewVariableContext 从池中获取 VariableContext,并注入全局变量。
|
||||
func NewVariableContext(ctx *fasthttp.RequestCtx) *VariableContext {
|
||||
vc := pool.Get().(*VariableContext)
|
||||
// NewContext 从池中获取 Context,并注入全局变量。
|
||||
func NewContext(ctx *fasthttp.RequestCtx) *Context {
|
||||
vc := pool.Get().(*Context)
|
||||
vc.ctx = ctx
|
||||
vc.status = 0
|
||||
vc.bodySize = 0
|
||||
@ -153,8 +153,13 @@ func NewVariableContext(ctx *fasthttp.RequestCtx) *VariableContext {
|
||||
return vc
|
||||
}
|
||||
|
||||
// ReleaseVariableContext 释放 VariableContext 回池中
|
||||
func ReleaseVariableContext(vc *VariableContext) {
|
||||
// NewVariableContext 是 NewContext 的别名(向后兼容)
|
||||
func NewVariableContext(ctx *fasthttp.RequestCtx) *Context {
|
||||
return NewContext(ctx)
|
||||
}
|
||||
|
||||
// ReleaseContext 释放 Context 回池中
|
||||
func ReleaseContext(vc *Context) {
|
||||
if vc == nil {
|
||||
return
|
||||
}
|
||||
@ -171,20 +176,25 @@ func ReleaseVariableContext(vc *VariableContext) {
|
||||
pool.Put(vc)
|
||||
}
|
||||
|
||||
// ReleaseVariableContext 是 ReleaseContext 的别名(向后兼容)
|
||||
func ReleaseVariableContext(vc *Context) {
|
||||
ReleaseContext(vc)
|
||||
}
|
||||
|
||||
// SetResponseInfo 设置响应信息(用于需要 status、body_bytes_sent、request_time 的场景)
|
||||
func (vc *VariableContext) SetResponseInfo(status int, bodySize int64, durationNs int64) {
|
||||
func (vc *Context) SetResponseInfo(status int, bodySize int64, durationNs int64) {
|
||||
vc.status = status
|
||||
vc.bodySize = bodySize
|
||||
vc.duration = durationNs
|
||||
}
|
||||
|
||||
// SetServerName 设置服务器名称
|
||||
func (vc *VariableContext) SetServerName(name string) {
|
||||
func (vc *Context) SetServerName(name string) {
|
||||
vc.serverName = name
|
||||
}
|
||||
|
||||
// SetUpstreamVars 设置上游变量
|
||||
func (vc *VariableContext) SetUpstreamVars(addr string, status int, responseTime, connectTime, headerTime float64) {
|
||||
func (vc *Context) SetUpstreamVars(addr string, status int, responseTime, connectTime, headerTime float64) {
|
||||
vc.upstreamAddr = addr
|
||||
vc.upstreamStatus = status
|
||||
vc.upstreamResponseTime = responseTime
|
||||
@ -193,7 +203,7 @@ func (vc *VariableContext) SetUpstreamVars(addr string, status int, responseTime
|
||||
}
|
||||
|
||||
// Get 获取变量值(优先自定义变量,再查内置变量)
|
||||
func (vc *VariableContext) Get(name string) (string, bool) {
|
||||
func (vc *Context) Get(name string) (string, bool) {
|
||||
// 1. 先查自定义变量
|
||||
if v, ok := vc.store[name]; ok {
|
||||
return v, true
|
||||
@ -281,12 +291,12 @@ func (vc *VariableContext) Get(name string) (string, bool) {
|
||||
}
|
||||
|
||||
// Set 设置自定义变量
|
||||
func (vc *VariableContext) Set(name string, value string) {
|
||||
func (vc *Context) Set(name string, value string) {
|
||||
vc.store[name] = value
|
||||
}
|
||||
|
||||
// evalBuiltin 求值内置变量
|
||||
func (vc *VariableContext) evalBuiltin(name string) (string, bool) {
|
||||
func (vc *Context) evalBuiltin(name string) (string, bool) {
|
||||
builtin := builtinVars[name]
|
||||
if builtin == nil || builtin.Getter == nil {
|
||||
return "", false
|
||||
@ -297,7 +307,7 @@ func (vc *VariableContext) evalBuiltin(name string) (string, bool) {
|
||||
// Expand 展开模板字符串中的变量
|
||||
// 支持 $var 和 ${var} 两种格式
|
||||
// 对于未定义的变量,保持原样不变
|
||||
func (vc *VariableContext) Expand(template string) string {
|
||||
func (vc *Context) Expand(template string) string {
|
||||
if template == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -30,8 +30,8 @@ func setupBenchmarkRequestCtx() *fasthttp.RequestCtx {
|
||||
// 模板: "$remote_addr - $request_method"
|
||||
func BenchmarkVariableExpandSimple(b *testing.B) {
|
||||
ctx := setupBenchmarkRequestCtx()
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
template := "$remote_addr - $request_method"
|
||||
|
||||
@ -47,9 +47,9 @@ func BenchmarkVariableExpandSimple(b *testing.B) {
|
||||
// "$remote_addr - [$time_local] \"$request_method $uri $args\" $status $body_bytes_sent"
|
||||
func BenchmarkVariableExpandComplex(b *testing.B) {
|
||||
ctx := setupBenchmarkRequestCtx()
|
||||
vc := NewVariableContext(ctx)
|
||||
vc := NewContext(ctx)
|
||||
vc.SetResponseInfo(200, 1024, 1000000) // status, bodySize, durationNs
|
||||
defer ReleaseVariableContext(vc)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
template := "$remote_addr - [$time_local] \"$request_method $uri $args\" $status $body_bytes_sent"
|
||||
|
||||
@ -62,8 +62,8 @@ func BenchmarkVariableExpandComplex(b *testing.B) {
|
||||
// BenchmarkVariableExpandMixed 测试混合 ${var} 和 $var 格式的展开性能。
|
||||
func BenchmarkVariableExpandMixed(b *testing.B) {
|
||||
ctx := setupBenchmarkRequestCtx()
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
template := "${remote_addr} - $request_method ${uri}?${args}"
|
||||
|
||||
@ -76,8 +76,8 @@ func BenchmarkVariableExpandMixed(b *testing.B) {
|
||||
// BenchmarkVariableExpandNoVar 测试无变量模板的性能(快速路径)。
|
||||
func BenchmarkVariableExpandNoVar(b *testing.B) {
|
||||
ctx := setupBenchmarkRequestCtx()
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
template := "This is a plain string with no variables"
|
||||
|
||||
@ -93,8 +93,8 @@ func BenchmarkVariableContextPool(b *testing.B) {
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
vc := NewVariableContext(ctx)
|
||||
ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
ReleaseContext(vc)
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,8 +104,8 @@ func BenchmarkVariableContextPoolParallel(b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
ctx := setupBenchmarkRequestCtx()
|
||||
for pb.Next() {
|
||||
vc := NewVariableContext(ctx)
|
||||
ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
ReleaseContext(vc)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -115,8 +115,8 @@ func BenchmarkVariableContextPoolParallel(b *testing.B) {
|
||||
// 首次获取变量会求值并缓存,后续获取命中缓存。
|
||||
func BenchmarkVariableGetCache(b *testing.B) {
|
||||
ctx := setupBenchmarkRequestCtx()
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 预热缓存
|
||||
_, _ = vc.Get("remote_addr")
|
||||
@ -135,17 +135,17 @@ func BenchmarkVariableGetNoCache(b *testing.B) {
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
vc := NewVariableContext(ctx)
|
||||
vc := NewContext(ctx)
|
||||
vc.Get("remote_addr")
|
||||
ReleaseVariableContext(vc)
|
||||
ReleaseContext(vc)
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkVariableGetMultiple 测试获取多个内置变量的性能。
|
||||
func BenchmarkVariableGetMultiple(b *testing.B) {
|
||||
ctx := setupBenchmarkRequestCtx()
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
vars := []string{
|
||||
"remote_addr", "request_method", "uri", "args",
|
||||
@ -163,8 +163,8 @@ func BenchmarkVariableGetMultiple(b *testing.B) {
|
||||
// BenchmarkVariableSetAndGet 测试设置和获取自定义变量的性能。
|
||||
func BenchmarkVariableSetAndGet(b *testing.B) {
|
||||
ctx := setupBenchmarkRequestCtx()
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@ -198,10 +198,10 @@ func BenchmarkExpandStringStaticWithLookup(b *testing.B) {
|
||||
// 模拟完整访问日志格式,约 200 字符。
|
||||
func BenchmarkVariableExpandLongTemplate(b *testing.B) {
|
||||
ctx := setupBenchmarkRequestCtx()
|
||||
vc := NewVariableContext(ctx)
|
||||
vc := NewContext(ctx)
|
||||
vc.SetResponseInfo(200, 4096, 15000000)
|
||||
vc.SetServerName("api.example.com")
|
||||
defer ReleaseVariableContext(vc)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
template := "$remote_addr - [$time_local] \"$request_method $uri?$args\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\" $request_time $server_name"
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
// mockRequestCtx 创建测试用的 fasthttp.RequestCtx
|
||||
func mockRequestCtx(t *testing.T) *fasthttp.RequestCtx {
|
||||
func mockRequestCtx(_ *testing.T) *fasthttp.RequestCtx {
|
||||
ctx := &fasthttp.RequestCtx{}
|
||||
|
||||
// 设置请求信息
|
||||
@ -51,8 +51,8 @@ func TestBuiltinVariables(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
value, ok := vc.Get(tt.varName)
|
||||
if !ok && !tt.contains {
|
||||
@ -76,8 +76,8 @@ func TestBuiltinVariables(t *testing.T) {
|
||||
// TestExpandSimple 测试简单变量展开
|
||||
func TestExpandSimple(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
tests := []struct {
|
||||
template string
|
||||
@ -104,8 +104,8 @@ func TestExpandSimple(t *testing.T) {
|
||||
// TestExpandBrace 测试花括号变量展开
|
||||
func TestExpandBrace(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
tests := []struct {
|
||||
template string
|
||||
@ -132,8 +132,8 @@ func TestExpandBrace(t *testing.T) {
|
||||
// TestExpandMixed 测试混合格式展开
|
||||
func TestExpandMixed(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
tests := []struct {
|
||||
template string
|
||||
@ -157,8 +157,8 @@ func TestExpandMixed(t *testing.T) {
|
||||
// TestExpandUndefined 测试未定义变量
|
||||
func TestExpandUndefined(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
tests := []struct {
|
||||
template string
|
||||
@ -183,8 +183,8 @@ func TestExpandUndefined(t *testing.T) {
|
||||
// TestExpandEdgeCases 测试边界情况
|
||||
func TestExpandEdgeCases(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
tests := []struct {
|
||||
template string
|
||||
@ -212,8 +212,8 @@ func TestExpandEdgeCases(t *testing.T) {
|
||||
// TestCustomVariable 测试自定义变量
|
||||
func TestCustomVariable(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 设置自定义变量
|
||||
vc.Set("custom_var", "custom_value")
|
||||
@ -234,8 +234,8 @@ func TestCustomVariable(t *testing.T) {
|
||||
// TestCustomOverridesBuiltin 测试自定义变量覆盖内置变量
|
||||
func TestCustomOverridesBuiltin(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 设置同名自定义变量
|
||||
vc.Set("host", "custom.host.com")
|
||||
@ -250,8 +250,8 @@ func TestCustomOverridesBuiltin(t *testing.T) {
|
||||
// TestResponseInfoVariables 测试响应相关变量
|
||||
func TestResponseInfoVariables(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 设置响应信息
|
||||
vc.SetResponseInfo(200, 1024, 15000000) // 15ms
|
||||
@ -345,8 +345,8 @@ func BenchmarkExpandSimple(b *testing.B) {
|
||||
ctx.Request.Header.SetMethod("GET")
|
||||
ctx.Request.Header.SetRequestURI("/test")
|
||||
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
template := "$host $request_method $uri"
|
||||
|
||||
@ -365,8 +365,8 @@ func BenchmarkExpandComplex(b *testing.B) {
|
||||
ctx.Request.Header.SetMethod("GET")
|
||||
ctx.Request.Header.SetRequestURI("/api/v1/users?page=1&limit=10")
|
||||
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 模拟日志格式
|
||||
template := "$remote_addr - - [$time_local] \"$request_method $request_uri HTTP/1.1\" $status $body_bytes_sent"
|
||||
@ -382,8 +382,8 @@ func BenchmarkExpandComplex(b *testing.B) {
|
||||
// BenchmarkExpandNoVariable 基准测试:无变量字符串
|
||||
func BenchmarkExpandNoVariable(b *testing.B) {
|
||||
ctx := &fasthttp.RequestCtx{}
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
template := "This is a static string without any variables"
|
||||
|
||||
@ -401,8 +401,8 @@ func BenchmarkExpandBrace(b *testing.B) {
|
||||
ctx.Request.Header.SetHost("example.com")
|
||||
ctx.Request.Header.SetMethod("GET")
|
||||
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
template := "${scheme}://${host}${uri}"
|
||||
|
||||
@ -422,8 +422,8 @@ func BenchmarkPoolGetPut(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
vc := NewVariableContext(ctx)
|
||||
ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
ReleaseContext(vc)
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,20 +456,20 @@ func TestPoolReuse(t *testing.T) {
|
||||
|
||||
// 获取和释放多个 context,确保没有 panic
|
||||
for i := 0; i < 10; i++ {
|
||||
vc := NewVariableContext(ctx)
|
||||
vc := NewContext(ctx)
|
||||
vc.Set("key", "value")
|
||||
if v, ok := vc.Get("key"); !ok || v != "value" {
|
||||
t.Errorf("iteration %d: expected key=value, got %s", i, v)
|
||||
}
|
||||
ReleaseVariableContext(vc)
|
||||
ReleaseContext(vc)
|
||||
}
|
||||
|
||||
// 验证池在复用(第二次获取应该清除之前的值)
|
||||
vc2 := NewVariableContext(ctx)
|
||||
vc2 := NewContext(ctx)
|
||||
if v, ok := vc2.Get("key"); ok {
|
||||
t.Errorf("expected key to be cleared after release, got %s", v)
|
||||
}
|
||||
ReleaseVariableContext(vc2)
|
||||
ReleaseContext(vc2)
|
||||
}
|
||||
|
||||
// TestMoreBuiltinVariables 测试更多内置变量
|
||||
@ -483,21 +483,21 @@ func TestMoreBuiltinVariables(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "server_port with local addr",
|
||||
setupFunc: func(ctx *fasthttp.RequestCtx) {},
|
||||
setupFunc: func(_ *fasthttp.RequestCtx) {},
|
||||
varName: VarServerPort,
|
||||
expected: "0", // 没有设置 local addr 时返回 "0"
|
||||
shouldExist: true,
|
||||
},
|
||||
{
|
||||
name: "remote_addr without addr",
|
||||
setupFunc: func(ctx *fasthttp.RequestCtx) {},
|
||||
setupFunc: func(_ *fasthttp.RequestCtx) {},
|
||||
varName: VarRemoteAddr,
|
||||
expected: "0.0.0.0:0", // mock ctx 返回默认值
|
||||
shouldExist: true,
|
||||
},
|
||||
{
|
||||
name: "remote_port without addr",
|
||||
setupFunc: func(ctx *fasthttp.RequestCtx) {},
|
||||
setupFunc: func(_ *fasthttp.RequestCtx) {},
|
||||
varName: VarRemotePort,
|
||||
expected: "0",
|
||||
shouldExist: true,
|
||||
@ -526,8 +526,8 @@ func TestMoreBuiltinVariables(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
tt.setupFunc(ctx)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
value, ok := vc.Get(tt.varName)
|
||||
if tt.shouldExist && !ok {
|
||||
@ -542,9 +542,9 @@ func TestMoreBuiltinVariables(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestReleaseNilContext 测试释放 nil context
|
||||
func TestReleaseNilContext(t *testing.T) {
|
||||
func TestReleaseNilContext(_ *testing.T) {
|
||||
// 不应该 panic
|
||||
ReleaseVariableContext(nil)
|
||||
ReleaseContext(nil)
|
||||
}
|
||||
|
||||
// TestGetBuiltin 测试获取内置变量定义
|
||||
@ -633,8 +633,8 @@ func TestGetCookieVariable(t *testing.T) {
|
||||
// TestEmptyTemplate 测试空模板
|
||||
func TestEmptyTemplate(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
result := vc.Expand("")
|
||||
if result != "" {
|
||||
@ -642,17 +642,17 @@ func TestEmptyTemplate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestReleaseVariableContextWithNil 测试释放 nil
|
||||
func TestReleaseVariableContextWithNil(t *testing.T) {
|
||||
// TestReleaseContextWithNil 测试释放 nil
|
||||
func TestReleaseContextWithNil(_ *testing.T) {
|
||||
// 不应该 panic
|
||||
ReleaseVariableContext(nil)
|
||||
ReleaseContext(nil)
|
||||
}
|
||||
|
||||
// TestExpandOnlyDollar 测试只有 $ 的情况
|
||||
func TestExpandOnlyDollar(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
tests := []struct {
|
||||
template string
|
||||
@ -698,7 +698,7 @@ func TestPoolFunctions(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestPoolPutNil 测试 PoolPut nil
|
||||
func TestPoolPutNil(t *testing.T) {
|
||||
func TestPoolPutNil(_ *testing.T) {
|
||||
// 不应该 panic
|
||||
PoolPut(nil)
|
||||
}
|
||||
@ -724,8 +724,8 @@ func TestStatsFunctions(t *testing.T) {
|
||||
// TestSetResponseInfo 测试 SetResponseInfo
|
||||
func TestSetResponseInfo(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 设置响应信息
|
||||
vc.SetResponseInfo(404, 512, 25000000) // 25ms
|
||||
@ -744,8 +744,8 @@ func TestSetResponseInfo(t *testing.T) {
|
||||
// TestSetServerName 测试 SetServerName
|
||||
func TestSetServerName(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
vc.SetServerName("my-server")
|
||||
if vc.serverName != "my-server" {
|
||||
@ -755,7 +755,7 @@ func TestSetServerName(t *testing.T) {
|
||||
|
||||
// TestEmptyExpandString 测试空模板 ExpandString
|
||||
func TestEmptyExpandString(t *testing.T) {
|
||||
lookup := func(name string) string { return "" }
|
||||
lookup := func(_ string) string { return "" }
|
||||
result := ExpandString("", lookup)
|
||||
if result != "" {
|
||||
t.Errorf("ExpandString('') = %q, want empty", result)
|
||||
@ -764,7 +764,7 @@ func TestEmptyExpandString(t *testing.T) {
|
||||
|
||||
// TestExpandStringNoVar 测试无变量模板
|
||||
func TestExpandStringNoVar(t *testing.T) {
|
||||
lookup := func(name string) string { return "" }
|
||||
lookup := func(_ string) string { return "" }
|
||||
result := ExpandString("hello world", lookup)
|
||||
if result != "hello world" {
|
||||
t.Errorf("ExpandString = %q, want 'hello world'", result)
|
||||
@ -780,8 +780,8 @@ func TestTLSBuiltin(t *testing.T) {
|
||||
// 由于无法直接设置 TLS,scheme 变量会检查 ctx.IsTLS()
|
||||
// 这里我们测试它返回 http(默认值)
|
||||
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
scheme, ok := vc.Get("scheme")
|
||||
if !ok {
|
||||
@ -795,8 +795,8 @@ func TestTLSBuiltin(t *testing.T) {
|
||||
// TestEmptyVarNameBrace 测试空变量名 ${}
|
||||
func TestEmptyVarNameBrace(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// ${} 应该保持为 ${}
|
||||
result := vc.Expand("${}")
|
||||
@ -835,8 +835,8 @@ func TestBuiltinVarNames(t *testing.T) {
|
||||
// TestUpstreamVariables 测试上游变量
|
||||
func TestUpstreamVariables(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 未设置时应该返回默认值 "-"
|
||||
tests := []struct {
|
||||
@ -895,8 +895,8 @@ func TestUpstreamVariables(t *testing.T) {
|
||||
// TestUpstreamVariablesInExpand 测试在模板中展开上游变量
|
||||
func TestUpstreamVariablesInExpand(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 设置上游变量
|
||||
vc.SetUpstreamVars("http://backend:8080", 200, 0.123, 0.001, 0.045)
|
||||
@ -913,8 +913,8 @@ func TestUpstreamVariablesInExpand(t *testing.T) {
|
||||
// TestUpstreamVariablesErrorCases 测试上游变量错误情况
|
||||
func TestUpstreamVariablesErrorCases(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 测试各种错误场景
|
||||
tests := []struct {
|
||||
@ -982,8 +982,8 @@ func TestUpstreamVariablesErrorCases(t *testing.T) {
|
||||
// TestUpstreamVariablesZeroValues 测试上游变量零值处理
|
||||
func TestUpstreamVariablesZeroValues(t *testing.T) {
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 测试零值应该返回 "-"
|
||||
vc.SetUpstreamVars("", 0, 0, 0, 0)
|
||||
@ -1020,8 +1020,8 @@ func BenchmarkUpstreamVariables(b *testing.B) {
|
||||
ctx.Request.Header.SetMethod("GET")
|
||||
ctx.Request.Header.SetRequestURI("/test")
|
||||
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 设置上游变量
|
||||
vc.SetUpstreamVars("http://backend:8080", 200, 0.123, 0.001, 0.045)
|
||||
@ -1075,8 +1075,8 @@ func TestGlobalVariables(t *testing.T) {
|
||||
SetGlobalVariables(nil)
|
||||
}
|
||||
|
||||
// TestNewVariableContextWithGlobals 测试全局变量注入到请求上下文
|
||||
func TestNewVariableContextWithGlobals(t *testing.T) {
|
||||
// TestNewContextWithGlobals 测试全局变量注入到请求上下文
|
||||
func TestNewContextWithGlobals(t *testing.T) {
|
||||
// 设置全局变量
|
||||
SetGlobalVariables(map[string]string{
|
||||
"global_var": "global_value",
|
||||
@ -1084,8 +1084,8 @@ func TestNewVariableContextWithGlobals(t *testing.T) {
|
||||
defer SetGlobalVariables(nil)
|
||||
|
||||
ctx := mockRequestCtx(t)
|
||||
vc := NewVariableContext(ctx)
|
||||
defer ReleaseVariableContext(vc)
|
||||
vc := NewContext(ctx)
|
||||
defer ReleaseContext(vc)
|
||||
|
||||
// 全局变量应该被注入
|
||||
if v, ok := vc.Get("global_var"); !ok || v != "global_value" {
|
||||
@ -1100,7 +1100,7 @@ func TestNewVariableContextWithGlobals(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestGlobalVariablesConcurrent 测试全局变量并发访问
|
||||
func TestGlobalVariablesConcurrent(t *testing.T) {
|
||||
func TestGlobalVariablesConcurrent(_ *testing.T) {
|
||||
SetGlobalVariables(map[string]string{
|
||||
"counter": "0",
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user