SkillAgentSearch skills...

Httpxy

🔀 A Full-Featured HTTP and WebSocket Proxy for Node.js

Install / Use

/learn @unjs/Httpxy
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

🔀 httpxy

[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![bundle][bundle-src]][bundle-href] [![Codecov][codecov-src]][codecov-href]

A Full-Featured HTTP and WebSocket Proxy for Node.js

Proxy Fetch

proxyFetch is a proxy utility with web standard (Request/Response) interfaces. It forwards requests to a specific server address (TCP host/port or Unix socket), bypassing the URL's hostname.

import { proxyFetch } from "httpxy";

// TCP — using a URL string
const res = await proxyFetch("http://127.0.0.1:3000", "http://example.com/api/data");
console.log(await res.json());

// Unix socket — using a URL string
const res2 = await proxyFetch("unix:/tmp/app.sock", "http://localhost/health");
console.log(await res2.text());

// Or use an object for more control
const res3 = await proxyFetch({ host: "127.0.0.1", port: 3000 }, "http://example.com/api/data");

// Using a Request object
const req = new Request("http://example.com/api/data", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ key: "value" }),
});
const res4 = await proxyFetch("http://127.0.0.1:3000", req);

// Using a URL string with RequestInit
const res5 = await proxyFetch("http://127.0.0.1:3000", "http://example.com/api/data", {
  method: "PUT",
  headers: { Authorization: "Bearer token" },
  body: JSON.stringify({ updated: true }),
});

It accepts the same input and init arguments as the global fetch, including Request objects and streaming bodies, and returns a standard Response. Redirects are handled manually by default.

Proxy Upgrade

proxyUpgrade is a standalone WebSocket upgrade proxy. It forwards upgrade requests to a target server without needing a ProxyServer instance — the WebSocket counterpart to proxyFetch.

import { createServer } from "node:http";
import { proxyUpgrade } from "httpxy";

const server = createServer((req, res) => {
  // Handle regular HTTP requests...
});

server.on("upgrade", (req, socket, head) => {
  proxyUpgrade("http://127.0.0.1:8080", req, socket, head);
});

server.listen(3000);

It accepts the same addr formats as proxyFetch ("http://host:port", "unix:/path", or { host, port } / { socketPath }), and returns a Promise<Socket> that resolves with the upstream proxy socket once the WebSocket connection is established.

// With options
server.on("upgrade", (req, socket, head) => {
  proxyUpgrade({ host: "127.0.0.1", port: 8080 }, req, socket, head, {
    // changeOrigin: true, // rewrite Host header
    // xfwd: false, // disable x-forwarded-* headers (enabled by default)
  });
});

Proxy Server

[!NOTE] Proxy server was originally forked from http-party/node-http-proxy.

Create proxy:

import { createServer } from "node:http";
import { createProxyServer } from "httpxy";

const proxy = createProxyServer({});

const server = createServer(async (req, res) => {
  try {
    await proxy.web(req, res, {
      target: address /* address of your proxy server here */,
    });
  } catch (error) {
    console.error(error);
    res.statusCode = 500;
    res.end("Proxy error: " + error.toString());
  }
});

server.listen(3000, () => {
  console.log("Proxy is listening on http://localhost:3000");
});

Options

| Option | Type | Default | Description | | ----------------------- | -------------------------------------- | -------- | --------------------------------------------------------------------------- | | target | string \| URL \| ProxyTargetDetailed | — | Target server URL | | forward | string \| URL | — | Forward server URL (pipes request without the target's response) | | agent | http.Agent | — | Object passed to http(s).request for connection pooling | | ssl | https.ServerOptions | — | Object passed to https.createServer() | | ws | boolean | false | Enable WebSocket proxying | | xfwd | boolean | false | Add x-forwarded-* headers | | secure | boolean | — | Verify SSL certificates | | toProxy | boolean | false | Pass absolute URL as path (proxy-to-proxy) | | prependPath | boolean | true | Prepend the target's path to the proxy path | | ignorePath | boolean | false | Ignore the incoming request path | | localAddress | string | — | Local interface to bind for outgoing connections | | changeOrigin | boolean | false | Change the Host header to match the target URL | | preserveHeaderKeyCase | boolean | false | Keep original letter case of response header keys | | auth | string | — | Basic authentication ('user:password') for Authorization header | | hostRewrite | string | — | Rewrite the Location hostname on redirects (301/302/307/308) | | autoRewrite | boolean | false | Rewrite Location host/port on redirects based on the request | | protocolRewrite | string | — | Rewrite Location protocol on redirects ('http' or 'https') | | cookieDomainRewrite | false \| string \| object | false | Rewrite domain of Set-Cookie headers | | cookiePathRewrite | false \| string \| object | false | Rewrite path of Set-Cookie headers | | headers | object | — | Extra headers to add to target requests | | proxyTimeout | number | 120000 | Timeout (ms) for the proxy request to the target | | timeout | number | — | Timeout (ms) for the incoming request | | selfHandleResponse | boolean | false | Disable automatic response piping (handle proxyRes yourself) | | followRedirects | boolean \| number | false | Follow HTTP redirects from target. true = max 5 hops; number = custom max | | buffer | stream.Stream | — | Stream to use as request body instead of the incoming request |

Events

| Event | Arguments | Description | | ------------ | ---------------------------------------- | ------------------------------------------------------ | | error | (err, req, res, target) | An error occurred during proxying | | proxyReq | (proxyReq, req, res, options) | Before request is sent to target (modify headers here) | | proxyRes | (proxyRes, req, res) | Response received from target | | proxyReqWs | (proxyReq, req, socket, options, head) | Before WebSocket upgrade request is sent | | open | (proxySocket) | WebSocket connection opened | | close | (proxyRes, proxySocket, proxyHead) | WebSocket connection closed | | start | (req, res, target) | Proxy processing started | | end | (req, res, proxyRes) | Proxy request completed |

Examples

HTTP Proxy

import { createServer } from "node:http";
import { createProxyServer } from "httpxy";

const proxy = createProxyServer({});

const server = createServer(async (req, res) => {
  await proxy.web(req, res, { target: "http://localhost:8080" });
});

server.listen(3000);

WebSocket Proxy

import { createServer } from "node:http";
import { createProxyServer } from "httpxy";

const proxy = createProxyServer({ target: "http://localhost:8080", ws: true });

const server = createServer(async (req, res) => {
  await proxy.web(req, res);
});

server.on("upgrade", (req, socket, head) => {
  proxy.ws(req, socket, { target: "http://localhost:8080" }, head);
});

server.listen(3000);

Modify Request Headers

import { createServer } from "node:http";
import { createProxyServer } from "httpxy";

const proxy = createProxyServer({ target: "http://localhost:8080" });

proxy.on("proxyReq", (proxyReq) => {
  proxyReq.setHeader("X-Forwarded-By", "httpxy");
});

const server = createServer(async (req, res) => {
  await proxy.web(req, res);
});

server.listen(3000);

HTTPS Proxy

import 
View on GitHub
GitHub Stars277
CategoryDevelopment
Updated15d ago
Forks20

Languages

TypeScript

Security Score

80/100

Audited on Mar 9, 2026

No findings