187 lines
4.6 KiB
Go
187 lines
4.6 KiB
Go
package runner
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
|
|
)
|
|
|
|
// extractCookie grabs cookies from the Lua state
|
|
func extractCookie(state *luajit.State) *http.Cookie {
|
|
cookie := &http.Cookie{
|
|
Path: "/", // Default path
|
|
}
|
|
|
|
// Get name
|
|
state.GetField(-1, "name")
|
|
if !state.IsString(-1) {
|
|
state.Pop(1)
|
|
return nil // Name is required
|
|
}
|
|
cookie.Name = state.ToString(-1)
|
|
state.Pop(1)
|
|
|
|
// Get value
|
|
state.GetField(-1, "value")
|
|
if state.IsString(-1) {
|
|
cookie.Value = state.ToString(-1)
|
|
}
|
|
state.Pop(1)
|
|
|
|
// Get path
|
|
state.GetField(-1, "path")
|
|
if state.IsString(-1) {
|
|
cookie.Path = state.ToString(-1)
|
|
}
|
|
state.Pop(1)
|
|
|
|
// Get domain
|
|
state.GetField(-1, "domain")
|
|
if state.IsString(-1) {
|
|
cookie.Domain = state.ToString(-1)
|
|
}
|
|
state.Pop(1)
|
|
|
|
// Get expires
|
|
state.GetField(-1, "expires")
|
|
if state.IsNumber(-1) {
|
|
expiry := int64(state.ToNumber(-1))
|
|
cookie.Expires = time.Unix(expiry, 0)
|
|
}
|
|
state.Pop(1)
|
|
|
|
// Get max age
|
|
state.GetField(-1, "max_age")
|
|
if state.IsNumber(-1) {
|
|
cookie.MaxAge = int(state.ToNumber(-1))
|
|
}
|
|
state.Pop(1)
|
|
|
|
// Get secure
|
|
state.GetField(-1, "secure")
|
|
if state.IsBoolean(-1) {
|
|
cookie.Secure = state.ToBoolean(-1)
|
|
}
|
|
state.Pop(1)
|
|
|
|
// Get http only
|
|
state.GetField(-1, "http_only")
|
|
if state.IsBoolean(-1) {
|
|
cookie.HttpOnly = state.ToBoolean(-1)
|
|
}
|
|
state.Pop(1)
|
|
|
|
return cookie
|
|
}
|
|
|
|
// LuaCookieModule provides cookie functionality to Lua scripts
|
|
const LuaCookieModule = `
|
|
-- Cookie module implementation
|
|
local cookie = {
|
|
-- Set a cookie
|
|
set = function(name, value, options, ...)
|
|
if type(name) ~= "string" then
|
|
error("cookie.set: name must be a string", 2)
|
|
end
|
|
|
|
-- Get or create response
|
|
local resp = __http_responses[1] or {}
|
|
resp.cookies = resp.cookies or {}
|
|
__http_responses[1] = resp
|
|
|
|
-- Handle options as table or legacy params
|
|
local opts = {}
|
|
if type(options) == "table" then
|
|
opts = options
|
|
elseif options ~= nil then
|
|
-- Legacy support: options is actually 'expires'
|
|
opts.expires = options
|
|
-- Check for other legacy params (4th-7th args)
|
|
local args = {...}
|
|
if args[1] then opts.path = args[1] end
|
|
if args[2] then opts.domain = args[2] end
|
|
if args[3] then opts.secure = args[3] end
|
|
if args[4] ~= nil then opts.http_only = args[4] end
|
|
end
|
|
|
|
-- Create cookie table
|
|
local cookie = {
|
|
name = name,
|
|
value = value or "",
|
|
path = opts.path or "/",
|
|
domain = opts.domain
|
|
}
|
|
|
|
-- Handle expiry
|
|
if opts.expires then
|
|
if type(opts.expires) == "number" then
|
|
if opts.expires > 0 then
|
|
cookie.max_age = opts.expires
|
|
local now = os.time()
|
|
cookie.expires = now + opts.expires
|
|
elseif opts.expires < 0 then
|
|
cookie.expires = 1
|
|
cookie.max_age = 0
|
|
else
|
|
-- opts.expires == 0: Session cookie
|
|
-- Do nothing (omitting both expires and max-age creates a session cookie)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Security flags
|
|
cookie.secure = (opts.secure ~= false)
|
|
cookie.http_only = (opts.http_only ~= false)
|
|
|
|
-- Store in cookies table
|
|
local n = #resp.cookies + 1
|
|
resp.cookies[n] = cookie
|
|
|
|
return true
|
|
end,
|
|
|
|
-- Get a cookie value
|
|
get = function(name)
|
|
if type(name) ~= "string" then
|
|
error("cookie.get: name must be a string", 2)
|
|
end
|
|
|
|
-- Access values directly from current environment
|
|
local env = getfenv(2)
|
|
|
|
-- Check if context exists and has cookies
|
|
if env.ctx and env.ctx.cookies and env.ctx.cookies[name] then
|
|
return tostring(env.ctx.cookies[name])
|
|
end
|
|
|
|
return nil
|
|
end,
|
|
|
|
-- Remove a cookie
|
|
remove = function(name, path, domain)
|
|
if type(name) ~= "string" then
|
|
error("cookie.remove: name must be a string", 2)
|
|
end
|
|
|
|
-- Create an expired cookie
|
|
return cookie.set(name, "", {expires = 0, path = path or "/", domain = domain})
|
|
end
|
|
}
|
|
|
|
-- Install cookie module
|
|
_G.cookie = cookie
|
|
|
|
-- Make sure the cookie module is accessible in sandbox
|
|
if __env_system and __env_system.base_env then
|
|
__env_system.base_env.cookie = cookie
|
|
end
|
|
`
|
|
|
|
// CookieModuleInitFunc returns an initializer for the cookie module
|
|
func CookieModuleInitFunc() StateInitFunc {
|
|
return func(state *luajit.State) error {
|
|
return state.DoString(LuaCookieModule)
|
|
}
|
|
}
|