lua

package
v0.0.0-...-6c608c1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

README

Lua Services Package

This package provides Lua services for use with the LuaDataSource. These services expose Go functionality to Lua scripts in a safe and controlled manner.

Available Services

HTTP Service

The HTTP service provides HTTP client functionality to Lua scripts.

Functions
  • http.get(url, [headers]) - Make a GET request

    • Returns: {status=int, body=string, headers=table} or (nil, error)
  • http.post(url, body, [headers]) - Make a POST request

    • Returns: {status=int, body=string, headers=table} or (nil, error)
  • http.request(method, url, [body], [headers]) - Make a generic HTTP request

    • Returns: {status=int, body=string, headers=table} or (nil, error)
Example
-- Simple GET request
local response = http.get("https://api.example.com/data")
if response.status == 200 then
  print("Success: " .. response.body)
end

-- GET with headers
local headers = {["Authorization"] = "Bearer token123"}
local response = http.get("https://api.example.com/protected", headers)

-- POST with JSON body
local body = json.encode({key = "value"})
local headers = {["Content-Type"] = "application/json"}
local response = http.post("https://api.example.com/create", body, headers)

-- Generic request
local response = http.request("PUT", "https://api.example.com/update", body, headers)
JSON Service

The JSON service provides JSON encoding and decoding functionality.

Functions
  • json.encode(value) - Encode a Lua value to JSON string

    • Returns: json_string or (nil, error)
  • json.decode(json_string) - Decode a JSON string to a Lua value

    • Returns: value or (nil, error)
Example
-- Encode to JSON
local obj = {
  name = "Alice",
  age = 30,
  roles = {"admin", "user"}
}
local jsonStr = json.encode(obj)
-- Result: '{"name":"Alice","age":30,"roles":["admin","user"]}'

-- Decode from JSON
local data = json.decode('{"key":"value","num":42}')
print(data.key)  -- "value"
print(data.num)  -- 42

-- Round-trip
local original = {test = "data"}
local encoded = json.encode(original)
local decoded = json.decode(encoded)
Config Service

The Config service provides access to configuration values passed to the LuaDataSource.

Functions
  • config.get(key, [default]) - Get a configuration value

    • Returns: value or default if not found
  • config.has(key) - Check if a configuration key exists

    • Returns: bool
  • config.keys() - Get all configuration keys

    • Returns: table (array of strings)
Example
-- Get config values
local apiKey = config.get("api_key")
local timeout = config.get("timeout", 30)  -- with default

-- Check if key exists
if config.has("feature_flag") then
  -- use the feature
end

-- List all keys
local keys = config.keys()
for i, key in ipairs(keys) do
  print(key .. " = " .. tostring(config.get(key)))
end

Type Conversions

Go to Lua
  • stringlua.LString
  • int, int64, float64lua.LNumber
  • boollua.LBool
  • map[string]interface{} → Lua table (object)
  • []interface{} → Lua table (array)
  • nillua.LNil
Lua to Go
  • lua.LStringstring
  • lua.LNumberfloat64
  • lua.LBoolbool
  • Lua table (with integer keys 1..N) → []interface{}
  • Lua table (with string keys) → map[string]interface{}
  • lua.LNilnil

Thread Safety

Each service instance can be registered to multiple Lua states. However, Lua states themselves are not thread-safe. The LuaDataSource creates a new Lua state for each request, ensuring thread safety.

Configuration

HTTP Service
// Simple usage with a pre-configured HTTP client (must not be nil)
client := &http.Client{Timeout: 30 * time.Second}
httpService, err := lua.NewHTTPService(ctx, client)

// With request options (per-request hooks applied before sending)
httpService, err := lua.NewHTTPService(ctx, client,
    lua.WithRequestOptions(func(req *http.Request) error {
        req.Header.Set("X-Tenant-ID", tenantFromContext(ctx))
        return nil
    }),
)
Request Options

The RequestOptions function allows you to modify HTTP requests before they are sent. This is useful for:

  • Adding authentication headers
  • Modifying URLs (e.g., adding query parameters)
  • Setting custom headers
  • Implementing request signing

Example: Adding Authentication

requestOptions := func(req *http.Request) error {
    req.Header.Set("Authorization", "Bearer secret-token")
    return nil
}

Example: Adding Query Parameters

requestOptions := func(req *http.Request) error {
    q := req.URL.Query()
    q.Add("api_key", "secret")
    q.Add("tenant", "acme-corp")
    req.URL.RawQuery = q.Encode()
    return nil
}
Config Service

The Config Service uses a ConfigSource interface to retrieve configuration values:

// Simple in-memory configuration
configSource := lua.NewMapConfigSource(map[string]interface{}{
    "api_key": "secret",
    "timeout": 60,
    "enabled": true,
})
configService := lua.NewConfigService(configSource)
Custom Config Sources

You can implement your own ConfigSource to back configuration with environment variables, files, remote services, etc:

type ConfigSource interface {
    // Get retrieves a configuration value by key
    // Returns the value and true if found, or nil and false if not found
    Get(key string) (interface{}, bool)
    
    // Keys returns all available configuration keys
    Keys() []string
}

Example: Environment Variable Config Source

type EnvConfigSource struct{}

func (e *EnvConfigSource) Get(key string) (interface{}, bool) {
    val, ok := os.LookupEnv(key)
    return val, ok
}

func (e *EnvConfigSource) Keys() []string {
    // Return all env var names
    return []string{} // implementation depends on needs
}

configService := lua.NewConfigService(&EnvConfigSource{})
JSON Service
jsonService := lua.NewJSONService()  // no configuration needed

Error Handling

Services follow Lua's convention of returning (result, error) tuples:

