package runner import ( "sync" "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" ) // Context represents execution context for a Lua script type Context struct { // Values stores any context values (route params, HTTP request info, etc.) Values map[string]any // FastHTTP context if this was created from an HTTP request RequestCtx *fasthttp.RequestCtx // Buffer for efficient string operations buffer *bytebufferpool.ByteBuffer } // Context pool to reduce allocations var contextPool = sync.Pool{ New: func() any { return &Context{ Values: make(map[string]any, 32), } }, } // NewContext creates a new context, potentially reusing one from the pool func NewContext() *Context { return contextPool.Get().(*Context) } // NewHTTPContext creates a new context from a fasthttp RequestCtx func NewHTTPContext(requestCtx *fasthttp.RequestCtx) *Context { ctx := NewContext() ctx.RequestCtx = requestCtx // Extract common HTTP values that Lua might need if requestCtx != nil { ctx.Values["_request_method"] = string(requestCtx.Method()) ctx.Values["_request_path"] = string(requestCtx.Path()) ctx.Values["_request_url"] = string(requestCtx.RequestURI()) // Extract cookies cookies := make(map[string]any) requestCtx.Request.Header.VisitAllCookie(func(key, value []byte) { cookies[string(key)] = string(value) }) ctx.Values["_request_cookies"] = cookies // Extract query params query := make(map[string]any) requestCtx.QueryArgs().VisitAll(func(key, value []byte) { query[string(key)] = string(value) }) ctx.Values["_request_query"] = query // Extract form data if present if requestCtx.IsPost() || requestCtx.IsPut() { form := make(map[string]any) requestCtx.PostArgs().VisitAll(func(key, value []byte) { form[string(key)] = string(value) }) ctx.Values["_request_form"] = form } // Extract headers headers := make(map[string]any) requestCtx.Request.Header.VisitAll(func(key, value []byte) { headers[string(key)] = string(value) }) ctx.Values["_request_headers"] = headers } return ctx } // Release returns the context to the pool after clearing its values func (c *Context) Release() { // Clear all values to prevent data leakage for k := range c.Values { delete(c.Values, k) } // Reset request context c.RequestCtx = nil // Return buffer to pool if we have one if c.buffer != nil { bytebufferpool.Put(c.buffer) c.buffer = nil } contextPool.Put(c) } // GetBuffer returns a byte buffer for efficient string operations func (c *Context) GetBuffer() *bytebufferpool.ByteBuffer { if c.buffer == nil { c.buffer = bytebufferpool.Get() } return c.buffer } // Set adds a value to the context func (c *Context) Set(key string, value any) { c.Values[key] = value } // Get retrieves a value from the context func (c *Context) Get(key string) any { return c.Values[key] }