lolly/internal/lua/api_ctx.go
xfy 26f18055ce feat(lua): 添加 Scheduler 模式下的 API 安全检查
为定时器回调上下文注册不安全的 ngx API 时返回错误:
- ngx.ctx: 请求上下文不可用
- ngx.req: 请求 API 不可用
- ngx.resp: 响应 API 不可用
- ngx.var: 变量 API 不可用
- ngx.log: 提供安全版本(不依赖 RequestCtx)

防止定时器回调中误用请求相关 API 导致并发问题。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 09:24:43 +08:00

76 lines
1.9 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 lua 提供 ngx.ctx API 实现
package lua
import (
glua "github.com/yuin/gopher-lua"
)
// ngxCtxAPI ngx.ctx API 实现
type ngxCtxAPI struct {
// 每个请求独立的 ctx 表
// 存储在协程的全局变量中
ctxTable *glua.LTable
}
// newNgxCtxAPI 创建 ngx.ctx API 实例
func newNgxCtxAPI() *ngxCtxAPI {
return &ngxCtxAPI{}
}
// RegisterNgxCtxAPI 在 Lua 状态机中注册 ngx.ctx API
// ngx.ctx 是一个普通的 Lua table每请求独立支持任意 Lua 值类型
func RegisterNgxCtxAPI(L *glua.LState, ngxTable *glua.LTable) {
// 创建请求级的 ctx table
ctxTable := L.NewTable()
// 将 ngx.ctx 添加到 ngx 表
ngxTable.RawSetString("ctx", ctxTable)
}
// GetCtxTable 获取 ctx table用于内部访问
func (api *ngxCtxAPI) GetCtxTable(L *glua.LState) *glua.LTable {
ngx := L.GetGlobal("ngx")
if ngx == glua.LNil {
return nil
}
if ngxTable, ok := ngx.(*glua.LTable); ok {
ctx := ngxTable.RawGetString("ctx")
if ctxTable, ok := ctx.(*glua.LTable); ok {
return ctxTable
}
}
return nil
}
// SetValue 在 Go 层设置 ctx 值
func (api *ngxCtxAPI) SetValue(L *glua.LState, key string, value glua.LValue) {
tb := api.GetCtxTable(L)
if tb != nil {
tb.RawSetString(key, value)
}
}
// GetValue 在 Go 层获取 ctx 值
func (api *ngxCtxAPI) GetValue(L *glua.LState, key string) glua.LValue {
tb := api.GetCtxTable(L)
if tb != nil {
return tb.RawGetString(key)
}
return glua.LNil
}
// RegisterSchedulerUnsafeCtxAPI 为 Scheduler LState 注册不安全的 ngx.ctx API
func RegisterSchedulerUnsafeCtxAPI(L *glua.LState, ngx *glua.LTable) {
ctxTable := L.NewTable()
mt := L.NewTable()
mt.RawSetString("__index", L.NewFunction(luaSchedulerUnsafeCtx))
mt.RawSetString("__newindex", L.NewFunction(luaSchedulerUnsafeCtx))
L.SetMetatable(ctxTable, mt)
ngx.RawSetString("ctx", ctxTable)
}
func luaSchedulerUnsafeCtx(L *glua.LState) int {
L.RaiseError("API ngx.ctx not available in timer callback context")
return 0
}