Routing
Adding Routes
H3 app instance has a built in router system to register routes matching patterns with parameter or specific HTTP method.
Example: Register a route to match requests to the /hello
endpoint with HTTP GET method:
// Method 1: using app.[method]
app.get("/hello", () => "Hello world!");
// Method 2: using app.on(method)
app.on("GET", "/hello", () => "Hello world!");
You can register multiple event handlers for the same route with different methods:
app
.get("/hello", () => "GET Hello world!")
.post("/hello", () => "POST Hello world!");
You can also use app.all
method to register a route accepting any HTTP method:
app.all("/hello", (event) => `This is a ${event.req.method} request!`);
Route Params
You can define parameters in your routes using :
prefix:
app.get("/hello/:name", (event) => {
return `Hello ${event.context.params.name}!`;
});
In this example, the name
parameter will be available in the event.context.params
object.
If you send a request to /hello/world
, the event handler will respond Hello world!
.
Instead of named params, you can use *
for unnamed and optional params:
app.get("/hello/*", (event) => `Hello!`);
Catch-all param
Adding /hello/:name
route will match /hello/world
or /hello/123
. But it will not match /hello/foo/bar
.
If you need to match multiple levels of sub routes, you can use **
prefix:
app.get("/hello/**", (event) => `Hello ${event.context.params._}!`);
This will match /hello
, /hello/world
, /hello/123
, /hello/world/123
, etc.
_
will store the full wildcard content as a single string.Adding Middleware
You can register middleware handlers to app instance using the app.use
.
Example: Register global middleware that calls on every route.
app.use((event) => {
console.log(event);
});
Example: Register routed middleware that matches GET
requests for specific routes starting with the prefix /blog
(i.e. /blog/
, /blog/world
, /blog/123
, etc.).
app.use(
(event) => {
console.log(event);
},
{ route: "/blog/**", method: "GET" },
);
You can define multiple middleware.
app.use(() => "First");
app.use(() => "Second");
In the example above, the first event handler will be called for every request and the second one will never be called.
However, if you do not return a response from the first event handler, the second one will be called. This is useful to have a middleware pattern.
app.use((event) => {
console.log("First");
});
app.use((event) => {
console.log("Second");
});
If all handlers get called and no response is returned, h3 will continue with the main router handlers.
You can also register middleware with next
argument to intercept return values of next middleware or handlers:
app.use(async (event, next) => {
const rawResponse = await next();
// [intercept response]
return rawResponse;
});
You can also register middleware that match certain requires:
app.use(
(event, next) => {
console.log("[alert] POST request on /blog paths!");
},
{
method: "POST",
route: "/blog/**",
// match: (event) => event.req.method === "POST", // Same as method: "POST"
},
);
When adding routes, you can register middleware to run with them:
app.get("/admin", (event) => {}, [auth]);