HTTP/2 & HTTP/1.1 Proxy for Node.js

5.0.53 · active · verified Wed Apr 22

http2-proxy is a robust Node.js library engineered to serve as a high-performance proxy for both HTTP/2 and HTTP/1.1 traffic, including support for WebSocket connections. Currently at version 5.0.53, the library maintains an active development status, though its major version release cadence appears irregular, with a significant jump from 1.x to 5.x. A core differentiator is its adherence to HTTP specifications, automatically managing critical headers such as hop-by-hop, connection, via, and forward. It is designed to be fully compatible with Node.js's async/await paradigm, with callback-based usage being an optional but discouraged alternative. A notable feature is its resilience during 503 errors, where it's safe to assume no data was read or written, enabling reliable request retries for all methods, including non-idempotent ones. Users are responsible for implementing their own final and error handlers, as the library does not perform automatic cleanup of errored responses, which provides flexibility for custom retry mechanisms. It requires Node.js v10.0.0 or higher to function correctly. The package also integrates seamlessly with common middleware frameworks like Connect and security libraries like Helmet.

Common errors

Warnings

Install

Imports

Quickstart

This code sets up an HTTP/2 server that also accepts HTTP/1.1 connections. It then proxies both HTTP and WebSocket requests to a specified target hostname and port, demonstrating error handling and optional request/response modification.

import http2 from 'http2';
import proxy from 'http2-proxy';
import finalhandler from 'finalhandler';

const port = 8000;
const targetHostname = 'localhost';
const targetPort = 9001; // Ensure a backend server is running on this port for testing

const defaultWebHandler = (err, req, res) => {
  if (err) {
    console.error('HTTP proxy error:', err.message); // Log error message for clarity
    if (!res.headersSent) {
      finalhandler(req, res)(err);
    } else {
      // If headers already sent, just end the response to prevent further errors
      res.end();
    }
  }
};

const defaultWsHandler = (err, req, socket, head) => {
  if (err) {
    console.error('WebSocket proxy error:', err.message);
    socket.destroy();
  }
};

const server = http2.createServer({ allowHTTP1: true });

server.on('request', (req, res) => {
  proxy.web(req, res, {
    hostname: targetHostname,
    port: targetPort,
    // Optional: Add custom headers to the request sent to the target
    onReq: (proxyReq, options) => {
      options.headers['x-forwarded-for'] = req.socket.remoteAddress;
      options.headers['x-custom-proxy-header'] = 'http2-proxy-example';
    },
    // Optional: Modify the response from the target before sending to client
    onRes: (req, res, proxyRes) => {
      res.setHeader('x-proxied-by', 'http2-proxy');
      res.writeHead(proxyRes.statusCode, proxyRes.headers);
      proxyRes.pipe(res);
    }
  }, defaultWebHandler);
});

server.on('upgrade', (req, socket, head) => {
  proxy.ws(req, socket, head, {
    hostname: targetHostname,
    port: targetPort
  }, defaultWsHandler);
});

server.listen(port, () => {
  console.log(`Proxy server listening on port ${port}`);
  console.log(`Proxying HTTP and WebSocket requests to ${targetHostname}:${targetPort}`);
});

view raw JSON →