[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-10136":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":21,"hasPages":21,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":38,"readmeContent":39,"aiSummary":40,"trendingCount":16,"starSnapshotCount":16,"syncStatus":41,"lastSyncTime":42,"discoverSource":43},10136,"http-proxy-middleware","chimurai\u002Fhttp-proxy-middleware","chimurai",":zap: The one-liner node.js http-proxy middleware for connect, express, next.js and more","",null,"TypeScript",11130,878,113,25,0,1,10,70.33,"MIT License",false,"master",[24,25,26,27,28,29,30,31,32,33,34,35,36,37],"browser-sync","connect","express","fastify","http-proxy","javascript","middleware","nextjs","node","nodejs","polka","proxy","proxy-middleware","websocket","2026-06-12 04:00:48","# http-proxy-middleware\n\n[![GitHub Workflow Status (with branch)](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Factions\u002Fworkflow\u002Fstatus\u002Fchimurai\u002Fhttp-proxy-middleware\u002Fci.yml?branch=master&logo=github-actions&logoColor=white&style=flat-square)](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Factions\u002Fworkflows\u002Fci.yml?query=branch%3Amaster)\n[![Coveralls](https:\u002F\u002Fimg.shields.io\u002Fcoveralls\u002Fchimurai\u002Fhttp-proxy-middleware.svg?style=flat-square&logo=coveralls)](https:\u002F\u002Fcoveralls.io\u002Fr\u002Fchimurai\u002Fhttp-proxy-middleware)\n[![Known Vulnerabilities](https:\u002F\u002Fsnyk.io\u002Ftest\u002Fgithub\u002Fchimurai\u002Fhttp-proxy-middleware\u002Fbadge.svg)](https:\u002F\u002Fsnyk.io\u002Ftest\u002Fgithub\u002Fchimurai\u002Fhttp-proxy-middleware)\n[![npm](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002Fhttp-proxy-middleware?color=%23CC3534&style=flat-square&logo=npm)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fhttp-proxy-middleware)\n\nNode.js proxying made simple. Configure proxy middleware with ease for [connect](https:\u002F\u002Fgithub.com\u002Fsenchalabs\u002Fconnect), [express](https:\u002F\u002Fgithub.com\u002Fexpressjs\u002Fexpress), [next.js](https:\u002F\u002Fgithub.com\u002Fvercel\u002Fnext.js), [hono](https:\u002F\u002Fgithub.com\u002Fhonojs\u002Fhono) and [many more](#compatible-servers).\n\nPowered by [`httpxy`](https:\u002F\u002Fgithub.com\u002Funjs\u002Fhttpxy). A maintained version of [http-proxy](https:\u002F\u002Fgithub.com\u002Fhttp-party\u002Fnode-http-proxy).\n\n## ⚠️ Note \u003C!-- omit in toc -->\n\nThis page is showing documentation for version **v4.x.x** ([release notes](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Freleases))\n\nFor older documentation:\n\n- [v3.0.5](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Ftree\u002Fv3.0.5#readme)\n- [v2.0.4](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Ftree\u002Fv2.0.4#readme)\n- [v0.21.0](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Ftree\u002Fv0.21.0#readme)\n\n## TL;DR \u003C!-- omit in toc -->\n\nProxy `\u002Fapi` requests to `http:\u002F\u002Fwww.example.org`\n\n:bulb: **Tip:** Set the option `changeOrigin` to `true` for [name-based virtual hosted sites](http:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FVirtual_hosting#Name-based).\n\n```typescript\n\u002F\u002F typescript\nimport express from 'express';\nimport type { NextFunction, Request, Response } from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\nimport type { Filter, Options, RequestHandler } from 'http-proxy-middleware';\n\nconst app = express();\n\nconst proxyMiddleware = createProxyMiddleware\u003CRequest, Response>({\n  target: 'http:\u002F\u002Fwww.example.org\u002Fapi',\n  changeOrigin: true,\n});\n\napp.use('\u002Fapi', proxyMiddleware);\n\napp.listen(3000);\n\n\u002F\u002F proxy and keep the same base path \"\u002Fapi\"\n\u002F\u002F http:\u002F\u002F127.0.0.1:3000\u002Fapi\u002Ffoo\u002Fbar -> http:\u002F\u002Fwww.example.org\u002Fapi\u002Ffoo\u002Fbar\n```\n\n_All_ `httpxy` [options](https:\u002F\u002Fgithub.com\u002Funjs\u002Fhttpxy#options) can be used, along with some extra `http-proxy-middleware` [options](#options).\n\n## Table of Contents \u003C!-- omit in toc -->\n\n\u003C!-- \u002F\u002F spell-checker:disable -->\n\n- [Install](#install)\n- [Basic usage](#basic-usage)\n- [Express Server Example](#express-server-example)\n  - [app.use(path, proxy)](#appusepath-proxy)\n- [Options](#options)\n  - [`pathFilter` (string, \\[\\]string, glob, \\[\\]glob, function)](#pathfilter-string-string-glob-glob-function)\n  - [`pathRewrite` (object\u002Ffunction)](#pathrewrite-objectfunction)\n  - [`router` (object\u002Ffunction)](#router-objectfunction)\n  - [`plugins` (Array)](#plugins-array)\n  - [`ejectPlugins` (boolean) default: `false`](#ejectplugins-boolean-default-false)\n  - [`logger` (Object)](#logger-object)\n- [`httpxy` events](#httpxy-events)\n- [`httpxy` options](#httpxy-options)\n- [WebSocket](#websocket)\n  - [External WebSocket upgrade](#external-websocket-upgrade)\n- [Intercept and manipulate requests](#intercept-and-manipulate-requests)\n- [Intercept and manipulate responses](#intercept-and-manipulate-responses)\n- [Node.js 17+: ECONNREFUSED issue with IPv6 and localhost (#705)](#nodejs-17-econnrefused-issue-with-ipv6-and-localhost-705)\n- [Debugging](#debugging)\n- [Working examples](#working-examples)\n- [Recipes](#recipes)\n- [Compatible servers](#compatible-servers)\n- [Tests](#tests)\n- [Changelog](#changelog)\n- [License](#license)\n\n\u003C!-- \u002F\u002F spell-checker:enable -->\n\n## Install\n\n```shell\nnpm install --save-dev http-proxy-middleware\n```\n\n## Basic usage\n\nCreate and configure a proxy middleware with: `createProxyMiddleware(config)`.\n\n```javascript\nimport { createProxyMiddleware } from 'http-proxy-middleware';\n\nconst apiProxy = createProxyMiddleware({\n  target: 'http:\u002F\u002Fwww.example.org',\n  changeOrigin: true,\n});\n\n\u002F\u002F 'apiProxy' is now ready to be used as middleware in a server.\n```\n\n- **options.target**: target host to proxy to. _(protocol + host)_\n- **options.changeOrigin**: for virtual hosted sites\n\n- see full list of [`http-proxy-middleware` configuration options](#options)\n\n## Express Server Example\n\nAn example with `express` server.\n\n```javascript\n\u002F\u002F include dependencies\nimport express from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\n\nconst app = express();\n\n\u002F\u002F create the proxy\n\u002F** @type {import('http-proxy-middleware').RequestHandler\u003Cimport('express').Request, import('express').Response>} *\u002F\nconst exampleProxy = createProxyMiddleware({\n  target: 'http:\u002F\u002Fwww.example.org\u002Fapi', \u002F\u002F target host with the same base path\n  changeOrigin: true, \u002F\u002F needed for virtual hosted sites\n});\n\n\u002F\u002F mount `exampleProxy` in web server\napp.use('\u002Fapi', exampleProxy);\napp.listen(3000);\n```\n\n### app.use(path, proxy)\n\nIf you want to use the server's `app.use` `path` parameter to match requests.\nUse `pathFilter` option to further include\u002Fexclude requests which you want to proxy.\n\n```javascript\napp.use(\n  createProxyMiddleware({\n    target: 'http:\u002F\u002Fwww.example.org\u002Fapi',\n    changeOrigin: true,\n    pathFilter: '\u002Fapi\u002Fproxy-only-this-path',\n  }),\n);\n```\n\n`app.use` documentation:\n\n- express: \u003Chttp:\u002F\u002Fexpressjs.com\u002Fen\u002F4x\u002Fapi.html#app.use>\n- connect: \u003Chttps:\u002F\u002Fgithub.com\u002Fsenchalabs\u002Fconnect#mount-middleware>\n- polka: \u003Chttps:\u002F\u002Fgithub.com\u002Flukeed\u002Fpolka#usebase-fn>\n\n## Options\n\nhttp-proxy-middleware options:\n\n### `pathFilter` (string, []string, glob, []glob, function)\n\nNarrow down which requests should be proxied. The `path` used for filtering is the `request.url` pathname. In Express, this is the `path` relative to the mount-point of the proxy.\n\n- **path matching**\n  - `createProxyMiddleware({...})` - matches any path, all requests will be proxied when `pathFilter` is not configured.\n  - `createProxyMiddleware({ pathFilter: '\u002Fapi', ...})` - matches paths starting with `\u002Fapi`\n\n- **multiple path matching**\n  - `createProxyMiddleware({ pathFilter: ['\u002Fapi', '\u002Fajax', '\u002Fsomeotherpath'], ...})`\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:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fmicromatch) or [glob](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fglob) for more globbing examples.\n  - `createProxyMiddleware({ pathFilter: '**', ...})` matches any path, all requests will be proxied.\n  - `createProxyMiddleware({ pathFilter: '**\u002F*.html', ...})` matches any path which ends with `.html`\n  - `createProxyMiddleware({ pathFilter: '\u002F*.html', ...})` matches paths directly under path-absolute\n  - `createProxyMiddleware({ pathFilter: '\u002Fapi\u002F**\u002F*.html', ...})` matches requests ending with `.html` in the path of `\u002Fapi`\n  - `createProxyMiddleware({ pathFilter: ['\u002Fapi\u002F**', '\u002Fajax\u002F**'], ...})` combine multiple patterns\n  - `createProxyMiddleware({ pathFilter: ['\u002Fapi\u002F**', '!**\u002Fbad.json'], ...})` exclusion\n\n  **Note**: 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  ```javascript\n  \u002F**\n   * @return {Boolean}\n   *\u002F\n  const pathFilter = function (path, req) {\n    return path.match('^\u002Fapi') && req.method === 'GET';\n  };\n\n  const apiProxy = createProxyMiddleware({\n    target: 'http:\u002F\u002Fwww.example.org',\n    pathFilter: pathFilter,\n  });\n  ```\n\n### `pathRewrite` (object\u002Ffunction)\n\nRewrite target's url path. Object-keys will be used as _RegExp_ to match paths.\n\n```javascript\n\u002F\u002F rewrite path\npathRewrite: {'^\u002Fold\u002Fapi' : '\u002Fnew\u002Fapi'}\n\n\u002F\u002F remove path\npathRewrite: {'^\u002Fremove\u002Fapi' : ''}\n\n\u002F\u002F add base path\npathRewrite: {'^\u002F' : '\u002Fbasepath\u002F'}\n\n\u002F\u002F custom rewriting\npathRewrite: function (path, req) { return path.replace('\u002Fapi', '\u002Fbase\u002Fapi') }\n\n\u002F\u002F 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### `router` (object\u002Ffunction)\n\nRe-target `option.target` for specific requests.\n\n```javascript\n\u002F\u002F Use `host` and\u002For `path` to match requests. First match will be used.\n\u002F\u002F The order of the configuration matters.\nrouter: {\n    'integration.localhost:3000' : 'http:\u002F\u002F127.0.0.1:8001',  \u002F\u002F host only\n    'staging.localhost:3000'     : 'http:\u002F\u002F127.0.0.1:8002',  \u002F\u002F host only\n    'localhost:3000\u002Fapi'         : 'http:\u002F\u002F127.0.0.1:8003',  \u002F\u002F host + path\n    '\u002Frest'                      : 'http:\u002F\u002F127.0.0.1:8004'   \u002F\u002F path only\n}\n\n\u002F\u002F Custom router function (string target)\nrouter: function(req) {\n    return 'http:\u002F\u002F127.0.0.1:8004';\n}\n\n\u002F\u002F Custom router function (target object)\nrouter: function(req) {\n    return {\n        protocol: 'https:', \u002F\u002F The : is required\n        host: '127.0.0.1',\n        port: 8004\n    };\n}\n\n\u002F\u002F Asynchronous router function which returns promise\nrouter: async function(req) {\n    const url = await doSomeIO();\n    return url;\n}\n```\n\n### `plugins` (Array)\n\n```js\nconst simpleRequestLogger = (proxyServer, options) => {\n  proxyServer.on('proxyReq', (proxyReq, req, res) => {\n    console.log(`[HPM] [${req.method}] ${req.url}`); \u002F\u002F outputs: [HPM] GET \u002Fusers\n  });\n},\n\nconst config = {\n  target: `http:\u002F\u002Fexample.org`,\n  changeOrigin: true,\n  plugins: [simpleRequestLogger],\n};\n```\n\n### `ejectPlugins` (boolean) default: `false`\n\nIf you're not satisfied with the pre-configured plugins, you can eject them by configuring `ejectPlugins: true`.\n\nNOTE: register your own error handlers to prevent server from crashing.\n\n```js\n\u002F\u002F eject default plugins and manually add them back\nimport {\n  debugProxyErrorsPlugin,\n  \u002F\u002F log proxy events to a logger (ie. console)\n  errorResponsePlugin,\n  \u002F\u002F subscribe to proxy errors to prevent server from crashing\n  loggerPlugin,\n  \u002F\u002F return 5xx response on proxy error\n  proxyEventsPlugin, \u002F\u002F implements the \"on:\" option\n} from 'http-proxy-middleware';\n\ncreateProxyMiddleware({\n  target: `http:\u002F\u002Fexample.org`,\n  changeOrigin: true,\n  ejectPlugins: true,\n  plugins: [debugProxyErrorsPlugin, loggerPlugin, errorResponsePlugin, proxyEventsPlugin],\n});\n```\n\n### `logger` (Object)\n\nConfigure a logger to output information from http-proxy-middleware: ie. `console`, `winston`, `pino`, `bunyan`, `log4js`, etc...\n\nOnly `info`, `warn`, `error` are used internally for compatibility across different loggers.\n\nIf you use `winston`, make sure to enable interpolation: \u003Chttps:\u002F\u002Fgithub.com\u002Fwinstonjs\u002Fwinston#string-interpolation>\n\nSee also logger recipes ([recipes\u002Flogger.md](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Fblob\u002Fmaster\u002Frecipes\u002Flogger.md)) for more details.\n\n```javascript\ncreateProxyMiddleware({\n  logger: console,\n});\n```\n\n## `httpxy` events\n\nSubscribe to [httpxy events](https:\u002F\u002Fgithub.com\u002Funjs\u002Fhttpxy#events) with the `on` option:\n\n```js\ncreateProxyMiddleware({\n  target: 'http:\u002F\u002Fwww.example.org',\n  on: {\n    proxyReq: (proxyReq, req, res) => {\n      \u002F* handle proxyReq *\u002F\n    },\n    proxyRes: (proxyRes, req, res) => {\n      \u002F* handle proxyRes *\u002F\n    },\n    error: (err, req, res) => {\n      \u002F* handle error *\u002F\n    },\n  },\n});\n```\n\n- **option.on.error**: function, subscribe to httpxy's `error` event for custom error handling.\n\n  ```javascript\n  function onError(err, req, res, target) {\n    res.writeHead(500, {\n      'Content-Type': 'text\u002Fplain',\n    });\n    res.end('Something went wrong. And we are reporting a custom error message.');\n  }\n  ```\n\n- **option.on.proxyRes**: function, subscribe to httpxy's `proxyRes` event.\n\n  ```javascript\n  function onProxyRes(proxyRes, req, res) {\n    proxyRes.headers['x-added'] = 'foobar'; \u002F\u002F add new header to response\n    delete proxyRes.headers['x-removed']; \u002F\u002F remove header from response\n  }\n  ```\n\n- **option.on.proxyReq**: function, subscribe to httpxy's `proxyReq` event.\n\n  ```javascript\n  function onProxyReq(proxyReq, req, res) {\n    \u002F\u002F add custom header to request\n    proxyReq.setHeader('x-added', 'foobar');\n    \u002F\u002F or log the req\n  }\n  ```\n\n- **option.on.proxyReqWs**: function, subscribe to httpxy's `proxyReqWs` event.\n\n  ```javascript\n  function onProxyReqWs(proxyReq, req, socket, options, head) {\n    \u002F\u002F add custom header\n    proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');\n  }\n  ```\n\n- **option.on.open**: function, subscribe to httpxy's `open` event.\n\n  ```javascript\n  function onOpen(proxySocket) {\n    \u002F\u002F listen for messages coming FROM the target here\n    proxySocket.on('data', hybridParseAndLogMessage);\n  }\n  ```\n\n- **option.on.close**: function, subscribe to httpxy's `close` event.\n\n  ```javascript\n  function onClose(res, socket, head) {\n    \u002F\u002F view disconnected websocket connections\n    console.log('Client disconnected');\n  }\n  ```\n\n## `httpxy` options\n\nThe following options are provided by the underlying [httpxy](https:\u002F\u002Fgithub.com\u002Funjs\u002Fhttpxy#options) library.\n\n- **option.target**: url string to be parsed with the url module\n- **option.forward**: url string to be parsed with the url module\n- **option.agent**: object to be passed to http(s).request (see Node's [https agent](http:\u002F\u002Fnodejs.org\u002Fapi\u002Fhttps.html#https_class_https_agent) and [http agent](http:\u002F\u002Fnodejs.org\u002Fapi\u002Fhttp.html#http_class_http_agent) objects)\n- **option.ssl**: object to be passed to https.createServer()\n- **option.ws**: true\u002Ffalse: if you want to proxy websockets\n- **option.xfwd**: true\u002Ffalse, adds x-forward headers\n- **option.secure**: true\u002Ffalse, if you want to verify the SSL Certs\n- **option.toProxy**: true\u002Ffalse, passes the absolute URL as the `path` (useful for proxying to proxies)\n- **option.prependPath**: true\u002Ffalse, Default: true - specify whether you want to prepend the target's path to the proxy path\n- **option.ignorePath**: true\u002Ffalse, Default: false - specify whether you want to ignore the proxy path of the incoming request (note: you will have to append \u002F manually if required).\n- **option.localAddress** : Local interface string to bind for outgoing connections\n- **option.changeOrigin**: true\u002Ffalse, Default: false - changes the origin of the host header to the target URL\n- **option.preserveHeaderKeyCase**: true\u002Ffalse, Default: false - specify whether you want to keep letter case of response header key\n- **option.auth** : Basic authentication i.e. 'user:password' to compute an Authorization header.\n- **option.hostRewrite**: rewrites the location hostname on (301\u002F302\u002F307\u002F308) redirects.\n- **option.autoRewrite**: rewrites the location host\u002Fport on (301\u002F302\u002F307\u002F308) redirects based on requested host\u002Fport. Default: false.\n- **option.protocolRewrite**: rewrites the location protocol on (301\u002F302\u002F307\u002F308) redirects to 'http' or 'https'. Default: null.\n- **option.cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values:\n  - `false` (default): disable cookie rewriting\n  - String: new domain, for example `cookieDomainRewrite: \"new.domain\"`. To remove the domain, use `cookieDomainRewrite: \"\"`.\n  - Object: mapping of domains to new domains, use `\"*\"` to match all domains.  \n    For example keep one domain unchanged, rewrite one domain and remove other domains:\n\n    ```jsonc\n    cookieDomainRewrite: {\n      \"unchanged.domain\": \"unchanged.domain\",\n      \"old.domain\": \"new.domain\",\n      \"*\": \"\"\n    }\n    ```\n\n- **option.cookiePathRewrite**: rewrites path of `set-cookie` headers. Possible values:\n  - `false` (default): disable cookie rewriting\n  - String: new path, for example `cookiePathRewrite: \"\u002FnewPath\u002F\"`. To remove the path, use `cookiePathRewrite: \"\"`. To set path to root use `cookiePathRewrite: \"\u002F\"`.\n  - Object: mapping of paths to new paths, use `\"*\"` to match all paths.\n    For example, to keep one path unchanged, rewrite one path and remove other paths:\n\n    ```jsonc\n    cookiePathRewrite: {\n      \"\u002Funchanged.path\u002F\": \"\u002Funchanged.path\u002F\",\n      \"\u002Fold.path\u002F\": \"\u002Fnew.path\u002F\",\n      \"*\": \"\"\n    }\n    ```\n\n- **option.headers**: object, adds [request headers](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FList_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}`)\n- **option.proxyTimeout**: timeout (in millis) when proxy receives no response from target\n- **option.timeout**: timeout (in millis) for incoming requests\n- **option.followRedirects**: true\u002Ffalse, Default: false - specify whether you want to follow redirects\n- **option.selfHandleResponse** true\u002Ffalse, if set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the `proxyRes` event\n- **option.buffer**: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option:\n\n  ```javascript\n  import { createProxyServer } from 'httpxy';\n  import streamify from 'stream-array';\n\n  const proxy = createProxyServer();\n\n  export default function proxyWithBody(req, res, next) {\n    proxy.web(\n      req,\n      res,\n      {\n        target: 'http:\u002F\u002F127.0.0.1:4003\u002F',\n        buffer: streamify(req.rawBody),\n      },\n      next,\n    );\n  }\n  ```\n\n## WebSocket\n\n```javascript\n\u002F\u002F verbose api\ncreateProxyMiddleware({ pathFilter: '\u002F', target: 'http:\u002F\u002Fecho.websocket.org', ws: true });\n```\n\n### External WebSocket upgrade\n\nIn the previous WebSocket examples, http-proxy-middleware relies on a initial http request in order to listen to the http `upgrade` event. If you need to proxy WebSockets without the initial http request, you can subscribe to the server's http `upgrade` event manually.\n\n```javascript\nconst wsProxy = createProxyMiddleware({ target: 'ws:\u002F\u002Fecho.websocket.org', changeOrigin: true });\n\nconst app = express();\napp.use(wsProxy);\n\nconst server = app.listen(3000);\nserver.on('upgrade', wsProxy.upgrade); \u002F\u002F \u003C-- subscribe to http 'upgrade'\n```\n\n## Intercept and manipulate requests\n\nIntercept requests from downstream by defining `onProxyReq` in `createProxyMiddleware`.\n\nCurrently the only pre-provided request interceptor is `fixRequestBody`, which is used to fix proxied POST requests when `bodyParser` is applied before this middleware.\n\nExample:\n\n```javascript\nimport { createProxyMiddleware, fixRequestBody } from 'http-proxy-middleware';\n\nconst proxy = createProxyMiddleware({\n  \u002F**\n   * Fix bodyParser\n   **\u002F\n  on: {\n    proxyReq: fixRequestBody,\n  },\n});\n```\n\n## Intercept and manipulate responses\n\nIntercept responses from upstream with `responseInterceptor`. (Make sure to set `selfHandleResponse: true`)\n\nResponses which are compressed with `brotli`, `gzip` and `deflate` will be decompressed automatically. The response will be returned as `buffer` ([docs](https:\u002F\u002Fnodejs.org\u002Fapi\u002Fbuffer.html)) which you can manipulate.\n\nWith `buffer`, response manipulation is not limited to text responses (html\u002Fcss\u002Fjs, etc...); image manipulation will be possible too. ([example](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Fblob\u002Fmaster\u002Frecipes\u002Fresponse-interceptor.md#manipulate-image-response))\n\nNOTE: `responseInterceptor` disables streaming of target's response.\n\nExample:\n\n```javascript\nimport { createProxyMiddleware, responseInterceptor } from 'http-proxy-middleware';\n\nconst proxy = createProxyMiddleware({\n  \u002F**\n   * IMPORTANT: avoid res.end being called automatically\n   **\u002F\n  selfHandleResponse: true, \u002F\u002F res.end() will be called internally by responseInterceptor()\n\n  \u002F**\n   * Intercept response and replace 'Hello' with 'Goodbye'\n   **\u002F\n  on: {\n    proxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => {\n      const response = responseBuffer.toString('utf8'); \u002F\u002F convert buffer to string\n      return response.replace('Hello', 'Goodbye'); \u002F\u002F manipulate response and return the result\n    }),\n  },\n});\n```\n\nCheck out [interception recipes](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Fblob\u002Fmaster\u002Frecipes\u002Fresponse-interceptor.md) for more examples.\n\n## Node.js 17+: ECONNREFUSED issue with IPv6 and localhost ([#705](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Fissues\u002F705))\n\nNode.js 17+ no longer prefers IPv4 over IPv6 for DNS lookups.\nE.g. It's **not** guaranteed that `localhost` will be resolved to `127.0.0.1` – it might just as well be `::1` (or some other IP address).\n\nIf your target server only accepts IPv4 connections, trying to proxy to `localhost` will fail if resolved to `::1` (IPv6).\n\nWays to solve it:\n\n- Change `target: \"http:\u002F\u002Flocalhost\"` to `target: \"http:\u002F\u002F127.0.0.1\"` (IPv4).\n- Change the target server to (also) accept IPv6 connections.\n- Add this flag when running `node`: `node index.js --dns-result-order=ipv4first`. (Not recommended.)\n\n> Note: There’s a thing called [Happy Eyeballs](https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FHappy_Eyeballs) which means connecting to both IPv4 and IPv6 in parallel, which Node.js doesn’t have, but explains why for example `curl` can connect.\n\n## Debugging\n\nConfigure the `DEBUG` environment variable enable debug logging.\n\nSee [`debug`](https:\u002F\u002Fgithub.com\u002Fdebug-js\u002Fdebug#readme) project for more options.\n\n```shell\nDEBUG=http-proxy-middleware* node server.js\n\n$ http-proxy-middleware proxy created +0ms\n$ http-proxy-middleware proxying request to target: 'http:\u002F\u002Fwww.example.org' +359ms\n```\n\n## Working examples\n\nView and play around with [working examples](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Ftree\u002Fmaster\u002Fexamples).\n\n- Browser-Sync ([example source](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Ftree\u002Fmaster\u002Fexamples\u002Fbrowser-sync\u002Findex.js))\n- express ([example source](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Ftree\u002Fmaster\u002Fexamples\u002Fexpress\u002Findex.js))\n- connect ([example source](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Ftree\u002Fmaster\u002Fexamples\u002Fconnect\u002Findex.js))\n- WebSocket ([example source](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Ftree\u002Fmaster\u002Fexamples\u002Fwebsocket\u002Findex.js))\n- Response Manipulation ([example source](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Fblob\u002Fmaster\u002Fexamples\u002Fresponse-interceptor\u002Findex.js))\n\n## Recipes\n\nView the [recipes](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Ftree\u002Fmaster\u002Frecipes) for common use cases.\n\n## Compatible servers\n\n`http-proxy-middleware` is compatible with the following servers:\n\n- [connect](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fconnect)\n- [express](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fexpress)\n- [hono](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@hono\u002Fnode-server)\n- [next.js](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fnext)\n- [fastify](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Ffastify)\n- [browser-sync](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fbrowser-sync)\n- [lite-server](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Flite-server)\n- [polka](https:\u002F\u002Fgithub.com\u002Flukeed\u002Fpolka)\n- [grunt-contrib-connect](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fgrunt-contrib-connect)\n- [grunt-browser-sync](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fgrunt-browser-sync)\n- [gulp-connect](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fgulp-connect)\n- [gulp-webserver](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fgulp-webserver)\n\nSample implementations can be found in the [server recipes](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Ftree\u002Fmaster\u002Frecipes\u002Fservers.md).\n\n## Tests\n\nRun the test suite:\n\n```bash\n# install dependencies\n$ yarn\n\n# linting\n$ yarn lint\n$ yarn lint:fix\n\n# building (compile typescript to js)\n$ yarn build\n\n# unit tests\n$ yarn test\n\n# code coverage\n$ yarn coverage\n\n# check spelling mistakes\n$ yarn spellcheck\n```\n\n## Changelog\n\n- [View changelog](https:\u002F\u002Fgithub.com\u002Fchimurai\u002Fhttp-proxy-middleware\u002Fblob\u002Fmaster\u002FCHANGELOG.md)\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2015-2026 Steven Chim\n","http-proxy-middleware 是一个用于 Node.js 的 HTTP 代理中间件，支持 connect、express、next.js 等多种框架。其核心功能是通过简洁的配置实现请求的代理转发，支持 WebSocket 和 HTTPS，并且可以处理基于名称的虚拟主机。该中间件提供了丰富的选项来定制代理行为，如更改源地址、路径过滤等。适用于需要在开发环境中模拟 API 请求、跨域请求处理或者前后端分离架构下的代理需求场景。",2,"2026-06-11 03:26:46","top_topic"]