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');Response object, or throw an errorRequest/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:
-
A
KaitoRequestobject - This is a thin wrapper around the standardRequestobject, providing a similar API -
A
KaitoHeadobject - This is a wrapper around aHeadersobject 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
Responseinstance, and if so, return that - Otherwise get the headers and status code from the
KaitoHeadobject - Automatically set
Content-Type: application/jsonif 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.