{"id":16355,"library":"express-http-proxy-2","title":"Express HTTP Proxy Middleware Fork","description":"express-http-proxy-2 is an HTTP proxy middleware for the Express.js framework, designed to forward incoming requests to a specified target host and stream the responses back. This package is a community-maintained fork of the original `express-http-proxy` library, specifically created to address critical bugs, such as issue #509, and to provide comprehensive TypeScript type definitions, making it more robust for modern JavaScript and TypeScript projects. Currently at version 1.1.0, its release cadence is tied to bug fixes and feature enhancements derived from the community's needs, rather than a fixed schedule. Key differentiators include built-in support for streaming requests and responses, the ability to use Promises for asynchronous hooks, and flexible host selection which can be a static string or a dynamic function evaluated per request. It seamlessly integrates into Express applications, offering various configuration options to customize request path resolution, header manipulation, and conditional proxying.","status":"maintenance","version":"1.1.0","language":"javascript","source_language":"en","source_url":"git://github.com/leonheess/express-http-proxy-2","tags":["javascript","express-http-proxy-2","typescript"],"install":[{"cmd":"npm install express-http-proxy-2","lang":"bash","label":"npm"},{"cmd":"yarn add express-http-proxy-2","lang":"bash","label":"yarn"},{"cmd":"pnpm add express-http-proxy-2","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The primary proxy function is a default export for ESM. CommonJS uses `require('express-http-proxy-2')` directly.","wrong":"const proxy = require('express-http-proxy-2').default;","symbol":"proxy","correct":"import proxy from 'express-http-proxy-2';"},{"note":"This is a type-only import for configuring the proxy middleware. Using `import` without `type` can cause issues if not correctly handled by your build system.","wrong":"import { ProxyOptions } from 'express-http-proxy-2';","symbol":"ProxyOptions","correct":"import type { ProxyOptions } from 'express-http-proxy-2';"},{"note":"For CommonJS environments, the main proxy function is the direct export.","symbol":"proxy","correct":"const proxy = require('express-http-proxy-2');"}],"quickstart":{"code":"import express from 'express';\nimport proxy from 'express-http-proxy-2';\n\nconst app = express();\nconst PORT = 3000;\n\n// Configure the proxy middleware for requests to '/api'\n// These requests will be forwarded to 'https://jsonplaceholder.typicode.com'\n// and rewritten to remove '/api' from the path.\napp.use('/api', proxy('https://jsonplaceholder.typicode.com', {\n  proxyReqPathResolver: (req) => {\n    // Example: change /api/users to /users\n    const originalPath = req.url;\n    const updatedPath = originalPath.replace('/api', '');\n    console.log(`Proxying request: ${originalPath} -> ${updatedPath}`);\n    return updatedPath;\n  },\n  userResDecorator: (proxyRes, proxyResData) => {\n    // Optional: modify the response data from the proxied server\n    console.log('Received response from proxy target.');\n    const data = JSON.parse(proxyResData.toString('utf8'));\n    // Add a custom header to the response indicating it was proxied\n    proxyRes.headers['x-proxied-by'] = 'express-http-proxy-2';\n    return JSON.stringify({ ...data, proxied: true });\n  }\n}));\n\n// A simple health check route for the Express server itself\napp.get('/health', (req, res) => {\n  res.send('Server is healthy!');\n});\n\napp.listen(PORT, () => {\n  console.log(`Express server listening on http://localhost:${PORT}`);\n  console.log('Test proxy: curl http://localhost:3000/api/todos/1');\n  console.log('Test local: curl http://localhost:3000/health');\n});","lang":"typescript","description":"Demonstrates setting up `express-http-proxy-2` to proxy requests from `/api` to an external JSON API, including path rewriting and response modification."},"warnings":[{"fix":"Migrate any usage of `forwardPath` or `forwardPathAsync` to the `proxyReqPathResolver` function, which supports both synchronous and Promise-based asynchronous operations.","message":"The `forwardPath` and `forwardPathAsync` options are deprecated. Use `proxyReqPathResolver` for all path manipulation needs.","severity":"deprecated","affected_versions":">=1.0.0"},{"fix":"Ensure that `app.use(proxy(...))` is called before `app.use(bodyParser.json())` or similar body parsing middleware for routes that will be proxied.","message":"When using `body-parser` or similar middleware that parses request bodies, it must be declared *after* `express-http-proxy-2` for a given route. If `body-parser` runs first, it may consume or modify the request body, preventing `express-http-proxy-2` from correctly forwarding the original POST/PUT payload to the target server.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Be mindful of performance implications when using response decorators with large data transfers. Only use these options when necessary, or consider alternative approaches if high-performance streaming is critical for large files.","message":"Streaming of request and response bodies is disabled if you define certain response modifiers like `userResDecorator`, `userResHeaderDecorator`, or `maybeSkipToNext`. When these hooks are present, the entire request/response body must be buffered in memory, which can lead to performance issues and increased memory consumption with large payloads.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"For CommonJS, use `const proxy = require('express-http-proxy-2');`. For ESM, use `import proxy from 'express-http-proxy-2';`. Ensure your `tsconfig.json` or build setup is correctly configured for your module system.","cause":"Attempting to use `express-http-proxy-2` with an incorrect import style, often mixing CommonJS `require` with ESM default import assumptions, or vice-versa.","error":"TypeError: proxy is not a function"},{"fix":"Review any custom hooks (e.g., `proxyErrorHandler`, `userResDecorator`) to ensure they handle errors or final responses without inadvertently calling `res.send()` or `res.end()` more than once, or after the proxy has already begun sending data.","cause":"This typically occurs in Express middleware when a response is sent multiple times or headers are attempted to be modified after the response stream has started. This can happen if a proxy hook (e.g., `userResDecorator` or `proxyErrorHandler`) explicitly sends a response and then Express tries to send another, or if promises in hooks are not handled correctly.","error":"Error: Can't set headers after they are sent."},{"fix":"First, verify the `host` argument is correct and accessible. Then, meticulously debug `proxyReqPathResolver` by logging the `req.url` and the `return` value to ensure the target path is constructed as expected. Check if the `filter` option is unintentionally blocking requests.","cause":"This often points to an issue with `proxyReqPathResolver` modifying the path incorrectly, `filter` blocking requests, or an invalid `host` being provided to the proxy.","error":"Proxy requests are not reaching the target server, or receive unexpected 404/500 errors from the target."}],"ecosystem":"npm"}