Context Object ​
The Context object wraps the native Request and provides convenient methods for accessing request data, setting response headers, and sending responses.
What is Context? ​
Context is a wrapper around Deno's native Request object. Instead of working with raw Request directly, you use Context which gives you:
- Lazy parsing - Data is parsed only when you access it
- Convenient methods - Simple APIs for common operations
- Response utilities - Built-in methods for sending responses
- Header management - Easy response header manipulation
Why Using Context? ​
Context avoids multiple parsing and repeated processing during the request lifecycle. The handler receives one Context object that persists through the entire lifecycle — from middleware to route handler.
Creating Context ​
Deserve creates Context automatically when requests arrive:
import type { Context } from '@neabyte/deserve'
export function GET(ctx: Context): Response {
return ctx.send.json({ message: 'Hello' })
}Context Structure ​
Context wraps several key pieces:
- Original Request - Access via
ctx.request - Parsed URL - Used internally for query params
- Route Parameters - Extracted from dynamic routes
- Response Headers - Set before sending response
Lazy Parsing ​
Context uses lazy parsing for performance:
export function GET(ctx: Context): Response {
// Query params aren't parsed yet
const query = ctx.query() // Parsed on first access
// Now cached, subsequent calls return cached value
const body = await ctx.body() // Parsed on first access
// Parsed based on Content-Type
return ctx.send.json({ query, body })
}Request Data Access ​
Access request data through Context methods:
- Query Parameters -
ctx.query(),ctx.queries() - Route Parameters -
ctx.param(),ctx.params() - Headers -
ctx.header(),ctx.headers - Cookies -
ctx.cookie() - Body -
ctx.body(),ctx.json(),ctx.formData(),ctx.text(),ctx.arrayBuffer(),ctx.blob() - URL Information -
ctx.url,ctx.pathname
Response Utilities ​
Send responses using ctx.send:
ctx.send.json()- JSON responsesctx.send.text()- Plain textctx.send.html()- HTML contentctx.send.file()- File downloadsctx.send.data()- In-memory data downloadsctx.send.redirect()- Redirectsctx.send.custom()- Custom responsesctx.handleError()- Error handling (unreleased)
You can also use ctx.redirect() directly as a convenience method:
export function GET(ctx: Context): Response {
return ctx.redirect('/new-location', 301)
// Equivalent to: ctx.send.redirect('/new-location', 301)
}Response Headers ​
Set response headers before sending:
export function GET(ctx: Context): Response {
ctx.setHeader('X-Custom', 'value')
ctx.setHeader('Cache-Control', 'no-cache')
return ctx.send.json({ data: 'test' })
}Setting Multiple Headers ​
Use setHeaders() to set multiple headers at once:
export function GET(ctx: Context): Response {
ctx.setHeaders({
'X-Custom': 'value',
'Cache-Control': 'no-cache',
'X-Request-ID': 'abc123'
})
return ctx.send.json({ data: 'test' })
}Reading Response Headers ​
Access all response headers that have been set:
export function GET(ctx: Context): Response {
ctx.setHeader('X-Custom', 'value')
ctx.setHeader('Cache-Control', 'no-cache')
const headers = ctx.responseHeadersMap // { 'X-Custom': 'value', 'Cache-Control': 'no-cache' }
return ctx.send.json({ data: 'test' })
}URL and Pathname ​
Get URL information directly:
ctx.url- Full URL stringctx.pathname- Pathname portion of URL (e.g.,/api/users/123)
export function GET(ctx: Context): Response {
const fullUrl = ctx.url // 'http://localhost:8000/api/users/123?sort=name'
const path = ctx.pathname // '/api/users/123'
return ctx.send.json({ path, fullUrl })
}Error Handling ​
WARNING
This feature is available in the development version but not yet released.
Handle errors consistently using ctx.handleError():
export function GET(ctx: Context): Response {
try {
if (!isAuthorized) {
return ctx.handleError(401, new Error('Unauthorized'))
}
return ctx.send.json({ data: 'success' })
} catch (error) {
return ctx.handleError(500, error as Error)
}
}How It Works ​
ctx.handleError() respects your global error handler set with router.catch():
- If
router.catch()is defined - Uses your custom error handler - If no error handler - Returns a simple response with the status code
Use in Middleware ​
Middleware can use ctx.handleError() to trigger error handling:
router.use(async (ctx, next) => {
if (!isValid) {
return ctx.handleError(401, new Error('Unauthorized'))
// This will use router.catch() if defined
}
return await next()
})Context Lifecycle ​
- Request arrives - Deserve creates Context with Request and URL
- Route matching - Route parameters extracted and added to Context
- Middleware execution - Context passed through middleware chain
- Route handler - Your handler receives Context
- Response sent - Context methods used to build Response