// Package lua 提供 Lua 脚本嵌入能力 package lua import ( "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/valyala/fasthttp" ) func TestLocationManagerRegister(t *testing.T) { manager := NewLocationManager() require.NotNil(t, manager) // 注册 location handler := func(ctx *fasthttp.RequestCtx) { ctx.WriteString("test response") } manager.Register("/test", handler) // 验证注册成功 manager.mu.Lock() _, ok := manager.handlers["/test"] manager.mu.Unlock() assert.True(t, ok) } func TestLocationManagerCapture(t *testing.T) { manager := NewLocationManager() // 注册 location handler := func(ctx *fasthttp.RequestCtx) { ctx.SetStatusCode(200) ctx.SetBodyString("hello from subrequest") ctx.Response.Header.Set("X-Custom", "value") } manager.Register("/api/sub", handler) // 创建父请求上下文 parentCtx := &fasthttp.RequestCtx{} parentCtx.Request.SetRequestURI("/parent") // 执行子请求 result, err := manager.Capture(parentCtx, "/api/sub", nil) require.NoError(t, err) require.NotNil(t, result) assert.Equal(t, 200, result.Status) assert.Equal(t, "hello from subrequest", string(result.Body)) assert.Equal(t, "value", result.Headers["X-Custom"]) } func TestLocationManagerCaptureNotFound(t *testing.T) { manager := NewLocationManager() parentCtx := &fasthttp.RequestCtx{} // 执行不存在的 location result, err := manager.Capture(parentCtx, "/notexist", nil) require.NoError(t, err) require.NotNil(t, result) assert.Equal(t, 404, result.Status) } func TestLocationManagerCaptureWithOptions(t *testing.T) { manager := NewLocationManager() // 注册 location handler := func(ctx *fasthttp.RequestCtx) { ctx.SetStatusCode(200) ctx.WriteString("method: " + string(ctx.Method()) + ", body: " + string(ctx.PostBody())) } manager.Register("/echo", handler) parentCtx := &fasthttp.RequestCtx{} parentCtx.Request.SetRequestURI("/parent") // 使用自定义选项 opts := map[string]any{ "method": "POST", "body": "test body", } result, err := manager.Capture(parentCtx, "/echo", opts) require.NoError(t, err) require.NotNil(t, result) assert.Equal(t, 200, result.Status) assert.Contains(t, string(result.Body), "method: POST") assert.Contains(t, string(result.Body), "body: test body") } func TestLocationLuaAPI(t *testing.T) { engine, err := NewEngine(DefaultConfig()) require.NoError(t, err) defer engine.Close() L := engine.GetLStateForTest() defer engine.PutLStateForTest(L) // 注册 ngx.location API ngx := L.NewTable() L.SetGlobal("ngx", ngx) RegisterLocationAPI(L, engine.LocationManager(), ngx) // 测试 ngx.location.capture err = L.DoString(` -- 创建模拟的 location 结果 local result = ngx.location.capture("/test") -- 验证结果结构 assert(result ~= nil) assert(result.status ~= nil) assert(result.body ~= nil) `) require.NoError(t, err) } // TestLocationCaptureWithParentRequest 测试子请求能够访问父请求数据 func TestLocationCaptureWithParentRequest(t *testing.T) { engine, err := NewEngine(DefaultConfig()) require.NoError(t, err) defer engine.Close() // 注册 location handler,它会检查父请求的头信息 engine.LocationManager().Register("/api/sub", func(ctx *fasthttp.RequestCtx) { // 检查是否继承了父请求的头 parentHeader := ctx.Request.Header.Peek("X-Parent-Header") ctx.SetStatusCode(200) ctx.SetBodyString("parent_header: " + string(parentHeader)) }) // 创建父请求上下文 parentCtx := &fasthttp.RequestCtx{} parentCtx.Request.SetRequestURI("/parent") parentCtx.Request.Header.Set("X-Parent-Header", "header_value") // 使用 Capture 进行子请求 result, err := engine.LocationManager().Capture(parentCtx, "/api/sub", nil) require.NoError(t, err) require.NotNil(t, result) // 验证子请求能够访问父请求数据(Headers 被继承) assert.Equal(t, 200, result.Status) assert.Contains(t, string(result.Body), "parent_header: header_value") }