Middleware
Middleware allows you to modify a Response before it's sent to the client.
One example of this is adding CORS headers to all responses.
Warning
You need to make middleware take one argument, either request: Request or response: Response.
Response middleware
Example
Tip
Middleware is called in the order it's added to the router. This means that if you add middleware to the router, and then add middleware to a route, the route's middleware will be called first.
Another usecase is setting default headers for all responses:
Example
function addDefaultHeaders(response: Response): Response {
const defaultHeaders = {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
"Accept-Charset": "utf-8",
};
// Remove content-type if it's text/plain, as that's the default
if (res.headers.get("content-type") === "text/plain;charset=UTF-8") {
res.headers.delete("content-type");
}
for (const [key, value] of Object.entries(defaultHeaders)) {
if (!res.headers.has(key)) {
res.headers.set(key, value);
}
}
return response;
}
router
.use(addDefaultHeaders)
.get("/", my_handler) // my_handler will return a response with the default headers all set
Request middleware
Middleware can also be used to modify the request before it's passed to the handler. This is useful for things like authentication, where you want to check the request before it's passed to the handler.
To do this, use router.use with request: Request:
Tip
Throwing a ClientError in middleware will return a json response with the error message and status code.
Example
import { ClientError, JoyRouter } from "joyrouter";
const router = new JoyRouter();
function checkAuth(request: Request): Request {
if (!request.headers.has("Authorization")) {
throw new router.ClientError("Unauthorized", 400);
}
return request;
}
router
.use(checkAuth)
.get("/", my_handler) // my_handler will only be called if the request has an Authorization header
export default {
async fetch(request: Request) {
return await router.handle(req);
},
};
Middleware categories
Categories can be assigned to functions, using the @category decorator.
See this page for more information.
Tip
By setting the middleware category to error, you can make it so that the middleware is only run when an error is thrown.
(Also technically if @category error is set on a jsdoc route, but that's weird, don't do that!)
They can then be used to only run middleware for certain categories:
Example
function myAccount() {
`
@category account
`;
return new Response("This is my account!", { status: 200 });
}
function helloWorld() {
return new Response("Hello world!", { status: 200 });
}
router
.use(checkAuth, "account") // Only run this middleware for routes with the "account" category
.get("/account", myAccount) // myAccount will only be called if the request has an Authorization header
.get("/", helloWorld) // helloWorld will be called for all requests