Skip to content

Context

Every route handler in Hedystia receives a context object (ctx) as its first argument. The shape of the context is fully inferred from the route schema.

Context Properties

req

The raw Request object from the Fetch API.

ts
app
.
get
('/info', ({
req
}) => {
const
ua
=
req
.
headers
.
get
('user-agent')
return {
userAgent
:
ua
}
})

params

Path parameters, automatically extracted from the URL and validated against the params schema.

ts
app
.
get
(
'/posts/:id', ({
params
}) => {
return {
id
:
params
.
id
}
}, {
params
:
h
.
object
({
id
:
h
.
number
().
coerce
() }),
} )

query

Query string parameters, validated against the query schema.

ts
app
.
get
(
'/search', ({
query
}) => {
return {
term
:
query
.
q
}
}, {
query
:
h
.
object
({
q
:
h
.
string
() }),
} )

body

The request body, parsed and validated against the body schema. Available on POST, PUT, PATCH, and DELETE routes.

ts
app
.
post
(
'/users', ({
body
}) => {
return {
created
:
body
.
name
}
}, {
body
:
h
.
object
({
name
:
h
.
string
() }),
} )

headers

Request headers, validated against the headers schema if provided. Otherwise, raw headers are available.

ts
app
.
get
(
'/me', ({
headers
}) => {
return {
token
:
headers
.
authorization
}
}, {
headers
:
h
.
object
({
authorization
:
h
.
string
() }),
} )

rawHeaders

The unvalidated raw headers object, always available regardless of schema.

typescript
app.get('/debug', ({ rawHeaders }) => {
  return { headers: rawHeaders }
})

error

A helper function to throw a typed HTTP error. Calling ctx.error() immediately terminates the request.

ts
app
.
get
(
'/users/:id', ({
params
,
error
}) => {
if (
params
.
id
=== 0) {
error
(404, 'User not found')
} return {
id
:
params
.
id
}
}, {
params
:
h
.
object
({
id
:
h
.
number
().
coerce
() }),
} )

The thrown error is caught by the framework and returned as a JSON response:

Response
{
  "message": "User not found",
  "code": 404
}

set

The response context — lets you set status codes, headers, and cookies without constructing a full Response object.

ts
app
.
get
('/redirect', ({
set
}) => {
set
.
status
(302)
set
.
headers
.
set
('Location', 'https://example.com')
return null })

set.status(code)

Sets the HTTP status code.

set.headers.set(key, value)

Sets a response header.

set.headers.add(key, value)

Appends to an existing header (comma-separated).

set.headers.delete(key)

Removes a response header.

set.cookies.set(name, value, options?)

Sets a cookie.

ts
app
.
post
('/login', ({
set
}) => {
set
.
cookies
.
set
('session', 'token-value', {
httpOnly
: true,
secure
: true,
sameSite
: 'lax',
maxAge
: 60 * 60 * 24,
}) return {
ok
: true }
})

set.cookies.delete(name)

Deletes a cookie by setting its expiry to the past.

route

The matched route path string.

method

The HTTP method of the request.

publish

The publish function for WebSocket subscriptions. See Subscriptions.

Returning Responses

Handlers can return:

  • A plain object → serialized as JSON
  • A string → sent as text/plain
  • A Response object → returned as-is
  • A Uint8Array → sent as raw binary
  • A Blob → streamed to the client
  • A FormData → multipart response
typescript
// JSON (auto)
app.get('/json', () => ({ hello: 'world' }))

// Plain text
app.get('/text', () => 'Hello!')

// Custom Response
app.get('/custom', () =>
  new Response('Not Found', { status: 404 })
)