Security
CSRF Protection
Manual verification:
new Bolt() {
port = 3000
enableCsrf("csrf-secret-key")
# Form with CSRF token
@get("/form", func {
token = $bolt.csrfToken()
html = '<form method="POST" action="/submit">
<input type="hidden" name="_csrf" value="' + token + '">
<input type="text" name="data">
<button>Submit</button>
</form>'
$bolt.send(html)
})
# Verify CSRF on submit
@post("/submit", func {
token = $bolt.formField("_csrf")
if !$bolt.verifyCsrf(token)
$bolt.forbidden()
return
ok
# Process form...
$bolt.send("Success!")
})
}Automatic verification (all POST/PUT/DELETE/PATCH requests checked automatically):
new Bolt() {
port = 3000
enableCsrf("csrf-secret-key")
csrfAutoVerify()
@get("/csrf-token", func {
$bolt.json([:csrf_token = $bolt.csrfToken()])
})
@post("/submit", func {
# CSRF already verified by auto-verify
$bolt.send("Success!")
})
}Rate Limiting
new Bolt() {
port = 3000
# Per-IP: 100 requests per minute per client IP
$bolt.rateLimit(100, 60)
@before(func {
if !$bolt.checkRateLimit()
$bolt.setHeader("Retry-After", "60")
$bolt.sendWithStatus(429, "Too many requests")
ok
})
@get("/api/data", func {
$bolt.json([:data = "..."])
})
# Per-route rate limiting
@post("/api/login", func {
# Login logic...
})
routeRateLimit(5, 60) # 5 attempts per minute
}IP Filtering
new Bolt() {
port = 3000
# Allow only specific IPs
ipWhitelist("192.168.1.0/24") # Local network
ipWhitelist("10.0.0.5") # Specific IP
# Block bad actors
ipBlacklist("1.2.3.4")
ipBlacklist("5.6.7.0/24")
# Routes...
}HTTPS/TLS
new Bolt() {
port = 443
# Enable TLS
enableTls("./certs/server.crt", "./certs/server.key")
# Force HTTPS redirect
@before(func {
if $bolt.header("X-Forwarded-Proto") = "http"
$bolt.redirectPermanent("https://" + $bolt.header("Host") + $bolt.path())
ok
})
# Routes...
}Force Secure Cookies Behind a Proxy
When running behind a TLS-terminating proxy (e.g., nginx, Cloudflare), the server doesn’t see TLS directly. Use forceSecureCookies() to ensure session cookies get the Secure flag and use the __Host- prefix:
new Bolt() {
forceSecureCookies()
# Routes...
}