Minimal HTTP router library based on the
URLPattern API.
- API docs: See
@fartlabs/rton JSR →jsr.io/@fartlabs/rt
import { Router } from "@fartlabs/rt";
const router = new Router()
.get("/", () => new Response("Hello, World!"))
.default(() => new Response("Not found", { status: 404 }));
Deno.serve((request) => router.fetch(request));Handle common HTTP verbs (GET, POST, PUT, DELETE) on resourceful routes.
import { Router } from "@fartlabs/rt";
const router = new Router()
.get("/users", () => new Response("List users"))
.post("/users", async ({ request }) => {
const body = await request.json();
return Response.json({ created: true, user: body });
})
.put("/users/:id", async ({ params, request }) => {
const id = params?.pathname.groups?.id;
const body = await request.json();
return Response.json({ updated: id, user: body });
})
.delete("/users/:id", ({ params }) => {
const id = params?.pathname.groups?.id;
return new Response(`Deleted ${id}`, { status: 204 });
})
.default(() => new Response("Not found", { status: 404 }));
Deno.serve((req) => router.fetch(req));Use URLPattern named parameters and a catch‑all wildcard for flexible matching.
const router = new Router()
// Named params are available via URLPattern groups
.get("/hello/:name", ({ params }) => {
const name = params?.pathname.groups?.name ?? "World";
return new Response(`Hello, ${name}!`);
})
// Wildcard catch-all
.get("/*", () => new Response("Catch-all"));Access query string values via new URL(request.url).searchParams.
const router = new Router().get("/search", ({ request }) => {
const { searchParams } = new URL(request.url);
const q = searchParams.get("q") ?? "";
return new Response(`You searched for: ${q}`);
});Add middleware that enriches a shared state object and delegates with next().
interface State {
user?: { name: string };
}
const router = new Router<State>()
// auth-like middleware that enriches state, then calls next()
.get("/*", async ({ state, next }) => {
state.user = { name: "Wazoo" };
return await next();
})
.get("/:name", ({ params, state }) => {
const name = params?.pathname.groups?.name;
if (state.user?.name !== name) {
return new Response("Forbidden", { status: 403 });
}
return new Response(`Hello, ${name}!`);
});Provide a custom 404 response and a centralized error handler for thrown errors.
const router = new Router()
.get("/boom", () => {
throw new Error("Kaboom");
})
.default(() => new Response("Custom 404", { status: 404 }))
.error((err) => new Response(`Oops: ${err.message}`, { status: 500 }));Compose routers by mounting one router's routes into another.
const api = new Router().get("/v1/ping", () => new Response("pong"));
const router = new Router().use(api);1. Install Deno.
2. Start a new Deno project.
deno init3. Add rt as a project dependency.
deno add jsr:@fartlabs/rtRun tests:
deno testType-check the project:
deno task checkIf you prefer composing routers in JSX, check out RTX: a library of JSX
components that build @fartlabs/rt routers.
- GitHub:
github.com/FartLabs/rtx - JSR docs:
jsr.io/@fartlabs/rtx
We appreciate your help!
Run deno fmt to format the code.
Run deno lint to lint the code.
This project is licensed under the WTFPL. See LICENSE for
details.
Developed with ❤️ @FartLabs