{"id":17033955,"url":"https://github.com/yisibell/h3-proxy","last_synced_at":"2025-06-21T15:07:23.002Z","repository":{"id":142838587,"uuid":"613791310","full_name":"yisibell/h3-proxy","owner":"yisibell","description":"A http(s) proxy event handler for h3, using proxyRequest.","archived":false,"fork":false,"pushed_at":"2025-01-03T02:56:03.000Z","size":226,"stargazers_count":13,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-21T15:07:15.382Z","etag":null,"topics":["event-handler","h3","http","http-proxy","https","middleware","nuxt","nuxt3","proxy","proxy-request"],"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/yisibell.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,"zenodo":null}},"created_at":"2023-03-14T09:27:22.000Z","updated_at":"2025-06-12T15:28:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"fdae6168-e357-459f-a891-ce63bf9a151b","html_url":"https://github.com/yisibell/h3-proxy","commit_stats":{"total_commits":78,"total_committers":1,"mean_commits":78.0,"dds":0.0,"last_synced_commit":"7544826df2abfc3a6a2c8fb2fcca6219bf8d6033"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/yisibell/h3-proxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yisibell%2Fh3-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yisibell%2Fh3-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yisibell%2Fh3-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yisibell%2Fh3-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yisibell","download_url":"https://codeload.github.com/yisibell/h3-proxy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yisibell%2Fh3-proxy/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261143148,"owners_count":23115674,"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":["event-handler","h3","http","http-proxy","https","middleware","nuxt","nuxt3","proxy","proxy-request"],"created_at":"2024-10-14T08:36:49.324Z","updated_at":"2025-06-21T15:07:17.990Z","avatar_url":"https://github.com/yisibell.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.org/package/h3-proxy\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/h3-proxy.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://npmcharts.com/compare/h3-proxy?minimal=true\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/dm/h3-proxy.svg\"\u003e\n  \u003c/a\u003e\n  \u003cbr\u003e\n\u003c/p\u003e\n\n# h3-proxy\n\nA **proxy event handler** for [h3](https://github.com/unjs/h3), using `proxyRequest`.\n\n- ✨ [Release Notes](./CHANGELOG.md)\n\n# Features\n\n- Powered by built-in [proxyRequest](https://github.com/unjs/h3/blob/main/src/utils/proxy.ts) of [h3](https://github.com/unjs/h3).\n- Support http(s) proxy via some simple [configurations](https://github.com/yisibell/h3-proxy#options).\n- Support logs via **consola**.\n- Support **Typescript**.\n\n# Installation\n\n```bash\n# pnpm\n$ pnpm add h3-proxy\n\n# yarn\n$ yarn add h3-proxy\n\n# npm\n$ npm i h3-proxy\n```\n\n# Basic usage\n\n```ts\nimport { createServer } from 'node:http'\nimport { createApp, eventHandler, toNodeListener } from 'h3'\nimport { createProxyEventHandler } from 'h3-proxy'\n\nconst app = createApp()\n\nconst port = process.env.PORT || 3000\n\n// Define proxy event handler\nconst proxyEventHandler = createProxyEventHandler({\n  target: `http://127.0.0.1:${port}`,\n  pathRewrite: {\n    '^/api': '',\n  },\n  pathFilter: ['/api/**'],\n  // enableLogger: true\n})\n\n// Add proxy middlewares\napp.use(eventHandler(proxyEventHandler))\n\n// Define api routes\napp.use(\n  '/test',\n  eventHandler(() =\u003e 'Hello world!')\n)\n\ncreateServer(toNodeListener(app)).listen(port)\n```\n\n# Multiple proxy targets usage\n\n### Create multiple proxy **h3** event handler middleware.\n\n```ts\nimport { createServer } from 'node:http'\nimport { createApp, eventHandler, toNodeListener } from 'h3'\nimport { createProxyEventHandler } from 'h3-proxy'\n\nconst app = createApp()\n\nconst port = process.env.PORT || 3000\n\n// proxy to `http://127.0.0.1:${port}`\nconst proxyEventHandler1 = createProxyEventHandler({\n  target: `http://127.0.0.1:${port}`, // http://127.0.0.1:3000\n  pathRewrite: {\n    '^/api': '',\n  },\n  pathFilter: ['/api/**'],\n})\n\n// proxy to other target\nconst proxyEventHandler2 = createProxyEventHandler({\n  target: `http://127.0.0.1:${port}/other-api-module`,\n  pathRewrite: {\n    '^/other-api': '',\n  },\n  pathFilter: ['/other-api/**'],\n})\n\n// Add proxy middlewares\napp.use(eventHandler(proxyEventHandler1))\napp.use(eventHandler(proxyEventHandler2))\n\n// Define api routes\napp.use(\n  '/test',\n  eventHandler(() =\u003e 'Hello world!')\n)\n\napp.use(\n  '/other-api-module/some/path',\n  eventHandler(() =\u003e 'Hello other API module!')\n)\n\ncreateServer(toNodeListener(app)).listen(port)\n```\n\n- For `proxyEventHandler1`, The result of proxy request  is as follows:\n\n`/api/test` -\u003e `http://127.0.0.1:3000/test`\n\n\n- For `proxyEventHandler2`, The result of proxy request  is as follows:\n\n`/other-api/some/path` -\u003e `http://127.0.0.1:3000/other-api-module/some/path`\n\n\n### Or, using **Array** type options to define multiple proxy targets (added in v1.11.0).\n\n```ts\nconst proxyEventHandler = createProxyEventHandler([\n  {\n    // options\n  },\n  {\n    // other proxy target options\n  }\n])\n```\n\n# APIs\n\n## createProxyEventHandler\n\nCreate a `h3` event handler that can handle **proxy requests**.\n\n```ts\nconst proxyEventHandler = createProxyEventHandler({\n  // options\n})\n```\n\n# Options\n\n| Key | Type | Required | Default value | Description |\n| :---: | :---: | :---: | :---: | :---:  |\n| `target` | `string` | `true` | `undefined` | Proxy target address, including **protocol**, **host** and **port**. url string to be parsed with the `node:url` module|\n| [pathFilter](https://github.com/yisibell/h3-proxy#pathFilter) | `string, string[], glob, glob[], Function` | `false` | `undefined` |Narrow down which requests should be proxied. |\n| [pathRewrite](https://github.com/yisibell/h3-proxy#pathRewrite) | `object/Function` | `false` | `undefined` | Rewrite target's url path. Object-keys will be used as RegExp to match paths. |\n| [configureProxyRequest](https://github.com/yisibell/h3-proxy#configureProxyRequest) | `Function` | `false` | `undefined` | Configure options of `proxyRequest`. More details see [built-in util proxyRequest of h3](https://github.com/unjs/h3) |\n| `proxyRequestMethod` \u003cbr /\u003e (Added in **v1.13.0**) | `Function` | `false` | `undefined` | Customize `proxyRequest` of **h3** method. |\n| `enableLogger` | `boolean` | `false` | `true` | Whether to enable logger which is created by **consola**. |\n| `loggerOptions` | `ConsolaOptions` | `false` | `{}` | Configure the options of [consola](https://github.com/unjs/consola). |\n| `changeOrigin` | `boolean` | `false` | `false` | Whether to changes the origin of the host header to the target URL |\n\n\n## pathFilter\n\n- **path matching**\n\n  - `createProxyEventHandler({...})` - matches any path, all requests will be proxied when `pathFilter` is not configured.\n  - `createProxyEventHandler({ pathFilter: '/api', ...})` - matches paths starting with `/api`\n\n- **multiple path matching**\n\n  - `createProxyEventHandler({ pathFilter: ['/api', '/ajax', '/someotherpath'], ...})`\n\n- **wildcard path matching**\n\n  For fine-grained control you can use wildcard matching. Glob pattern matching is done by _micromatch_. Visit [micromatch](https://www.npmjs.com/package/micromatch) or [glob](https://www.npmjs.com/package/glob) for more globbing examples.\n\n  - `createProxyEventHandler({ pathFilter: '**', ...})` matches any path, all requests will be proxied.\n  - `createProxyEventHandler({ pathFilter: '**/*.html', ...})` matches any path which ends with `.html`\n  - `createProxyEventHandler({ pathFilter: '/*.html', ...})` matches paths directly under path-absolute\n  - `createProxyEventHandler({ pathFilter: '/api/**/*.html', ...})` matches requests ending with `.html` in the path of `/api`\n  - `createProxyEventHandler({ pathFilter: ['/api/**', '/ajax/**'], ...})` combine multiple patterns\n  - `createProxyEventHandler({ pathFilter: ['/api/**', '!**/bad.json'], ...})` exclusion\n\n\u003e :warning: TIPS, In multiple path matching, you cannot use string paths and wildcard paths together.\n\n- **custom matching**\n\n  For full control you can provide a custom function to determine which requests should be proxied or not.\n\n  ```js\n  /**\n   * @return {Boolean}\n   */\n  const pathFilter = function (path, req) {\n\n    return path.match(/^\\/api/) \u0026\u0026 req.method === 'GET';\n\n    // TIPS: if you are using it in nuxt-proxy-request\n    // Pls use `new RegExp()` instead.\n\n    // return path.match(new RegExp('^\\/api')) \u0026\u0026 req.method === 'GET';\n  };\n\n  const apiProxy = createProxyEventHandler({\n    target: 'http://www.example.org',\n    pathFilter: pathFilter,\n  });\n  ```\n\n## pathRewrite\n\nRewrite target's url path. **Object-keys** will be used as **RegExp** to match paths.\n\n```js\n// rewrite path\npathRewrite: {'^/old/api' : '/new/api'}\n\n// remove path\npathRewrite: {'^/remove/api' : ''}\n\n// add base path\npathRewrite: {'^/' : '/basepath/'}\n\n// custom rewriting\npathRewrite: function (path, req) { return path.replace('/api', '/base/api') }\n\n// custom rewriting, returning Promise\npathRewrite: async function (path, req) {\n  const should_add_something = await httpRequestToDecideSomething(path);\n  if (should_add_something) path += \"something\";\n  return path;\n}\n```\n\n## configureProxyRequest\n\nFor the return value, Please refer to the source code of [proxyRequest of h3](https://github.com/unjs/h3/blob/main/src/utils/proxy.ts).\n\n```ts\ncreateProxyEventHandler({\n  // ...\n  // the param `event` is H3Event\n  configureProxyRequest(event) {\n    // return your custom options of proxyRequest\n\n    // eg: specify some request headers\n    // return {\n    //   headers: {}\n    // }\n\n    return {}\n  }\n})\n```\n\n# Framework Supports\n## Nuxt\n\n- using [nuxt-proxy-request](https://github.com/yisibell/nuxt-proxy-request) module.\n- using `h3-proxy` directly in **Nuxt**.\n\nAdd a [server middleware](https://nuxt.com/docs/guide/directory-structure/server#server-middleware).\n\n```ts\n// ~/server/middleware/proxy.ts\n\nimport { createProxyEventHandler } from 'h3-proxy'\n\nexport default defineEventHandler(createProxyEventHandler({\n  // options...\n}))\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyisibell%2Fh3-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyisibell%2Fh3-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyisibell%2Fh3-proxy/lists"}