Guide
Middleware
Middleware runs before every handler. Return false to reject with a 403, return nothing to pass through.
Signature
app:Use(name, function(Player, Payload) → boolean?)
Global blocking
Runs on every request. Good for banning players or blocking suspended accounts.
app:Use("ban-check", function(Player, Payload)
if BanList[Player.UserId] then
return false -- 403 Forbidden
end
end)
Route-scoped guards
Check Payload.route to run logic only for a subset of routes.
app:Use("admin-guard", function(Player, Payload)
if Payload.route:match("^admin/") and not ADMINS[Player.UserId] then
return false
end
end)
Analytics / logging
No return value | passes through after recording.
app:Use("analytics", function(Player, Payload)
Analytics:Track({
userId = Player.UserId,
route = Payload.route,
method = Payload.method,
ts = os.time(),
})
end)
Middleware order
Middleware runs in registration order. Register guards before logging so rejected requests aren't tracked as successful.
app:Use("ban-check", banCheckFn) -- 1st
app:Use("admin-guard", adminGuardFn) -- 2nd
app:Use("analytics", analyticsFn) -- 3rd | only runs if not rejected
Return
false, not nil. Returning nil (or nothing) passes through. Only a literal false rejects.See also
App | app:Use() API ·
Authentication | full auth middleware with tokens ·
Admin Commands | route-scoped guard in practice ·
Tamper | built-in exploit detection