{"id":19477071,"url":"https://github.com/swordjs/h3","last_synced_at":"2026-06-17T11:31:11.932Z","repository":{"id":113482748,"uuid":"483681688","full_name":"swordjs/h3","owner":"swordjs","description":null,"archived":false,"fork":false,"pushed_at":"2023-07-05T15:57:51.000Z","size":1683,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-25T16:30:59.421Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/swordjs.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":"2022-04-20T14:11:04.000Z","updated_at":"2022-04-20T14:11:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"3e33fb38-b16e-4cc4-9684-bd68310b0298","html_url":"https://github.com/swordjs/h3","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/swordjs/h3","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swordjs%2Fh3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swordjs%2Fh3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swordjs%2Fh3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swordjs%2Fh3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swordjs","download_url":"https://codeload.github.com/swordjs/h3/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swordjs%2Fh3/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34447264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-11-10T19:43:37.417Z","updated_at":"2026-06-17T11:31:11.907Z","avatar_url":"https://github.com/swordjs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# H3\n\n[![npm version][npm-version-src]][npm-version-href]\n[![npm downloads][npm-downloads-src]][npm-downloads-href]\n[![bundle][bundle-src]][bundle-href]\n[![Codecov][codecov-src]][codecov-href]\n[![License][license-src]][license-href]\n[![JSDocs][jsdocs-src]][jsdocs-href]\n\nH3 is a minimal h(ttp) framework built for high performance and portability.\n\n## Features\n\n✔️ \u0026nbsp;**Portable:** Works perfectly in Serverless, Workers, and Node.js\n\n✔️ \u0026nbsp;**Minimal:** Small and tree-shakable\n\n✔️ \u0026nbsp;**Modern:** Native promise support\n\n✔️ \u0026nbsp;**Extendable:** Ships with a set of composable utilities but can be extended\n\n✔️ \u0026nbsp;**Router:** Super fast route matching using [unjs/radix3](https://github.com/unjs/radix3)\n\n✔️ \u0026nbsp;**Compatible:** Compatibility layer with node/connect/express middleware\n\n## Install\n\n```bash\n# Using npm\nnpm install h3\n\n# Using yarn\nyarn add h3\n\n# Using pnpm\npnpm add h3\n```\n\n## Usage\n\n```ts\nimport { createServer } from \"node:http\";\nimport { createApp, eventHandler, toNodeListener } from \"h3\";\n\nconst app = createApp();\napp.use(\n  \"/\",\n  eventHandler(() =\u003e \"Hello world!\")\n);\n\ncreateServer(toNodeListener(app)).listen(process.env.PORT || 3000);\n```\n\nExample using \u003ca href=\"https://github.com/unjs/listhen\"\u003elisthen\u003c/a\u003e for an elegant listener:\n\n```ts\nimport { createApp, eventHandler, toNodeListener } from \"h3\";\nimport { listen } from \"listhen\";\n\nconst app = createApp();\napp.use(\n  \"/\",\n  eventHandler(() =\u003e \"Hello world!\")\n);\n\nlisten(toNodeListener(app));\n```\n\n## Router\n\nThe `app` instance created by `h3` uses a middleware stack (see [how it works](./src/app.ts)) with the ability to match route prefix and apply matched middleware.\n\nTo opt-in using a more advanced and convenient routing system, we can create a router instance and register it to app instance.\n\n```ts\nimport { createApp, eventHandler, createRouter } from \"h3\";\n\nconst app = createApp();\n\nconst router = createRouter()\n  .get(\n    \"/\",\n    eventHandler(() =\u003e \"Hello World!\")\n  )\n  .get(\n    \"/hello/:name\",\n    eventHandler((event) =\u003e `Hello ${event.context.params.name}!`)\n  );\n\napp.use(router);\n```\n\n**Tip:** We can register the same route more than once with different methods.\n\nRoutes are internally stored in a [Radix Tree](https://en.wikipedia.org/wiki/Radix_tree) and matched using [unjs/radix3](https://github.com/unjs/radix3).\n\n## More app usage examples\n\n```js\n// Handle can directly return object or Promise\u003cobject\u003e for JSON response\napp.use(\n  \"/api\",\n  eventHandler((event) =\u003e ({ url: event.node.req.url }))\n);\n\n// We can have better matching other than quick prefix match\napp.use(\n  \"/odd\",\n  eventHandler(() =\u003e \"Is odd!\"),\n  { match: (url) =\u003e url.substr(1) % 2 }\n);\n\n// Handle can directly return string for HTML response\napp.use(eventHandler(() =\u003e \"\u003ch1\u003eHello world!\u003c/h1\u003e\"));\n\n// We can chain calls to .use()\napp\n  .use(\n    \"/1\",\n    eventHandler(() =\u003e \"\u003ch1\u003eHello world!\u003c/h1\u003e\")\n  )\n  .use(\n    \"/2\",\n    eventHandler(() =\u003e \"\u003ch1\u003eGoodbye!\u003c/h1\u003e\")\n  );\n\n// We can proxy requests and rewrite cookie's domain and path\napp.use(\n  \"/api\",\n  eventHandler((event) =\u003e\n    proxyRequest(event, \"https://example.com\", {\n      // f.e. keep one domain unchanged, rewrite one domain and remove other domains\n      cookieDomainRewrite: {\n        \"example.com\": \"example.com\",\n        \"example.com\": \"somecompany.co.uk\",\n        \"*\": \"\",\n      },\n      cookiePathRewrite: {\n        \"/\": \"/api\",\n      },\n    })\n  )\n);\n\n// Legacy middleware with 3rd argument are automatically promisified\napp.use(\n  fromNodeMiddleware((req, res, next) =\u003e {\n    req.setHeader(\"x-foo\", \"bar\");\n    next();\n  })\n);\n\n// Lazy loaded routes using { lazy: true }\napp.use(\"/big\", () =\u003e import(\"./big-handler\"), { lazy: true });\n```\n\n## Utilities\n\nH3 has a concept of composable utilities that accept `event` (from `eventHandler((event) =\u003e {})`) as their first argument. This has several performance benefits over injecting them to `event` or `app` instances in global middleware commonly used in Node.js frameworks, such as Express. This concept means only required code is evaluated and bundled, and the rest of the utilities can be tree-shaken when not used.\n\n### Built-in\n\n- `readRawBody(event, encoding?)`\n- `readBody(event)`\n- `parseCookies(event)`\n- `getCookie(event, name)`\n- `setCookie(event, name, value, opts?)`\n- `deleteCookie(event, name, opts?)`\n- `getQuery(event)`\n- `getRouterParams(event)`\n- `send(event, data, type?)`\n- `sendRedirect(event, location, code=302)`\n- `getRequestHeaders(event, headers)` (alias: `getHeaders`)\n- `getRequestHeader(event, name)` (alias: `getHeader`)\n- `setResponseHeaders(event, headers)` (alias: `setHeaders`)\n- `setResponseHeader(event, name, value)` (alias: `setHeader`)\n- `appendResponseHeaders(event, headers)` (alias: `appendHeaders`)\n- `appendResponseHeader(event, name, value)` (alias: `appendHeader`)\n- `writeEarlyHints(event, links, callback)`\n- `sendStream(event, data)`\n- `sendError(event, error, debug?)`\n- `getMethod(event, default?)`\n- `isMethod(event, expected, allowHead?)`\n- `assertMethod(event, expected, allowHead?)`\n- `createError({ statusCode, statusMessage, data? })`\n- `sendProxy(event, { target, ...options })`\n- `proxyRequest(event, { target, ...options })`\n- `fetchWithEvent(event, req, init, { fetch? }?)`\n- `getProxyRequestHeaders(event)`\n- `sendNoContent(event, code = 204)`\n- `setResponseStatus(event, status)`\n- `getResponseStatus(event)`\n- `getResponseStatusText(event)`\n- `readMultipartFormData(event)`\n- `useSession(event, config = { password, maxAge?, name?, cookie?, seal?, crypto? })`\n- `getSession(event, config)`\n- `updateSession(event, config, update)`\n- `clearSession(event, config)`\n- `sealSession(event, config)`\n- `unsealSession(event, config, sealed)`\n- `handleCors(options)` (see [h3-cors](https://github.com/NozomuIkuta/h3-cors) for more detail about options)\n- `isPreflightRequest(event)`\n- `isCorsOriginAllowed(event)`\n- `appendCorsHeaders(event, options)` (see [h3-cors](https://github.com/NozomuIkuta/h3-cors) for more detail about options)\n- `appendCorsPreflightHeaders(event, options)` (see [h3-cors](https://github.com/NozomuIkuta/h3-cors) for more detail about options)\n- `getRequestHost(event)`\n- `getRequestProtocol(event)`\n- `getRequestURL(event)`\n\n👉 You can learn more about usage in [JSDocs Documentation](https://www.jsdocs.io/package/h3#package-functions).\n\n## Community Packages\n\nYou can use more H3 event utilities made by the community.\n\nPlease check their READMEs for more details.\n\nPRs are welcome to add your packages.\n\n- [h3-typebox](https://github.com/kevinmarrec/h3-typebox)\n  - `validateBody(event, schema)`\n  - `validateQuery(event, schema)`\n- [h3-zod](https://github.com/wobsoriano/h3-zod)\n  - `useValidatedBody(event, schema)`\n  - `useValidatedQuery(event, schema)`\n\n## License\n\nMIT\n\n\u003c!-- Badges --\u003e\n\n[npm-version-src]: https://img.shields.io/npm/v/h3?style=flat\u0026colorA=18181B\u0026colorB=F0DB4F\n[npm-version-href]: https://npmjs.com/package/h3\n[npm-downloads-src]: https://img.shields.io/npm/dm/h3?style=flat\u0026colorA=18181B\u0026colorB=F0DB4F\n[npm-downloads-href]: https://npmjs.com/package/h3\n[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/h3/main?style=flat\u0026colorA=18181B\u0026colorB=F0DB4F\n[codecov-href]: https://codecov.io/gh/unjs/h3\n[bundle-src]: https://img.shields.io/bundlephobia/minzip/h3?style=flat\u0026colorA=18181B\u0026colorB=F0DB4F\n[bundle-href]: https://bundlephobia.com/result?p=h3\n[license-src]: https://img.shields.io/github/license/unjs/h3.svg?style=flat\u0026colorA=18181B\u0026colorB=F0DB4F\n[license-href]: https://github.com/unjs/h3/blob/main/LICENSE\n[jsdocs-src]: https://img.shields.io/badge/jsDocs.io-reference-18181B?style=flat\u0026colorA=18181B\u0026colorB=F0DB4F\n[jsdocs-href]: https://www.jsdocs.io/package/h3\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswordjs%2Fh3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswordjs%2Fh3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswordjs%2Fh3/lists"}