{"id":21660030,"url":"https://github.com/jollytoad/deno_http_fns","last_synced_at":"2025-10-14T22:18:13.287Z","repository":{"id":153049267,"uuid":"621395689","full_name":"jollytoad/deno_http_fns","owner":"jollytoad","description":"A bunch of functions for building HTTP servers","archived":false,"fork":false,"pushed_at":"2025-02-18T15:28:08.000Z","size":464,"stargazers_count":21,"open_issues_count":5,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-18T16:21:47.644Z","etag":null,"topics":["deno","functions","http","http-server","javascript","server","typescript","utility-library"],"latest_commit_sha":null,"homepage":"https://jsr.io/@http","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/jollytoad.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-30T15:18:49.000Z","updated_at":"2025-02-18T15:27:17.000Z","dependencies_parsed_at":"2024-07-25T12:06:18.514Z","dependency_job_id":"debe96f0-2182-4b0e-a1fc-acf59e05bed2","html_url":"https://github.com/jollytoad/deno_http_fns","commit_stats":null,"previous_names":[],"tags_count":54,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jollytoad%2Fdeno_http_fns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jollytoad%2Fdeno_http_fns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jollytoad%2Fdeno_http_fns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jollytoad%2Fdeno_http_fns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jollytoad","download_url":"https://codeload.github.com/jollytoad/deno_http_fns/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244141434,"owners_count":20404836,"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","functions","http","http-server","javascript","server","typescript","utility-library"],"created_at":"2024-11-25T09:32:04.193Z","updated_at":"2025-10-14T22:18:13.231Z","avatar_url":"https://github.com/jollytoad.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# HTTP Functions for Deno (and other runtimes)\n\nThis is a collection of functions to aid building of a HTTP service in Deno, or\nother JS runtimes.\n\nThey can be used instead of a monolithic router framework, or in tandem with\none.\n\n## The bullet points\n\n- A library of composable functions rather than a monolithic router class\n- Based on web standard [Request] =\u003e [Response] functions, aka\n  [Fetch handlers](https://blog.val.town/blog/the-api-we-forgot-to-name/)\n- Works with [`Deno.serve`][deno_serve]\n- Routing based on various criteria\n  - URLPattern\n  - Method\n  - Media Type\n- Request and Response helper functions\n- Generate router module from filesystem based handlers\n  - Static or dynamic imports\n  - Build time or runtime discovery\n- Request/Response interceptor function chains\n  - Logging\n  - CORS\n- `Deno.serve` options helper fns for various hosting scenarios\n  - Development on localhost (including https support)\n  - Deno Deploy\n\n[Request]: https://developer.mozilla.org/en-US/docs/Web/API/Request\n[Response]: https://developer.mozilla.org/en-US/docs/Web/API/Response\n[deno_serve]: https://deno.land/api?s=Deno.serve\n\n## An Example\n\nLet's start with a really simple example, a router for `GET /hello`...\n\n```ts\nimport { handle } from \"@http/route/handle\";\nimport { byPattern } from \"@http/route/by_pattern\";\nimport { byMethod } from \"@http/route/by_method\";\n\nDeno.serve(handle([\n  byPattern(\n    \"/hello\",\n    byMethod({\n      GET: () =\u003e {\n        return new Response(\"Hello world\");\n      },\n    }),\n  ),\n]));\n```\n\nAs you can see this is a fairly difference approach to the routers you may be\nused to.\n\nThe main idea is to compose your router from simple `Request` =\u003e `Response`\nfunctions.\n\nLet's take a look at each part of the example, starting with `byPattern` (we'll\ncome back to `handle` later):\n\n```ts\nbyPattern(\n  \"/hello\",\n  ...\n)\n```\n\nThis function actually creates a handler function, which attempts to match the\nrequest URL against the given pattern, and if it matches calls the handler given\nin its 2nd arg, in this case...\n\n```ts\nbyMethod({\n  GET: ...\n})\n```\n\nAgain this creates another handler function, which attempts to match the request\nHTTP method against a key in the given record of method =\u003e handlers. If it\nmatches the HTTP method, the associated handler is called...\n\n\u003c!-- deno-fmt-ignore-start --\u003e\n```ts\n() =\u003e {\n  return new Response(\"Hello world\");\n}\n```\n\u003c!-- deno-fmt-ignore-end --\u003e\n\nSo, this will be the handler function for `GET /hello`, the function is passed\nthe `Request` and returns a `Response`.\n\nBut what if the user hits `GET /other`, and `byPattern` doesn't match the\npattern?\n\nWell the function can return `null` to indicate that this request cannot be\nhandled, and this is where `handle` comes in. It can take an array of handlers,\nand try each one until a non-null response is returned, and if no response comes\na fallback handler is invoked. By default returning a `404 Not Found`, but a\ndifferent fallback function can be supplied where necessary.\n\nAlthough `handle` itself is just a convenience function for a common combination\nof `cascade` and `withFallback` functions, which can be used independently for a\nmore flexible approach. See below for the full documentation of these.\n\nYou can read more about the concepts in the [blog], although it may not remain\ntotally up to date with the state of this library.\n\n[blog]: https://jollytoad.deno.dev/blog/http_fns\n\n## Common handler concepts\n\n### Response or null\n\nAlthough based on `Request` =\u003e `Response` functions, there is a little more to\nit than that, for example, many functions produced by the `by*` helpers may also\nreturn `null` instead of a `Response`, and where a regular handler is required\nthe `withFallback` function can be used to catch the `null` and return a\nconcrete `Response`. The `Response` or `null` may also be as a promise.\n\n### Additional arguments\n\nAlso, many handlers may also accept additional arguments beyond the first\n`Request`, for example, in the case of `byPatten(pattern, handler)`, the\n`handler` is given the request and the pattern match result as arguments...\n\n```ts\n((request: Request, match: URLPatternResult) =\u003e Awaitable\u003cResponse | null\u003e);\n```\n\n### Argument shunting\n\nMost of the `by*` helpers will pass arguments on as is, or shunt the arguments\nalong if they want to introduce their own, so for example,\n`byPattern(pattern, handler)` returns a handler with the type:\n\n```ts\n(request: Request, ...additionalArgs: SomeArgsType) =\u003e ...\n```\n\nbut the actual `handler` you pass to it is actually...\n\n```ts\n(request: Request, match: URLPatternResult, ...additionalArgs: SomeArgsType) =\u003e ...\n```\n\nIt has the extra `match` argument insert before all other arguments that are\njust passed along.\n\nThis allows the handlers created via `by*` helpers to work with a wide variety\nof other frameworks, as it's totally agnostic to the extra arguments beyond the\n`Request`. So when you use these functions with `Deno.serve` for example, your\npattern handler function will actually have the signature:\n\n```ts\n(request: Request, match: URLPatternResult, info: Deno.ServeHandlerInfo) =\u003e ...\n```\n\nSo you still have this extra context available to you in your handler.\n\n## Take a look inside\n\nThis is just a library of functions, and these are kept as simple a possible\nwith the intention that it is easy to take a look inside of each function and\nsee exactly what it does, the documentation below links to the source of each\nfunction and an example of it's usage, and I encourage you follow these and take\na good look at the code.\n\nAlso, in general each module represents a single function, intended to be\nimported individually, so you only import exactly what you need, not a mountain\nof unused features. You'll find no `mod.ts` or `deps.ts` around here.\n\n## Examples\n\nThere are many [examples](./packages/examples) that can be executed directly,\nand many tests for these examples.\n\nYou can run them after cloning this repo, for example:\n\n```sh\ndeno task example packages/examples/logging.ts\n```\n\nor directly from jsr:\n\n```sh\ndeno run -A jsr:@http/examples/logging\n```\n\nMany of the examples have accompanying tests, which I hope to improve coverage\nof as time permits. I'd encourage you to take a look at the tests to see how\neach example can be exercised. You can also run the whole test suite simply\nwith:\n\n```sh\ndeno task test\n```\n\n## Functions\n\n- Routing\n  - [Criteria](./docs/routing_criteria.md)\n    - `byPattern`\n    - `bySubPattern`\n    - `byMethod`\n    - `byMediaType`\n  - [Delegation](./docs/routing_delegation.md)\n    - `handle`\n    - `cascade`\n    - `withFallback`\n    - `lazy`\n  - [Handlers](./docs/handlers.md)\n    - `staticRoute`\n  - [Filesystem](./docs/routing_filesystem.md)\n    - `discoverRoutes`\n    - `dynamicRoute`\n    - `generateRoutesModule`\n    - Fresh compatibility (_TODO_)\n- [Interceptors](./docs/interceptors.md)\n  - `intercept`\n  - `interceptResponse`\n  - `skip`\n  - `byStatus`\n  - `logging`\n  - `cors`\n- Utilities\n  - [Request](./docs/request_utils.md)\n  - [Response](./docs/response_utils.md)\n- Hosting (_TODO_)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjollytoad%2Fdeno_http_fns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjollytoad%2Fdeno_http_fns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjollytoad%2Fdeno_http_fns/lists"}