[![npm downloads](https://img.shields.io/npm/dm/h3.svg?style=flat-square)](https://npmjs.com/package/h3) [![version](https://img.shields.io/npm/v/h3/latest.svg?style=flat-square)](https://npmjs.com/package/h3) [![bundlephobia](https://img.shields.io/bundlephobia/min/h3/latest.svg?style=flat-square)](https://bundlephobia.com/result?p=h3) [![build status](https://img.shields.io/github/workflow/status/unjs/h3/ci/main?style=flat-square)](https://github.com/unjs/h3/actions) [![coverage](https://img.shields.io/codecov/c/gh/unjs/h3/main?style=flat-square)](https://codecov.io/gh/unjs/h3) [![jsDocs.io](https://img.shields.io/badge/jsDocs.io-reference-blue?style=flat-square)](https://www.jsdocs.io/package/h3) > H3 is a minimal h(ttp) framework built for high performance and portability ## Features ✔️  **Portable:** Works perfectly in Serverless, Workers, and Node.js ✔️  **Minimal:** Small and tree-shakable ✔️  **Modern:** Native promise support ✔️  **Extendable:** Ships with a set of composable utilities but can be extended ✔️  **Router:** Super fast route matching using [unjs/radix3](https://github.com/unjs/radix3) ✔️  **Compatible:** Compatibility layer with node/connect/express middleware ## Install ```bash # Using npm npm install h3 # Using yarn yarn add h3 # Using pnpm pnpm add h3 ``` ## Usage ```ts import { createServer } from 'http' import { createApp, eventHandler, toNodeListener } from 'h3' const app = createApp() app.use('/', eventHandler(() => 'Hello world!')) createServer(toNodeListener(app)).listen(process.env.PORT || 3000) ```
Example using listhen for an elegant listener. ```ts import { createApp, toNodeListener } from 'h3' import { listen } from 'listhen' const app = createApp() app.use('/', eventHandler(() => 'Hello world!')) listen(toNodeListener(app)) ```
## Router The `app` instance created by `h3` uses a middleware stack (see [how it works](#how-it-works)) with the ability to match route prefix and apply matched middleware. To opt-in using a more advanced and convenient routing system, we can create a router instance and register it to app instance. ```ts import { createApp, eventHandler, createRouter } from 'h3' const app = createApp() const router = createRouter() .get('/', eventHandler(() => 'Hello World!')) .get('/hello/:name', eventHandler(event => `Hello ${event.context.params.name}!`)) app.use(router) ``` **Tip:** We can register same route more than once with different methods. Routes are internally stored in a [Radix Tree](https://en.wikipedia.org/wiki/Radix_tree) and matched using [unjs/radix3](https://github.com/unjs/radix3). ## More app usage examples ```js // Handle can directly return object or Promise for JSON response app.use('/api', eventHandler((event) => ({ url: event.node.req.url })) // We can have better matching other than quick prefix match app.use('/odd', eventHandler(() => 'Is odd!'), { match: url => url.substr(1) % 2 }) // Handle can directly return string for HTML response app.use(eventHandler(() => '

Hello world!

')) // We can chain calls to .use() app.use('/1', eventHandler(() => '

Hello world!

')) .use('/2', eventHandler(() => '

Goodbye!

')) // Legacy middleware with 3rd argument are automatically promisified app.use(fromNodeMiddleware((req, res, next) => { req.setHeader('x-foo', 'bar'); next() })) // Lazy loaded routes using { lazy: true } app.use('/big', () => import('./big-handler'), { lazy: true }) ``` ## Utilities H3 has concept of compasable utilities that accept `event` (from `eventHandler((event) => {})`) as their first argument. This has several performance benefits over injecting them to `event` or `app` instances and global middleware commonly used in Node.js frameworks such as Express, which Only required code is evaluated and bundled and rest of utils can be tree-shaken when not used. ### Built-in - `readRawBody(event, encoding?)` - `readBody(event)` - `parseCookies(event)` - `getCookie(event, name)` - `setCookie(event, name, value, opts?)` - `deleteCookie(event, name, opts?)` - `getQuery(event)` - `getRouterParams(event)` - `send(event, data, type?)` - `sendRedirect(event, location, code=302)` - `getRequestHeaders(event, headers)` (alias: `getHeaders`) - `getRequestHeader(event, name)` (alias: `getHeader`) - `setResponseHeaders(event, headers)` (alias: `setHeaders`) - `setResponseHeader(event, name, value)` (alias: `setHeader`) - `appendResponseHeaders(event, headers)` (alias: `appendHeaders`) - `appendResponseHeader(event, name, value)` (alias: `appendHeader`) - `writeEarlyHints(event, links, callback)` - `sendStream(event, data)` - `sendError(event, error, debug?)` - `getMethod(event, default?)` - `isMethod(event, expected, allowHead?)` - `assertMethod(event, expected, allowHead?)` - `createError({ statusCode, statusMessage, data? })` - `sendProxy(event, { target, headers?, fetchOptions?, fetch?, sendStream? })` - `proxyRequest(event, { target, headers?, fetchOptions?, fetch?, sendStream? })` 👉 You can learn more about usage in [JSDocs Documentation](https://www.jsdocs.io/package/h3#package-functions). ## Community Packages You can use more h3 event utilities made by the community. Please check their READMEs for more details. PRs are welcome to add your packages. - [h3-cors](https://github.com/NozomuIkuta/h3-cors) - `defineCorsEventHandler(options)` - `isPreflight(event)` - [h3-typebox](https://github.com/kevinmarrec/h3-typebox) - `validateBody(event, schema)` - `validateQuery(event, schema)` - [h3-zod](https://github.com/wobsoriano/h3-zod) - `useValidatedBody(event, schema)` - `useValidatedQuery(event, schema)` ## License MIT