add http utils

This commit is contained in:
Sky Johnson 2025-03-22 22:27:58 -05:00
parent 780533bd76
commit 0259d1a135
3 changed files with 115 additions and 75 deletions

View File

@ -170,27 +170,33 @@ func writeResponse(w http.ResponseWriter, result any, log *logger.Logger) {
return
}
switch res := result.(type) {
case string:
// String result
w.Header().Set("Content-Type", contentTypePlain)
w.Write([]byte(res))
// Check for HTTPResponse type
if httpResp, ok := result.(*runner.HTTPResponse); ok {
// Set response headers
for name, value := range httpResp.Headers {
w.Header().Set(name, value)
}
case map[string]any, []any:
// Table or array result - convert to JSON
w.Header().Set("Content-Type", contentTypeJSON)
data, err := json.Marshal(res)
if err != nil {
log.Error("Failed to marshal response: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
// Set status code
w.WriteHeader(httpResp.Status)
// Process the body based on its type
if httpResp.Body == nil {
return
}
w.Write(data)
result = httpResp.Body // Set result to body for processing below
}
switch res := result.(type) {
case string:
// String result - plain text
setContentTypeIfMissing(w, contentTypePlain)
w.Write([]byte(res))
default:
// Other result types - convert to JSON
w.Header().Set("Content-Type", contentTypeJSON)
data, err := json.Marshal(result)
// All other types - convert to JSON
setContentTypeIfMissing(w, contentTypeJSON)
data, err := json.Marshal(res)
if err != nil {
log.Error("Failed to marshal response: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
@ -199,3 +205,9 @@ func writeResponse(w http.ResponseWriter, result any, log *logger.Logger) {
w.Write(data)
}
}
func setContentTypeIfMissing(w http.ResponseWriter, contentType string) {
if w.Header().Get("Content-Type") == "" {
w.Header().Set("Content-Type", contentType)
}
}

View File

@ -103,18 +103,25 @@ func NewRunner(options ...RunnerOption) (*LuaRunner, error) {
return nil, ErrInitFailed
}
// Initialize HTTP module BEFORE sandbox setup
httpInit := HTTPModuleInitFunc()
if err := httpInit(state); err != nil {
state.Close()
return nil, ErrInitFailed
}
// Set up sandbox AFTER HTTP module is initialized
if err := runner.sandbox.Setup(state); err != nil {
state.Close()
return nil, ErrInitFailed
}
// Preload all modules into package.loaded
if err := runner.moduleLoader.PreloadAllModules(state); err != nil {
state.Close()
return nil, errors.New("failed to preload modules")
}
// Set up sandbox
if err := runner.sandbox.Setup(state); err != nil {
state.Close()
return nil, ErrInitFailed
}
// Run init function if provided
if runner.initFunc != nil {
if err := runner.initFunc(state); err != nil {

View File

@ -12,10 +12,12 @@ type Sandbox struct {
// NewSandbox creates a new sandbox
func NewSandbox() *Sandbox {
return &Sandbox{
s := &Sandbox{
modules: make(map[string]any),
initialized: false,
}
return s
}
// AddModule adds a module to the sandbox environment
@ -78,6 +80,9 @@ func (s *Sandbox) Setup(state *luajit.State) error {
preload = package.preload
}
-- Add HTTP module explicitly to the base environment
base.http = http
-- Add registered custom modules
if __sandbox_modules then
for name, mod in pairs(__sandbox_modules) do
@ -90,6 +95,9 @@ func (s *Sandbox) Setup(state *luajit.State) error {
__env_system.initialized = true
end
-- Global variable for tracking current environment
__last_env = nil
-- Fast environment creation with pre-allocation
function __get_sandbox_env(ctx)
local env
@ -101,6 +109,8 @@ func (s *Sandbox) Setup(state *luajit.State) error {
-- Clear any previous context
env.ctx = ctx or nil
-- Clear any previous response
env._response = nil
else
-- Create new environment with metatable inheritance
env = setmetatable({}, {
@ -118,6 +128,9 @@ func (s *Sandbox) Setup(state *luajit.State) error {
end
end
-- Store reference to current environment
__last_env = env
return env
end
@ -127,6 +140,7 @@ func (s *Sandbox) Setup(state *luajit.State) error {
if __env_system.pool_size < __env_system.max_pool_size then
-- Clear context reference to avoid memory leaks
env.ctx = nil
-- Don't clear response data - we need it for extraction
-- Add to pool
table.insert(__env_system.env_pool, env)
@ -239,7 +253,14 @@ func (s *Sandbox) Execute(state *luajit.State, bytecode []byte, ctx map[string]a
// Get result
result, err := state.ToValue(-1)
state.Pop(1)
state.Pop(1) // Pop result
// Check if HTTP response was set
httpResponse, hasHTTPResponse := GetHTTPResponse(state)
if hasHTTPResponse {
httpResponse.Body = result
return httpResponse, err
}
return result, err
}