Using route parameters
Most adapters natively support route parameters (also called parametric path or path parameters) such as /hello/:name
. @universal-middleware/core
provides the params
helper to universally retrieve those.
We recommend to follow this next example when using route parameters:
ts
import type { UniversalHandler } from "@universal-middleware/core";
import { params } from "@universal-middleware/core";
interface RouteParamOption {
route?: string;
}
const handler = ((options?) => (request, _context, runtime) => {
const myParams = params(request, runtime, options?.route);
if (myParams === null || !myParams.name) {
// Provide a useful error message to the user
throw new Error(
"A route parameter named `:name` is required. " +
"You can set your server route as `/user/:name`, or use the `route` option of this middleware " +
"to achieve the same purpose.",
);
}
return new Response(`User name is: ${myParams.name}`);
}) satisfies (options?: RouteParamOption) => UniversalHandler;
export default handler;
NOTE
For servers supporting route parameters (app.get("/user/:name", myHandler())
), the parameters are available under runtime.params
.
For other adapters (app.get("/user/*", myHandler({ route: "/user/:name" }))
), the 3rd argument of params
helper must be present and not undefined. Then parameters are extracted with regexparam.
After bundling and publishing this middleware, one can then use this middleware as follows:
ts
import { Hono } from "hono";
import paramHandler from "@universal-middleware-examples/tool/params-handler-hono";
const app = new Hono();
app.get("/user/:name", paramHandler());
export default app;
ts
import { createApp, createRouter } from "h3";
import paramHandler from "@universal-middleware-examples/tool/params-handler-h3";
import { universalOnBeforeResponse } from "@universal-middleware/h3";
const app = createApp({
// /!\ This is required for universal-middleware to operate properly
onBeforeResponse: universalOnBeforeResponse,
});
const router = createRouter();
router.get("/user/:name", paramHandler());
app.use(router);
export default app;
ts
import { createRouter } from "@hattip/router";
import paramHandler from "@universal-middleware-examples/tool/params-handler-hattip";
const app = createRouter();
app.get("/user/:name", paramHandler());
const hattipHandler = app.buildHandler();
export default hattipHandler;
ts
import paramsHandler from "@universal-middleware-examples/tool/params-handler";
import { createHandler } from "@universal-middleware/cloudflare";
import { pipe } from "@universal-middleware/core";
const paramsHandlerInstance = paramsHandler({
// Mandatory when targeting Cloudflare Worker
route: "/user/:name",
});
// Cloudflare Workers have no native routing support.
// We recommend using Hono as it fully supports Cloudflare Worker.
const wrapped = pipe(
(request, ctx, runtime) => {
const url = new URL(request.url);
// intercept `/user/*` routes with this handler
if (url.pathname.startsWith("/user/")) {
return paramsHandlerInstance(request, ctx, runtime);
}
},
// Other handlers
);
export default createHandler(() => wrapped)();
ts
// functions/user/[name].ts
import paramHandler from "@universal-middleware-examples/tool/params-handler-cloudflare-pages";
export const onRequest = paramHandler();
ts
import paramHandler from "@universal-middleware-examples/tool/params-handler-express";
import express from "express";
const app = express();
app.get("/user/:name", paramHandler());
export default app;
ts
import paramHandler from "@universal-middleware-examples/tool/params-handler-fastify";
import fastify from "fastify";
const app = fastify();
app.get("/user/:name", paramHandler());
export default app;
ts
import paramHandler from "@universal-middleware-examples/tool/params-handler-elysia";
import Elysia from "elysia";
const app = new Elysia().get("/user/:name", paramHandler());
export default app;