local result, err = http.get("https://example.com")
if result == nil then
  print("Error: " .. err)
else
  print("Success: " .. result.body)
end

Security Considerations

  1. HTTP Timeout: The HTTP service has a configurable timeout to prevent long-running requests
  2. No File System Access: Services don't provide file system access
  3. Sandboxed Execution: Each Lua script runs in its own isolated state
  4. No Subprocess Execution: Services don't allow executing system commands

Best Practices

  1. Handle Errors: Always check for errors when calling service functions
  2. Use Timeouts: Configure appropriate HTTP timeouts for your use case
  3. Validate Inputs: Validate data before encoding to JSON or making HTTP requests
  4. Cache Config: Store frequently accessed config values in local variables
  5. Clean JSON: Use json.encode/decode for reliable serialization

Example: Complete LuaDataSource Script

function fetch(input)
  -- Get configuration
  local apiEndpoint = config.get("api_endpoint")
  local apiKey = config.get("api_key")
  
  -- Access input data
  local subject = input.subject.subject
  
  -- Make HTTP request
  local headers = {
    ["Authorization"] = "Bearer " .. apiKey,
    ["Content-Type"] = "application/json"
  }
  
  local response = http.get(apiEndpoint .. "/user/" .. subject, headers)
  
  if response.status ~= 200 then
    return nil  -- Data source has nothing to contribute
  end
  
  -- Parse and enhance response
  local userData = json.decode(response.body)
  userData.fetched_at = os.time()
  
  -- Return result
  return {
    data = json.encode(userData),
    content_type = "application/json"
  }
end

function fetch_cache_key(input)
  -- Only cache based on subject
  return {
    subject = {
      subject = input.subject.subject
    }
  }
end

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CompileScript

func CompileScript(source string, name string) (*lua.FunctionProto, error)

CompileScript parses and compiles a Lua script to bytecode. The returned lua.FunctionProto is immutable and safe to share across goroutines and LState instances.

func GoToLua

func GoToLua(L *lua.LState, value any) lua.LValue

GoToLua converts a Go value to a Lua value

func LoadProto

func LoadProto(L *lua.LState, proto *lua.FunctionProto) error

LoadProto loads a pre-compiled lua.FunctionProto into an LState and executes its top-level chunk, which typically defines global functions.

func LuaToGo

func LuaToGo(lv lua.LValue) interface{}

LuaToGo converts a Lua value to a Go value

func ValidateFunction

func ValidateFunction(proto *lua.FunctionProto, functionName string) error

ValidateFunction loads a pre-compiled script into a temporary LState and verifies that executing it defines a global function with the given name.

Types

type ConfigService

type ConfigService struct {
	// contains filtered or unexported fields
}

ConfigService provides access to configuration values in Lua scripts

func NewConfigService

func NewConfigService(source ConfigSource) *ConfigService

NewConfigService creates a new config service with the given configuration source

func (*ConfigService) Register

func (s *ConfigService) Register(L *lua.LState)

Register adds the config service to the Lua state Usage in Lua:

local value = config.get("key")
local value = config.get("key", "default_value")
local exists = config.has("key")

type ConfigSource

type ConfigSource interface {
	// Get retrieves a configuration value by key
	// Returns the value and true if found, or nil and false if not found
	Get(key string) (any, bool)

	// Keys returns all available configuration keys
	Keys() []string
}

ConfigSource is an interface for retrieving configuration values Implementations can back this with environment variables, config files, etc.

func NewMapConfigSource

func NewMapConfigSource(values map[string]any) ConfigSource

NewMapConfigSource creates a ConfigSource backed by a map

type HTTPService

type HTTPService struct {
	// contains filtered or unexported fields
}

HTTPService provides HTTP client functionality to Lua scripts.

func NewHTTPService

func NewHTTPService(ctx context.Context, client *http.Client, opts ...HTTPServiceOption) (*HTTPService, error)

NewHTTPService creates a new HTTP service. ctx is required and propagated to every outgoing request, enabling cancellation, tracing, and request-ID propagation. client is the fully-configured HTTP client (auth, timeout, transport already set) and must not be nil. Optional settings are provided via HTTPServiceOption.

func (*HTTPService) Register

func (s *HTTPService) Register(L *lua.LState)

Register adds the HTTP service to the Lua state Usage in Lua:

local response = http.get("https://api.example.com/data")
local response = http.post("https://api.example.com/data", "request body", {["Content-Type"] = "application/json"})

type HTTPServiceOption

type HTTPServiceOption func(*httpServiceConfig)

HTTPServiceOption configures optional settings for NewHTTPService.

func WithRequestOptions

func WithRequestOptions(ro RequestOptions) HTTPServiceOption

WithRequestOptions sets a function that processes requests before sending.

type JSONService

type JSONService struct{}

JSONService provides JSON encoding/decoding functionality to Lua scripts

func NewJSONService

func NewJSONService() *JSONService

NewJSONService creates a new JSON service

func (*JSONService) Register

func (s *JSONService) Register(L *lua.LState)

Register adds the JSON service to the Lua state Usage in Lua:

local obj = json.decode('{"key": "value"}')
local str = json.encode({key = "value"})

type MapConfigSource

type MapConfigSource struct {
	// contains filtered or unexported fields
}

MapConfigSource is a simple in-memory implementation of ConfigSource

func (*MapConfigSource) Get

func (m *MapConfigSource) Get(key string) (any, bool)

Get retrieves a value from the map

func (*MapConfigSource) Keys

func (m *MapConfigSource) Keys() []string

Keys returns all keys in the map

type RequestOptions

type RequestOptions func(*http.Request) error

RequestOptions is a function that can modify a request before it is sent. This can be used to add authentication headers, modify URLs, etc.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL