{"id":18827494,"url":"https://github.com/rclarey/rtr","last_synced_at":"2026-01-22T02:30:17.011Z","repository":{"id":59312442,"uuid":"536574069","full_name":"rclarey/rtr","owner":"rclarey","description":"A fast HTTP router and type-safe middleware library for Fetch compliant runtimes","archived":false,"fork":false,"pushed_at":"2023-05-25T01:31:41.000Z","size":18,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-31T13:02:51.418Z","etag":null,"topics":["deno","http","middleware","router"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rclarey.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-09-14T12:47:24.000Z","updated_at":"2024-06-20T05:23:03.000Z","dependencies_parsed_at":"2022-09-16T00:41:19.563Z","dependency_job_id":null,"html_url":"https://github.com/rclarey/rtr","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rclarey%2Frtr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rclarey%2Frtr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rclarey%2Frtr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rclarey%2Frtr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rclarey","download_url":"https://codeload.github.com/rclarey/rtr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239763653,"owners_count":19692812,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deno","http","middleware","router"],"created_at":"2024-11-08T01:16:37.201Z","updated_at":"2025-02-20T02:13:26.791Z","avatar_url":"https://github.com/rclarey.png","language":"TypeScript","readme":"# rtr\n\nA fast HTTP router and type-safe middleware library for [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) compliant runtimes.\n\n## Usage\nThese examples below use Deno, but they could be easily adapted for runtimes that support `Request`/`Response`\n(many edge runtimes, Bun, etc.)\n\n### Handlers\n\n```typescript\n// a handler is a function that takes a request and context, and returns a response\ntype Handler\u003cT extends object\u003e = (\n  request: Request,\n  context: T,\n) =\u003e Response | Promise\u003cResponse\u003e;\n\nconst greeting: Handler\u003c{ name: string }\u003e = (req, ctx) =\u003e {\n  return new Response(`Hello ${ctx.name}!`);\n}\n\nconst asyncHandler: Handler\u003c{ userid: string }\u003e = async (req, ctx) =\u003e {\n  const user = await findById(ctx.userid);\n  return new Response(`Hello ${user.name}!`);\n}\n```\n\n### Routing\n```typescript\nimport { serve } from \"https://deno.land/std/http/server.ts\";\nimport { Handler, Router, ParamsCtx } from \"https://deno.land/x/rtr/mod.ts\";\n\nconst router = new Router();\n\n// you can use parameters in the path\nrouter.get(\"/user/:userid\", async (req: Request, ctx: ParamsCtx) =\u003e {\n  // access the path parameters with the `params` field of the context\n  const user = await findById(ctx.params.userid);\n  return new Response(JSON.stringify(user));\n});\n\n// of course paths can have multiple parameters\nrouter.delete(\"/user/:userid/todos/:todoId\", async (req: Request, ctx: ParamsCtx) =\u003e {\n  await deleteTodo(ctx.params.userId, ctx.params.todoId);\n  return new Response('OK');\n})\n\n// wildcards are supported at the end of a path\nrouter.get(\"/static/*\", (req: Request) =\u003e {\n  return serveFile(new URL(req.url).pathname);\n})\n\n// there are default implementations for 404, 405, and 500 error handling\n// but they can be overridden for custom functionality\nrouter.notFound = () =\u003e new Response(\"You must be lost\", { status: 404 });\nrouter.methodNotAllowed = () =\u003e new Response(\"That isn't allowed\", { status: 405 });\nrouter.internalServerError = () =\u003e new Response(\"Oops I messed up\", { status: 500 });\n\n// router.handler is a `Handler\u003cobject\u003e` that routes the request to the paths bound above\nserve(router.handler);\n```\n\n### Middleware\n```typescript\n// a middleware is a function that takes a handler and returns another handler\ntype Middleware\u003c\n  Requires extends object = object,\n  Provides extends object = object,\n\u003e = \u003cT extends object\u003e(\n  h: Handler\u003cT \u0026 Requires \u0026 Provides\u003e,\n) =\u003e Handler\u003cT \u0026 Requires\u003e;\n\n// a logging middleware that requires a user object in context\nconst log: Middleware\u003c{ user: { id: string } }\u003e = (h) =\u003e async (r, c) =\u003e {\n  const id = c.user.id;\n  const res = await h(r, c);\n  console.log(`${r.method} ${r.url} ${id}`);\n  return res;\n};\n\n// an authorization middleware that provides a user object in context\nconst auth: Middleware\u003c{}, { user: { id: string } }\u003e = (h) =\u003e async (r, c) =\u003e {\n  const user = await validate(r.headers.get(\"Authorization\"));\n  if (!user) {\n    return new Response(\"Unauthorized\", { status: 401 });\n  }\n  return h(r, { ...c, user });\n};\n\n// you can compose middleware\nconst middleware = composeMiddleware(auth, log);\n// which is the same as\nconst middleware = (h) =\u003e auth(log(h));\n\n// and then apply the middleware to handlers\nrouter.get('/asdf', middleware((_, ctx) =\u003e new Response('asdf: ' + ctx.user.id)));\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frclarey%2Frtr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frclarey%2Frtr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frclarey%2Frtr/lists"}