Guide

Routing


Adding Routes

H3 app instance has a built in router system to register routes matching patterns with parameter or specific HTTP method.

Router is powered by 🌳 rou3, an ultra fast and tiny route matcher engine.

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.

Param _ 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 specific routes only starting with the prefix /blog (i.e. /blog, /blog/world, /blog/123, etc.).

app.use("/blog/**", (event) => {
  console.log(event);
});
Running order of different kinds of middleware is different:
  • Global onRequest hook will be always called before
  • Global middleware registered without route pattern will always be called by the order of registration before any other handler.
  • Routed middleware with route pattern, will be called after global middleware by the order of less to the most specific pattern.
  • If no middleware handles response, normal router method matcher will be used.

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.