Context
Introduction
The context object is passed as the first parameter to a middleware function. It includes the HTTP request, the HTTP response, and any additional properties added by previous middleware calls.
Usage
import { type Context, Kernel } from "@raptor/kernel";
const app = new Kernel();
app.use((context: Context) => {
const { request, response } = context;
console.log(request, response);
return "Dinosaurs eat man. Woman inherits the earth";
});
app.serve();Request
Raptor uses the standard Web API Request object, giving you access to all its built-in properties and methods without any framework-specific wrappers.
app.use((context: Context) => {
const { request } = context;
console.log(request.method);
console.log(request.url);
console.log(request.headers);
return "Life, uh, finds a way";
});Common Request Operations
Reading Headers
app.use((context: Context) => {
const authToken = context.request.headers.get("Authorization");
const contentType = context.request.headers.get("Content-Type");
return { authToken, contentType };
});Parsing Request Body
app.use(async (context: Context) => {
// JSON body
const data = await context.request.json();
// Form data
const formData = await context.request.formData();
// Plain text
const text = await context.request.text();
return { received: data };
});Reading Query Parameters
app.use((context: Context) => {
const url = new URL(context.request.url);
const name = url.searchParams.get("name");
const page = url.searchParams.get("page") || "1";
return { name, page };
});Checking Request Method
import { MethodNotAllowed } from "@raptor/kernel";
app.use((context: Context) => {
if (context.request.method === "POST") {
// Handle POST request
}
if (context.request.method !== "GET") {
throw new MethodNotAllowed();
}
return "Clever Girl";
});Since Raptor doesn't wrap or modify the Request object, you can use any Web API features directly - no need to learn framework-specific methods.
Response
In Raptor, at least one middleware function is required to return a body response to ensure that the request cycle completes successfully. Raptor automatically handles response types through its response processor system. By default, it can process JSON objects, HTML strings, plain text, and raw Response objects. However, you can extend this system with your own custom processors.
Returning JSON
If the middleware response body is an object, it will be automatically recognized as application/json. Consequently, both the Content-Type header and the response body will be appropriately set to reflect this format.
app.use(() => ({
name: 'Dr Ian Malcolm',
}));Returning HTML
When a string is returned, the Content-Type header is automatically set to text/plain. However, if the string is detected to contain HTML, the Content-Type header will be automatically adjusted to text/html.
app.use(() => '<h1>Hello, Dr Malcolm!</h1>');Returning Response Directly
Raptor makes it easy to return simple scalar values as responses, but when you need full control over the output, you can also return a custom Response object directly.
app.use(() => new Response("We spared no expense", { status: 200 }));Overriding headers
Although it's convenient to return data without configuring a Content-Type, there may be instances where you need to specify a particular header. In such cases, you can proceed as follows:
app.use((context: Context) => {
context.response.headers.set("Content-Type", "application/hal+json");
return {
name: "That doesn't look very scary. More like a six-foot turkey."
}
});Extending
Response Processors
What are Response Processors?
The Response Manager handles converting your middleware return values into HTTP responses. There are four built-in processors out of the box, but you can add custom ones or override the defaults.
Built-in Processors
| Type | Handles | Content-Type |
|---|---|---|
response | Response objects | (preserved from original) |
error | Error instances | Based on request Accept header |
string | String values | text/plain or text/html |
object | Objects/Arrays | application/json |
Creating a custom processor
To create a custom processor, implement the Processor interface:
import type { Context, Processor, ResponseBodyType } from "@raptor/kernel";
export default class CustomStringProcessor implements Processor {
process(body: any, context: Context): Response {
return new Response("custom string processor: " + body, {
status: context.response.status,
headers: context.response.headers,
});
}
}Overriding an existing processor
To override an existing processor with your own, you can do the following:
import { type Context, Kernel, ResponseManager } from "@raptor/kernel";
import CustomStringProcessor from "./custom-string-processor.ts";
const app = new Kernel();
const manager = new ResponseManager();
manager.register("string", new CustomStringProcessor());
app.setResponseManager(manager);
app.use(() => "Hello, Dr Malcom!");
app.serve();
// custom string processor: Hello, Dr Malcolm!All strings which are returned from middleware will now use your custom processor.