- 新增 getVariableLua 方法返回 Lua 类型而非字符串 - request_length 等变量返回数值类型而非字符串 - luaVarNewIndex 支持 nil 值转换为空字符串 - 添加 api_var 全面的单元测试覆盖 - 添加 api_ctx 上下文 API 测试 - 添加 api_socket_tcp TCP socket 测试 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
679 lines
17 KiB
Go
679 lines
17 KiB
Go
// Package lua 提供 ngx.var API 测试
|
||
package lua
|
||
|
||
import (
|
||
"testing"
|
||
|
||
"github.com/stretchr/testify/assert"
|
||
"github.com/stretchr/testify/require"
|
||
"github.com/valyala/fasthttp"
|
||
)
|
||
|
||
// TestNgxVarAPI 测试 ngx.var API 基础功能
|
||
func TestNgxVarAPI(t *testing.T) {
|
||
// 创建 fasthttp 请求上下文
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("GET")
|
||
req.Header.SetRequestURI("/test/path?foo=bar&baz=qux")
|
||
req.Header.Set("Host", "example.com")
|
||
req.Header.Set("User-Agent", "TestAgent")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
// 创建协程
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
// 设置沙箱(这会注册 ngx API)
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
// 测试 ngx.var 存在
|
||
err = coro.Execute(`
|
||
if type(ngx) ~= "table" then
|
||
error("ngx is not a table")
|
||
end
|
||
if type(ngx.var) ~= "table" then
|
||
error("ngx.var is not a table")
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarReadBuiltin 测试读取内置变量
|
||
func TestNgxVarReadBuiltin(t *testing.T) {
|
||
// 创建 fasthttp 请求上下文
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("POST")
|
||
req.Header.SetRequestURI("/api/test?name=value")
|
||
req.Header.Set("Host", "test.example.com")
|
||
req.Header.Set("User-Agent", "Mozilla/5.0")
|
||
req.Header.Set("Accept", "application/json")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
// 测试读取内置变量
|
||
err = coro.Execute(`
|
||
local method = ngx.var.request_method
|
||
if method ~= "POST" then
|
||
error("request_method should be POST, got: " .. tostring(method))
|
||
end
|
||
|
||
local uri = ngx.var.uri
|
||
if uri ~= "/api/test" then
|
||
error("uri should be /api/test, got: " .. tostring(uri))
|
||
end
|
||
|
||
local host = ngx.var.http_host
|
||
if host ~= "test.example.com" then
|
||
error("http_host should be test.example.com, got: " .. tostring(host))
|
||
end
|
||
|
||
local userAgent = ngx.var.http_user_agent
|
||
if userAgent ~= "Mozilla/5.0" then
|
||
error("http_user_agent should be Mozilla/5.0, got: " .. tostring(userAgent))
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarReadQueryArgs 测试读取查询参数
|
||
func TestNgxVarReadQueryArgs(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("GET")
|
||
req.Header.SetRequestURI("/search?q=lua&page=1")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
// 测试读取查询参数
|
||
err = coro.Execute(`
|
||
local q = ngx.var.arg_q
|
||
if q ~= "lua" then
|
||
error("arg_q should be 'lua', got: " .. tostring(q))
|
||
end
|
||
|
||
local page = ngx.var.arg_page
|
||
if page ~= "1" then
|
||
error("arg_page should be '1', got: " .. tostring(page))
|
||
end
|
||
|
||
local queryString = ngx.var.query_string
|
||
if type(queryString) ~= "string" then
|
||
error("query_string should be a string")
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarWriteCustom 测试设置自定义变量
|
||
func TestNgxVarWriteCustom(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("GET")
|
||
req.Header.SetRequestURI("/test")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
// 测试设置和读取自定义变量
|
||
err = coro.Execute(`
|
||
-- 设置自定义变量
|
||
ngx.var.my_custom_var = "hello world"
|
||
ngx.var.another_var = "12345"
|
||
|
||
-- 读取自定义变量
|
||
local val1 = ngx.var.my_custom_var
|
||
if val1 ~= "hello world" then
|
||
error("my_custom_var should be 'hello world', got: " .. tostring(val1))
|
||
end
|
||
|
||
local val2 = ngx.var.another_var
|
||
if val2 ~= "12345" then
|
||
error("another_var should be '12345', got: " .. tostring(val2))
|
||
end
|
||
|
||
-- 覆盖已存在的变量
|
||
ngx.var.my_custom_var = "updated"
|
||
local val3 = ngx.var.my_custom_var
|
||
if val3 ~= "updated" then
|
||
error("my_custom_var should be 'updated', got: " .. tostring(val3))
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarIndexAccess 测试索引访问方式 ngx.var[key]
|
||
func TestNgxVarIndexAccess(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("GET")
|
||
req.Header.SetRequestURI("/test")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
// 测试索引访问
|
||
err = coro.Execute(`
|
||
-- 使用索引方式设置变量
|
||
ngx.var["dynamic_key"] = "dynamic_value"
|
||
|
||
-- 使用索引方式读取变量
|
||
local val = ngx.var["dynamic_key"]
|
||
if val ~= "dynamic_value" then
|
||
error("dynamic_key should be 'dynamic_value', got: " .. tostring(val))
|
||
end
|
||
|
||
-- 混合访问方式
|
||
ngx.var.mixed = "mixed_value"
|
||
local mixed = ngx.var["mixed"]
|
||
if mixed ~= "mixed_value" then
|
||
error("mixed should be 'mixed_value', got: " .. tostring(mixed))
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarNilRequestCtx 测试无请求上下文的情况
|
||
func TestNgxVarNilRequestCtx(t *testing.T) {
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
// 创建没有请求上下文的协程
|
||
coro, err := engine.NewCoroutine(nil)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
// 测试在无请求上下文时访问 ngx.var
|
||
err = coro.Execute(`
|
||
-- 应该返回空字符串或 nil
|
||
local method = ngx.var.request_method
|
||
-- 可以接受空字符串或 nil
|
||
|
||
-- 但自定义变量仍然可以设置
|
||
ngx.var.test = "value"
|
||
local val = ngx.var.test
|
||
if val ~= "value" then
|
||
error("custom var should be settable even without request ctx")
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarUndefined 测试未定义变量
|
||
func TestNgxVarUndefined(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("GET")
|
||
req.Header.SetRequestURI("/test")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
// 测试读取未定义变量
|
||
err = coro.Execute(`
|
||
local undefined = ngx.var.undefined_var_name
|
||
if undefined ~= nil then
|
||
error("undefined var should be nil, got: " .. tostring(undefined))
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarAdditionalBuiltinVars 测试其他内置变量
|
||
func TestNgxVarAdditionalBuiltinVars(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("DELETE")
|
||
req.Header.SetRequestURI("/api/users?id=123&name=test")
|
||
req.Header.Set("Host", "api.example.com")
|
||
req.Header.Set("User-Agent", "TestClient/1.0")
|
||
req.Header.Set("Accept", "application/json")
|
||
req.Header.Set("Content-Type", "application/json")
|
||
req.Header.Set("Authorization", "Bearer token123")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
// 测试其他内置变量
|
||
err = coro.Execute(`
|
||
-- URI 相关变量
|
||
local request_uri = ngx.var.request_uri
|
||
if request_uri ~= "/api/users?id=123&name=test" then
|
||
error("request_uri mismatch, got: " .. tostring(request_uri))
|
||
end
|
||
|
||
local uri = ngx.var.uri
|
||
if uri ~= "/api/users" then
|
||
error("urishould be /api/users, got: " .. tostring(uri))
|
||
end
|
||
|
||
local document_uri = ngx.var.document_uri
|
||
if document_uri ~= "/api/users" then
|
||
error("document_uri should be /api/users, got: " .. tostring(document_uri))
|
||
end
|
||
|
||
-- 查询字符串
|
||
local query_string = ngx.var.query_string
|
||
if query_string ~= "id=123&name=test" then
|
||
error("query_string mismatch, got: " .. tostring(query_string))
|
||
end
|
||
|
||
local args = ngx.var.args
|
||
if args ~= "id=123&name=test" then
|
||
error("args should match query_string, got: " .. tostring(args))
|
||
end
|
||
|
||
-- 请求头
|
||
local accept = ngx.var.http_accept
|
||
if accept ~= "application/json" then
|
||
error("http_accept mismatch, got: " .. tostring(accept))
|
||
end
|
||
|
||
local contentType = ngx.var.http_content_type
|
||
if contentType ~= "application/json" then
|
||
error("http_content_type mismatch, got: " .. tostring(contentType))
|
||
end
|
||
|
||
local authorization = ngx.var.http_authorization
|
||
if authorization ~= "Bearer token123" then
|
||
error("http_authorization mismatch, got: " .. tostring(authorization))
|
||
end
|
||
|
||
-- 内置变量 map
|
||
local vars = {
|
||
"request_method", "request_uri", "uri", "document_uri",
|
||
"query_string", "args", "http_host", "http_user_agent",
|
||
"http_accept", "http_content_type"
|
||
}
|
||
for _, v in ipairs(vars) do
|
||
local val = ngx.var[v]
|
||
if type(val) ~= "string" then
|
||
error("var " .. v .. " should be string, got: " .. type(val))
|
||
end
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarDynamicArgsAccess 测试动态参数访问
|
||
func TestNgxVarDynamicArgsAccess(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("GET")
|
||
req.Header.SetRequestURI("/search?keyword=lua&category=programming&limit=10")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
// 测试动态参数访问
|
||
err = coro.Execute(`
|
||
-- 直接通过 arg_ 访问
|
||
local keyword = ngx.var.arg_keyword
|
||
if keyword ~= "lua" then
|
||
error("arg_keyword should be 'lua', got: " .. tostring(keyword))
|
||
end
|
||
|
||
local category = ngx.var.arg_category
|
||
if category ~= "programming" then
|
||
error("arg_category should be 'programming', got: " .. tostring(category))
|
||
end
|
||
|
||
local limit = ngx.var.arg_limit
|
||
if limit ~= "10" then
|
||
error("arg_limit should be '10', got: " .. tostring(limit))
|
||
end
|
||
|
||
-- 使用动态键访问
|
||
local keys = {"keyword", "category", "limit"}
|
||
for i, k in ipairs(keys) do
|
||
local val = ngx.var["arg_" .. k]
|
||
if type(val) ~= "string" then
|
||
error("dynamic arg access should return string")
|
||
end
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarGoAPI 测试 Go 层 API 调用
|
||
func TestNgxVarGoAPI(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("GET")
|
||
req.Header.SetRequestURI("/test")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
// 直接创建 API 实例并测试 Go 层 API
|
||
api := newNgxVarAPI(ctx)
|
||
require.NotNil(t, api)
|
||
|
||
// 测试 SetVariable
|
||
api.SetVariable("go_set_var", "value_from_go")
|
||
value, ok := api.GetVariable("go_set_var")
|
||
assert.True(t, ok)
|
||
assert.Equal(t, "value_from_go", value)
|
||
|
||
// 测试 GetVariable 不存在的变量
|
||
value, ok = api.GetVariable("nonexistent")
|
||
assert.False(t, ok)
|
||
assert.Equal(t, "", value)
|
||
|
||
// 测试覆盖:Go 设置,Go 读取验证
|
||
api.SetVariable("cross_lang", "from_go")
|
||
val, ok := api.GetVariable("cross_lang")
|
||
assert.True(t, ok)
|
||
assert.Equal(t, "from_go", val)
|
||
|
||
// 测试覆盖:直接设置 store,Go 读取验证
|
||
api.store["cross_lang2"] = "from_lua"
|
||
value, ok = api.GetVariable("cross_lang2")
|
||
assert.True(t, ok)
|
||
assert.Equal(t, "from_lua", value)
|
||
}
|
||
|
||
// TestNgxVarRequestMethodAccess 测试各种请求方法
|
||
func TestNgxVarRequestMethodAccess(t *testing.T) {
|
||
methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"}
|
||
|
||
for _, method := range methods {
|
||
t.Run(method, func(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod(method)
|
||
req.Header.SetRequestURI("/test")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
err = coro.Execute(`
|
||
local method = ngx.var.request_method
|
||
if method ~= "` + method + `" then
|
||
error("request_method should be '` + method + `', got: " .. tostring(method))
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
})
|
||
}
|
||
}
|
||
|
||
// TestNgxVarMixedAccessPatterns 测试混合访问模式
|
||
func TestNgxVarMixedAccessPatterns(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("GET")
|
||
req.Header.SetRequestURI("/test")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
// 测试混合访问模式
|
||
err = coro.Execute(`
|
||
-- 点号访问设置
|
||
ngx.var.test1 = "value1"
|
||
-- 索引访问读取
|
||
local val1 = ngx.var["test1"]
|
||
if val1 ~= "value1" then
|
||
error("mixed access 1 failed")
|
||
end
|
||
|
||
-- 索引访问设置
|
||
ngx.var["test2"] = "value2"
|
||
-- 点号访问读取
|
||
local val2 = ngx.var.test2
|
||
if val2 ~= "value2" then
|
||
error("mixed access 2 failed")
|
||
end
|
||
|
||
-- 循环访问
|
||
for i = 1, 3 do
|
||
ngx.var["dynamic_" .. i] = "val_" .. i
|
||
end
|
||
|
||
for i = 1, 3 do
|
||
local v = ngx.var["dynamic_" .. i]
|
||
if v ~= "val_" .. i then
|
||
error("dynamic loop failed for i=" .. i)
|
||
end
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarSpecialHeaders 测试特殊请求头
|
||
func TestNgxVarSpecialHeaders(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("GET")
|
||
req.Header.SetRequestURI("/test")
|
||
req.Header.Set("Accept-Encoding", "gzip, deflate, br")
|
||
req.Header.Set("Accept-Language", "en-US,en;q=0.9")
|
||
req.Header.Set("Connection", "keep-alive")
|
||
req.Header.Set("Referer", "https://example.com")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
err = coro.Execute(`
|
||
-- 测试带连字符的头
|
||
local acceptEncoding = ngx.var.http_accept_encoding
|
||
if acceptEncoding ~= "gzip, deflate, br" then
|
||
error("http_accept_encoding mismatch")
|
||
end
|
||
|
||
local acceptLanguage = ngx.var.http_accept_language
|
||
if acceptLanguage ~= "en-US,en;q=0.9" then
|
||
error("http_accept_language mismatch")
|
||
end
|
||
|
||
local connection = ngx.var.http_connection
|
||
if connection ~= "keep-alive" then
|
||
error("http_connection mismatch")
|
||
end
|
||
|
||
local referer = ngx.var.http_referer
|
||
if referer ~= "https://example.com" then
|
||
error("http_referer mismatch")
|
||
end
|
||
|
||
-- 测试也可以通过下划线访问
|
||
local enc2 = ngx.var["http_accept_encoding"]
|
||
if enc2 ~= acceptEncoding then
|
||
error("http_accept_encoding via index mismatch")
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarEmptyAndNil 测试空值和 nil 处理
|
||
func TestNgxVarEmptyAndNil(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("GET")
|
||
req.Header.SetRequestURI("/")
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
err = coro.Execute(`
|
||
-- 未设置的参数应该返回空字符串或 nil
|
||
local empty = ngx.var.arg_nonexistent
|
||
-- arg_ 对不存在的参数通常返回空字符串
|
||
|
||
-- 自定义变量设为空字符串
|
||
ngx.var.empty_string = ""
|
||
local val = ngx.var.empty_string
|
||
if val ~= "" then
|
||
error("empty_string should be empty")
|
||
end
|
||
|
||
-- 覆盖为空值
|
||
ngx.var.test = "value"
|
||
ngx.var.test = nil -- Lua 的 nil 在 __newindex 中会被转换
|
||
-- 实现中 nil 会被转换为空字符串
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|
||
|
||
// TestNgxVarRequestBodyAccess 测试请求体相关变量
|
||
func TestNgxVarRequestBodyAccess(t *testing.T) {
|
||
var req fasthttp.Request
|
||
req.Header.SetMethod("POST")
|
||
req.Header.SetRequestURI("/upload")
|
||
req.Header.SetContentType("application/octet-stream")
|
||
req.SetBody([]byte("test body content"))
|
||
|
||
ctx := &fasthttp.RequestCtx{}
|
||
ctx.Init(&req, nil, nil)
|
||
|
||
engine, err := NewEngine(DefaultConfig())
|
||
require.NoError(t, err)
|
||
defer engine.Close()
|
||
|
||
coro, err := engine.NewCoroutine(ctx)
|
||
require.NoError(t, err)
|
||
defer coro.Close()
|
||
|
||
err = coro.SetupSandbox()
|
||
require.NoError(t, err)
|
||
|
||
err = coro.Execute(`
|
||
-- 测试请求长度
|
||
local length = ngx.var.request_length
|
||
if type(length) ~= "number" then
|
||
error("request_length should be a number")
|
||
end
|
||
|
||
-- 测试内容类型
|
||
local contentType = ngx.var.http_content_type
|
||
if contentType ~= "application/octet-stream" then
|
||
error("content_type mismatch")
|
||
end
|
||
`)
|
||
assert.NoError(t, err)
|
||
}
|