Skip to Content

Routes

Routes are the basic building blocks of Kaito. They represent a single HTTP route with a optional input schemas (body, query) and execution logic.

Creating a Route

Creating a route requires a router. If you have not set one up yet, check out the getting started guide.

Here’s an extremely basic example of a ping/pong route.

const app = router.get('/ping', async () => 'pong');
You must either return something JSON serializable, a Response object, or throw an error

Request/Response model

Understanding how Kaito handles requests and responses is crucial, so let’s cover that first.

For each incoming request, Kaito creates two important objects:

  1. A KaitoRequest object - This is a thin wrapper around the standard Request object, providing a similar API

  2. A KaitoHead object - This is a wrapper around a Headers object and a status code. It’s used so the router knows what changes you might have made to the status code or headers.

And then the router handles requests very similarly to the following:

const kaitoRequest = new KaitoRequest(url, reqFromServer); // url is a `URL` instance, reqFromServer is a `Request` instance const kaitoHead = new KaitoHead(); const context = await getContext(kaitoRequest, kaitoHead); const result = await route(context); if (result instanceof Response) { return result; } // Create the final response object using the // headers and status code from the kaitoHead object const response = Response.json(result, { status: kaitoHead.status(), // status will always default to 200 headers: kaitoHead.headers, }); return response;

So to summarise

  • Check if you returned a Response instance, and if so, return that
  • Otherwise get the headers and status code from the KaitoHead object
  • Automatically set Content-Type: application/json if you return a JSON-serializable value
  • Use these to build the final response

Ultimately the important thing to understand here is that if you return a Response instance directly, Kaito will use that as-is and ignore any changes made to the KaitoHead object. This gives you full control when needed, but means you need to set all headers and status codes on the Response object itself.

Input

Routes can take a query and body schema using Kaito’s built-in schema system. Internally, Kaito will validate all request bodies and query params so you can be absolutely certain you are processing the right data.

Query schemas should always expect strings as input, because query params are always strings. If you need them as numbers, parse them in your route handler.

import {k} from '@kaito-http/core'; const app = router.post('/echo', { query: { skip: k.string(), take: k.string(), }, body: k.number(), async run({body, query}) { const skip = parseInt(query.skip); const take = parseInt(query.take); // Echo it back return {body, skip, take}; }, });

The schema system supports all JSON types — strings, numbers, booleans, null, arrays, objects, unions, literals, you name it.

Last updated on