Request data at a glance
Every handler receives a ctx (context) object. .params give you route parameters. For raw request data, use the req global.
app:get("/search", function(ctx)
return {
query = req.query.q, -- ?q=hello
method = req.method, -- "GET"
auth_header = req.headers["authorization"] -- Bearer token
}
end)
Reading query parameters
-- /search?q=lua&page=2&category=tutorial
app:get("/search", function(ctx)
local q = req.query.q -- "lua"
local page = req.query.page -- "2"
-- req.get is the same as req.query
return api.dataset.find("articles", {
filter = { title = { like = "%" .. q .. "%" } }
})
end)
Reading form data (POST)
-- Form: <input name="email"> <input name="password">
app:post("/login", function(ctx)
local email = req.post.email
local password = req.post.password
local user = api.users.login(email, password)
if not user then
ctx:flash("error", "Invalid credentials")
return ctx:redirect("/login")
end
return ctx:redirect("/dashboard")
end)
Reading JSON body
Enable the "json" middleware, then use ctx.body:
app:use("json")
app:post("/api/users", function(ctx)
-- ctx.body is now a Lua table (parsed JSON)
local name = ctx.body.name
local email = ctx.body.email
return api.users.create({ username = name, email = email, password = "temp" })
end)
Reading raw body
app:post("/webhook", function(ctx)
local raw = req.body -- raw string
local signature = req.headers["x-signature"]
-- verify signature...
end, { csrf = false })
Request headers
All header names are lowercased and use hyphens:
req.headers["content-type"] -- ✓ correct
req.headers["Content-Type"] -- ✗ wrong (not lowercased)
req.headers["content_type"] -- ✗ wrong (underscore)
File uploads
app:post("/upload", function(ctx)
local file = req.files.photo
if file then
-- file.name, file.size, file.type, file.tmp_name
api.files.upload({ file = file })
end
end)
Reading cookies
app:get("/preferences", function(ctx)
local theme = req.cookie.theme or "light"
return { theme = theme }
end)
Session data
Session is read-only. Access user state via env.is_user instead:
if env.is_user then
local me = api.users.me()
return { user = me }
end
Environment info
app:get("/info", function(ctx)
return {
site = env.sitename, -- your site name
site_id = env.siteid, -- numeric ID
ip = env.remote_ip, -- visitor IP
is_admin = env.is_admin, -- true/false
timezone = env.timezone -- server timezone
}
end)
Next: Responses — send data back to the browser.