Requests
Handling Incoming Requests
Every handler in Jazzy receives a Context object, which provides simple ways to access incoming data from the client.
Request Input
Unified Access: input()
The input() helper simplifies data retrieval by checking both query string parameters and JSON bodies automatically.
proc search(ctx: Context) {.async.} = # Works for /search?q=query OR {"q": "query"} let query = ctx.input("q")
# With a default value let page = ctx.input("page", "1")
ctx.text("Searching for: " & query & " (Page " & page & ")")Route Parameters: param()
For dynamic routes (e.g., Route.get("/users/:id", ...)), use the param() helper to retrieve values from the URL path.
proc showUser(ctx: Context) {.async.} = let id = ctx.param("id") ctx.text("Viewing user with ID: " & id)Type-Safe Body Parsing: bodyAs()
If you want to parse the entire request body into a typed object, use bodyAs. This is ideal for structured API payloads.
type UserDto = object username: string age: int
proc create(ctx: Context) {.async.} = let dto = ctx.bodyAs(UserDto) # dto.username and dto.age are now typed values! echo dto.usernameHeaders and IP
Accessing Request Headers
You can access raw request headers directly from the ctx.request.headers table.
proc debugHeaders(ctx: Context) {.async.} = if ctx.request.headers.hasKey("User-Agent"): let ua = ctx.request.headers["User-Agent"] ctx.text("Your browser is: " & ua)Client IP: ip()
Retrieves the client’s IP address. It automatically detects and respects the X-Forwarded-For or X-Real-IP headers if TRUST_PROXY=true is set in your .env.
proc checkIp(ctx: Context) {.async.} = let ipAddress = ctx.ip() ctx.text("Your IP is: " & ipAddress)File Uploads
Jazzy makes handling multi-part file uploads simple. Use the file() helper to retrieve uploaded files.
proc upload(ctx: Context) {.async.} = let myFile = ctx.file("avatar")
if myFile.filename.len > 0: # myFile.filename: "photo.jpg" # myFile.contentType: "image/jpeg" # myFile.content: "raw file bytes..."
# Save the file writeFile("uploads/" & myFile.filename, myFile.content) ctx.text("File uploaded successfully!") else: ctx.status(400).text("No file uploaded.")