Node.js HTTP/WebSocket Programmable Proxy
http-proxy is a robust and programmable HTTP proxying library for Node.js, designed to facilitate the creation of components such as reverse proxies and load balancers. It offers comprehensive support for both HTTP(S) and WebSockets. The current stable version is 1.18.1. While its release cadence is not rapid, the project undergoes periodic maintenance, as highlighted by the 1.17.0 release which delivered numerous bug fixes and feature additions, indicating active, albeit slower, development. A key differentiator is its `createProxyServer` factory, which returns a flexible proxy instance, allowing developers to customize request and response pipelines for fine-grained control over proxied traffic, making it suitable for complex proxying scenarios beyond basic URL forwarding.
Common errors
-
Error: Must provide a target protocol and host (e.g. http://localhost)
cause The `target` option in the `createProxyServer` constructor or `proxy.web`/`proxy.ws` calls is either missing or malformed.fixEnsure the `target` option is a string with a valid protocol and host (e.g., `'http://localhost:3000'`) or an object specifying `host` and `port`. -
TypeError: proxy.web is not a function
cause This usually means you're trying to call `web` on the `httpProxy` module object itself (e.g., `httpProxy.web(...)`) rather than on an instance created by `httpProxy.createProxyServer()`.fixFirst, create a proxy instance: `const proxy = httpProxy.createProxyServer(options);`. Then, call `proxy.web(req, res);` on that instance. -
Error: connect ECONNREFUSED 127.0.0.1:9000
cause The target server specified in the `target` option is not running or is inaccessible at the given host and port, preventing `http-proxy` from establishing a connection.fixVerify that your target server is actively running and listening on the specified host and port. Check firewall rules if the target is on a different machine or network.
Warnings
- breaking Major breaking changes were introduced after the 0.8.x series. Direct migration from these older versions to 1.x.x without consulting the `UPGRADING.md` guide will likely result in compatibility issues.
- gotcha Proxy errors must be explicitly handled, either by listening to the `error` event on the proxy instance or by providing an error callback to `proxy.web` or `proxy.ws` calls. Unhandled errors can lead to ungraceful server shutdowns or unresponsiveness.
- gotcha The `target` option is mandatory for `proxy.web` and `proxy.ws` calls, specifying the destination URL for the proxied request. Omitting or providing an invalid target will result in connection errors and prevent successful proxying.
Install
-
npm install http-proxy -
yarn add http-proxy -
pnpm add http-proxy
Imports
- httpProxy (Module Object, CommonJS)
import httpProxy from 'http-proxy';
const httpProxy = require('http-proxy'); - httpProxy (Module Object, ESM)
const httpProxy = require('http-proxy');import httpProxy from 'http-proxy';
- createProxyServer (Factory Function, CommonJS Destructuring)
const createProxyServer = require('http-proxy').createProxyServer;const { createProxyServer } = require('http-proxy'); - createProxyServer (Factory Function, ESM Named Import)
import createProxyServer from 'http-proxy';
import { createProxyServer } from 'http-proxy';
Quickstart
const http = require('http');
const httpProxy = require('http-proxy');
// --- Target Server ---
const targetPort = 9000;
const targetServer = http.createServer((req, res) => {
console.log(`[Target] Received request for: ${req.url}`);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`Hello from Target Server! You requested ${req.url}\n`);
});
targetServer.listen(targetPort, () => {
console.log(`[Target] Server listening on http://localhost:${targetPort}`);
});
// --- Proxy Server ---
const proxyPort = 8000;
const proxy = httpProxy.createProxyServer({
target: `http://localhost:${targetPort}`,
ws: true // Enable WebSocket proxying
});
proxy.on('error', (err, req, res) => {
console.error('[Proxy] HTTP error:', err.message);
if (!res.headersSent) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Proxy Error: Could not reach the target.');
}
});
proxy.on('proxyReq', (proxyReq, req, res, options) => {
console.log(`[Proxy] Proxying HTTP request: ${req.method} ${req.url}`);
});
proxy.on('proxyRes', (proxyRes, req, res) => {
console.log(`[Proxy] Response from target: ${proxyRes.statusCode}`);
});
const proxyServer = http.createServer((req, res) => {
// Handle regular HTTP(S) requests
proxy.web(req, res);
});
proxyServer.on('upgrade', (req, socket, head) => {
// Handle WebSocket upgrade requests
console.log(`[Proxy] Proxying WebSocket upgrade for: ${req.url}`);
proxy.ws(req, socket, head);
});
proxyServer.listen(proxyPort, () => {
console.log(`[Proxy] Server listening on http://localhost:${proxyPort}`);
console.log(`
Test HTTP by visiting: http://localhost:${proxyPort}/any/path`);
console.log(`Test WebSocket (e.g., with 'wscat'): wscat -c ws://localhost:${proxyPort}`);
});
// Clean up on exit
process.on('SIGINT', () => {
console.log('\n[App] Shutting down servers...');
proxyServer.close(() => console.log('[Proxy] Server closed.'));
targetServer.close(() => console.log('[Target] Server closed.'));
process.exit(0);
});