express-http-proxy
Express/Connect middleware that proxies requests to another host, with promise-based hooks for decorating and filtering requests and responses.
Repository Health
Technical Analysis
express-http-proxy is a middleware for Express and Connect applications that forwards incoming requests to another host and pipes the response back to the original caller. It breaks the proxy lifecycle into a series of discrete, swappable steps — resolving the target host, decorating the outgoing request, streaming or buffering the response, and rewriting headers — each of which can be overridden with a small decorator function.
Most of its hooks (filter, proxyReqOptDecorator, proxyReqBodyDecorator, proxyReqPathResolver, userResDecorator) support both plain return values and Promises, which makes it straightforward to wire in async logic like looking up a routing target from a database, or transforming a response body after an upstream async call. Requests and responses are streamed by default for performance, and the library automatically falls back to buffered mode when a response decorator needs to inspect or rewrite the body.
What You Get
- A
proxy(host, options)middleware factory that mounts directly on any Express route or app - Async-capable hooks for filtering requests, resolving proxy paths/hosts, and decorating request/response bodies and headers
- Automatic streaming of requests and responses, with buffered mode kicking in only when a response decorator is present
- Built-in body size limiting (
limitoption) with a413response when exceeded - Support for dynamic proxy targets via a function argument, with optional per-request re-evaluation (
memoizeHost: false) - A
skipToNextHandlerFilterhook to fall through to the next Express handler instead of returning the proxied response
Common Use Cases
- Proxying API requests from a frontend dev server to a backend service during local development
- Building a lightweight API gateway that rewrites paths, injects headers, or aggregates multiple backend services behind one Express app
- Mocking or intercepting third-party API responses in tests by rewriting response bodies with
userResDecorator - Load-splitting or A/B routing traffic across multiple backend hosts using a dynamic host-resolver function
Under The Hood
Architecture
The module (index.js) composes the proxy lifecycle as a promise chain over a set of discrete step functions in app/steps/ (filterUserRequest, buildProxyReq, resolveProxyHost, decorateProxyReqOpts, resolveProxyReqPath, decorateProxyReqBody, prepareProxyReq, sendProxyRequest, maybeSkipToNextHandler, copyProxyResHeadersToUserRes, decorateUserResHeaders, decorateUserRes, sendUserRes), each receiving and returning a shared ScopeContainer instance (lib/scopeContainer.js) that carries the request, response, next, host, and resolved options through the chain. This step-pipeline design means the library’s core control flow is a single readable .then() chain in index.js, and any individual stage can be swapped by supplying the corresponding option (e.g. proxyReqPathResolver, userResDecorator) without touching the pipeline itself — a clean separation of orchestration from behavior. A rejected promise short-circuits the chain and is routed to handleProxyErrors or a user-supplied proxyErrorHandler, while a rejection with no error value is treated as an intentional bail-out to next().
Tech Stack
The library is plain Node.js/CommonJS with a minimal runtime dependency footprint: debug for namespaced logging, es6-promise as a Promise polyfill for older Node targets, and raw-body for reading and size-limiting the incoming request body. It has no build step — index.js is the published entry point directly. Development tooling includes Mocha for the test runner, Chai and Supertest for assertions and HTTP integration testing, nock for stubbing upstream HTTP responses, ESLint for linting, and nyc for coverage reporting; CI is wired through Travis.
Code Quality
The test/ directory contains over 30 spec files, each named after and mirroring a step module (filter.js, host.js, postBody.js, streaming.js, etc.), giving the library close to one-to-one test coverage of its internal pipeline stages, run via Mocha with Supertest driving real Express apps and nock stubbing the proxied backend. Error handling is centralized in a dedicated handleProxyErrors step rather than scattered try/catch blocks, and the codebase favors small single-responsibility files (most step modules are under 100 lines) with consistent camelCase naming. The project is plain JavaScript with no static types, but ESLint enforces a consistent style, and the lint script runs as part of npm test.
What Makes It Unique Rather than exposing one large configuration object with mutually exclusive flags, express-http-proxy models proxying as an explicit, ordered pipeline of independently overridable steps, each with first-class Promise support — letting consumers inject async logic (e.g. an async host lookup or a database-backed path resolver) at precisely the stage where it’s needed, without forking the whole request-handling flow. The automatic switch between streaming and buffered response modes based on whether a response decorator is registered is a deliberate performance/flexibility tradeoff exposed transparently to the caller.
Used by 2 apps in this directory
overleaf
Collaboration · Productivity
Open-source, real-time collaborative LaTeX editor with sandboxed compilation and full TeXLive support for self-hosted academic and research teams.
ToolJet
Low Code Platforms · No Code Platforms · AI Agents
Open-source AI-native platform to build and deploy internal tools, workflows, and AI agents with a visual drag-and-drop builder and 80+ data source integrations.