package runner import ( luajit "git.sharkk.net/Sky/LuaJIT-to-Go" ) // HTTPResponse represents an HTTP response from Lua type HTTPResponse struct { Status int `json:"status"` Headers map[string]string `json:"headers"` Body any `json:"body"` } // NewHTTPResponse creates a default HTTP response func NewHTTPResponse() *HTTPResponse { return &HTTPResponse{ Status: 200, Headers: make(map[string]string), } } // LuaHTTPModule is the pure Lua implementation of the HTTP module const LuaHTTPModule = ` -- Table to store response data __http_responses = {} -- HTTP module implementation local http = { -- Set HTTP status code set_status = function(code) if type(code) ~= "number" then error("http.set_status: status code must be a number", 2) end local resp = __http_responses[1] or {} resp.status = code __http_responses[1] = resp end, -- Set HTTP header set_header = function(name, value) if type(name) ~= "string" or type(value) ~= "string" then error("http.set_header: name and value must be strings", 2) end local resp = __http_responses[1] or {} resp.headers = resp.headers or {} resp.headers[name] = value __http_responses[1] = resp end } -- Set content type; set_header helper http.set_content_type = function(content_type) http.set_header("Content-Type", content_type) end -- Install HTTP module _G.http = http -- Override sandbox executor to clear HTTP responses local old_execute_sandbox = __execute_sandbox __execute_sandbox = function(bytecode, ctx) -- Clear previous response for this thread __http_responses[1] = nil -- Execute the original function local result = old_execute_sandbox(bytecode, ctx) -- Return the result unchanged return result end -- Make sure the HTTP module is accessible in sandbox if __env_system and __env_system.base_env then __env_system.base_env.http = http end ` // HTTPModuleInitFunc returns an initializer function for the HTTP module func HTTPModuleInitFunc() StateInitFunc { return func(state *luajit.State) error { // Initialize pure Lua HTTP module return state.DoString(LuaHTTPModule) } } // GetHTTPResponse extracts the HTTP response from Lua state func GetHTTPResponse(state *luajit.State) (*HTTPResponse, bool) { response := NewHTTPResponse() // Get response table state.GetGlobal("__http_responses") if state.IsNil(-1) { state.Pop(1) return response, false } // Check for response at thread index state.PushNumber(1) state.GetTable(-2) if state.IsNil(-1) { state.Pop(2) return response, false } // Get status state.GetField(-1, "status") if state.IsNumber(-1) { response.Status = int(state.ToNumber(-1)) } state.Pop(1) // Get headers state.GetField(-1, "headers") if state.IsTable(-1) { // Iterate through headers table state.PushNil() // Start iteration for state.Next(-2) { // Stack has key at -2 and value at -1 if state.IsString(-2) && state.IsString(-1) { key := state.ToString(-2) value := state.ToString(-1) response.Headers[key] = value } state.Pop(1) // Pop value, leave key for next iteration } } state.Pop(1) // Clean up state.Pop(2) // Pop response table and __http_responses return response, true }