Kynetra FX

Documentation

Responses

Kynetra FX handlers return a standard Response. The ctx object provides convenience helpers for the most common cases — json, text, html, redirect, stream, and response — but you can always return a raw new Response().

JSON#

ctx.json(data, init?) serialises any value to JSON, sets Content-Type: application/json, and returns a Response.

app.ts
app.get('/users', (ctx) => {
return ctx.json([{ id: '1', name: 'Alice' }])
})
 
// With a custom status code
app.post('/users', async (ctx) => {
const body = await ctx.jsonBody()
return ctx.json({ created: true, ...body }, { status: 201 })
})

Text#

ctx.text(s, init?) returns a plain-text response with Content-Type: text/plain;charset=UTF-8.

app.ts
app.get('/health', (ctx) => ctx.text('ok'))
 
app.get('/ping', (ctx) => ctx.text('pong', { status: 200 }))

HTML#

ctx.html(s, init?) returns an HTML response with Content-Type: text/html;charset=UTF-8.

app.ts
app.get('/', (ctx) =>
ctx.html('<html><body><h1>Hello</h1></body></html>')
)
 
// Useful with a template function
function template(title: string, body: string) {
return '<html><head><title>' + title + '</title></head><body>' + body + '</body></html>'
}
 
app.get('/about', (ctx) =>
ctx.html(template('About', '<p>About us</p>'))
)

Redirects#

ctx.redirect(url, status?) returns a redirect response. The default status is 302 (Found). Pass 301 for a permanent redirect.

app.ts
app.get('/old-path', (ctx) =>
ctx.redirect('/new-path') // 302 temporary
)
 
app.get('/legacy', (ctx) =>
ctx.redirect('https://new.example.com', 301) // 301 permanent
)

Streaming#

ctx.stream(body, init?) wraps a ReadableStream in a Response. Use it for server-sent events, large file transfers, or any progressively-generated content.

app.ts
app.get('/events', (ctx) => {
const { readable, writable } = new TransformStream()
const writer = writable.getWriter()
const encoder = new TextEncoder()
 
// Write data asynchronously
;(async () => {
for (let i = 0; i < 5; i++) {
await writer.write(encoder.encode('data: ' + i + '
 
'))
await new Promise(r => setTimeout(r, 500))
}
await writer.close()
})()
 
return ctx.stream(readable, {
headers: { 'Content-Type': 'text/event-stream' },
})
})

Raw response#

ctx.response(body?, init?) constructs a raw Response with full control. Equivalent to new Response(body, init) but consistent with the ctx API.

app.ts
app.get('/no-content', (ctx) =>
ctx.response(null, { status: 204 })
)
 
app.get('/binary', async (ctx) => {
const bytes = new Uint8Array([0x89, 0x50, 0x4e, 0x47])
return ctx.response(bytes, {
headers: { 'Content-Type': 'image/png' },
})
})

Returning a native Response#

You can return a plain new Response() from any handler. Kynetra FX will pass it through as-is. This is useful when integrating with other libraries that already return a Response.

app.ts
app.get('/pass-through', async (ctx) => {
// Fetch from an upstream API and return its response directly
return fetch('https://api.upstream.com/data')
})

Setting status codes#

Pass a status in the init object to any helper, or use ctx.status(code) which is chainable:

app.ts
// Via init option
app.post('/items', async (ctx) => {
return ctx.json({ created: true }, { status: 201 })
})
 
// Via chainable ctx.status()
app.delete('/items/:id', (ctx) => {
// delete logic...
return ctx.status(204).response()
})

Setting response headers#

ctx.set(name, value) sets a response header. ctx.append(name, value) appends to an existing header. Both must be called before returning the response.

app.ts
app.get('/cached', (ctx) => {
ctx.set('Cache-Control', 'public, max-age=3600')
ctx.set('X-Custom-Header', 'hello')
return ctx.json({ data: 'cacheable' })
})
 
// Append to an existing header (e.g. Vary)
app.use(async (ctx, next) => {
const res = await next()
ctx.append('Vary', 'Accept-Encoding')
return res
})

Note

ctx.set() and ctx.append() set response headers. To read request headers, use ctx.header(name).

Response helper reference#

NameTypeDescription
json(data, init?)ResponseSerialize data to JSON with Content-Type: application/json.
text(s, init?)ResponseReturn a plain-text response.
html(s, init?)ResponseReturn an HTML response.
redirect(url, status?)ResponseRedirect to url. Defaults to 302.
stream(body, init?)ResponseReturn a streaming response from a ReadableStream.
response(body?, init?)ResponseConstruct a raw Response with full control.
status(code)ctxSet the default status code. Chainable — call before a response helper.
set(name, value)voidSet a response header. Call before returning.
append(name, value)voidAppend to a response header. Call before returning.