httpxy

repository·main·Indexed 43 days ago

https://github.com/unjs/httpxy

A full-featured HTTP proxy for Node.js (v0.5.5) that supports proxying fetch requests via proxyFetch, handling WebSocket upgrades with proxyUpgrade, and creating managed proxy instances using createProxyServer. It supports TCP hosts, ports, and Unix sockets, providing extensive configuration for header rewriting, SSL/TLS, and request/response interception through a middleware system and event emitters.

Tokens
9.7K
Snippets
32
Records
40
Agent score
55%

What's inside httpxy

  1. Configure `httpxy` Proxy Server options

    main

    When using createProxyServer, you can pass an options object to control behavior.

    OptionTypeDefaultDescription
    targetstring | URL | ProxyTargetDetailed—Target server URL
    forwardstring | URL—Forward server URL (pipes request without the target's response)
    agenthttp.Agent | falsekeep-aliveShared keep-alive agent. Set false to disable connection reuse
    sslhttps.ServerOptions—Object passed to https.createServer()
    wsbooleanfalseEnable WebSocket proxying
    xfwdbooleanfalseAdd x-forwarded-* headers
    secureboolean—Verify SSL certificates
    toProxybooleanfalsePass absolute URL as path (proxy-to-proxy)
    prependPathbooleantruePrepend the target's path to the proxy path
    ignorePathbooleanfalseIgnore the incoming request path
    localAddressstring—Local interface to bind for outgoing connections
    changeOriginbooleanfalseChange the Host header to match the target URL
    preserveHeaderKeyCasebooleanfalseKeep original letter case of response header keys
    authstring—Basic authentication ('user:password') for Authorization header
    hostRewritestring—Rewrite the Location hostname on redirects (301/302/307/308)
    autoRewritebooleanfalseRewrite Location host/port on redirects based on the request
    protocolRewritestring—Rewrite Location protocol on redirects ('http' or 'https')
    cookieDomainRewritefalse | string | objectfalseRewrite domain of Set-Cookie headers
    cookiePathRewritefalse | string | objectfalseRewrite path of Set-Cookie headers
    headersobject—Extra headers to add to target requests
    proxyTimeoutnumber120000Timeout (ms) for the proxy request to the target
    timeoutnumber—Timeout (ms) for the incoming request
    selfHandleResponsebooleanfalseDisable automatic response piping (handle proxyRes yourself)
    followRedirectsboolean | numberfalseFollow HTTP redirects from target. true = max 5 hops; number = custom max
    bufferstream.Stream—Stream to use as request body instead of the incoming request
  2. Define a ProxyTarget

    main

    A ProxyTarget specifies the destination for proxied requests. It can be provided in three formats:

    1. String: A URL string (e.g., 'http://localhost:3000').
    2. URL: A standard JavaScript URL object.
    3. ProxyTargetDetailed: A configuration object for fine-grained control over the connection, including protocol, host, port, and SSL/TLS settings.

    Use ProxyTargetDetailed when you need to specify specific SSL certificates (cert, key, ca), ciphers, or socket paths for Unix domain sockets.

    // Example using a string
    const target: ProxyTarget = 'https://api.example.com';
    
    // Example using ProxyTargetDetailed for SSL
    const detailedTarget: ProxyTarget = {
      protocol: 'https',
      host: 'api.example.com',
      port: 443,
      cert: 'path/to/cert.pem',
      key: 'path/to/key.pem'
    };
  3. Modify request headers using `proxyReq` event

    main

    You can intercept a request before it is sent to the target by listening to the proxyReq event on the ProxyServer instance. This allows you to inject custom headers into the outgoing request.

    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);
  4. Run a standalone proxy server

    main

    If you don't need to integrate with an existing HTTP server, you can use proxy.listen() to start a standalone proxy server directly.

    import { createProxyServer } from "httpxy";
    
    const proxy = createProxyServer({
      target: "http://localhost:8080",
      changeOrigin: true,
    });
    
    proxy.listen(3000);
  5. Configure an HTTPS Proxy Server

    main

    To run a proxy server over HTTPS, pass an ssl object containing your key and cert to the createProxyServer options. You can also use the secure option to allow self-signed certificates.

    import { readFileSync } from "node:fs";
    import { createProxyServer } from "httpxy";
    
    const proxy = createProxyServer({
      ssl: {
        key: readFileSync("server-key.pem", "utf8"),
        cert: readFileSync("server-cert.pem", "utf8"),
      },
      target: "https://localhost:8443",
      secure: false, // allow self-signed certificates
    });
    
    proxy.listen(3000);
  6. Create a Proxy Server with `createProxyServer`

    main

    Use createProxyServer to create a managed proxy instance. You can then use the .web() method to proxy standard HTTP requests to a target address. This is useful when integrating proxying logic into an existing Node.js HTTP server.

    Example of integrating with a custom server:

    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: "http://127.0.0.1:8080", // target address
        });
      } catch (error) {
        console.error(error);
        res.statusCode = 500;
        res.end("Proxy error: " + error.toString());
      }
    });
    
    server.listen(3000);
    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: "http://127.0.0.1:8080",
        });
      } catch (error) {
        console.error(error);
        res.statusCode = 500;
        res.end("Proxy error: " + error.toString());
      }
    });
    
    server.listen(3000);
  7. Use `proxyUpgrade` for standalone WebSocket proxying

    main

    proxyUpgrade is a standalone WebSocket upgrade proxy. It allows you to forward upgrade requests to a target server without needing a full ProxyServer instance. It returns a Promise<Socket> that resolves with the upstream proxy socket once the connection is established.

    It accepts the same address formats as proxyFetch ("http://host:port", "unix:/path", or { host, port } / { socketPath }).

    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);
  8. Use `proxyFetch` for web-standard proxying

    main

    proxyFetch is a utility that uses web standard (Request/Response) interfaces to forward requests to a specific server address (TCP host/port or Unix socket), bypassing the URL's hostname. It accepts the same input and init arguments as the global fetch and returns a standard Response. Note that redirects are handled manually by default.

    Supported address formats include:

    • URL strings (e.g., http://127.0.0.1:3000 or unix:/tmp/app.sock)
    • Detailed objects (e.g., { host: '127.0.0.1', port: 3000 })
    • Unix socket paths via unix:/path prefix.
    import { proxyFetch } from "httpxy";
    
    // TCP — using a URL string
    const res = await proxyFetch("http://127.0.0.1:3000", "http://example.com/api/data");
    
    // Unix socket — using a URL string
    const res2 = await proxyFetch("unix:/tmp/app.sock", "http://localhost/health");
    
    // Using 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 }),
    });
  9. Configure `x-forwarded-*` headers for WebSockets

    main

    The XHeaders middleware within the WebSocket stack automatically populates x-forwarded-* headers if the xfwd option is enabled in your configuration. It sets the following headers based on the incoming connection:

    • x-forwarded-for: The remote address of the client.
    • x-forwarded-port: The port of the incoming request.
    • x-forwarded-proto: The protocol (ws or wss) based on whether the connection is encrypted.

    These headers are only added if they do not already exist in the request.

  10. Configure ProxyServerOptions

    main

    The ProxyServerOptions interface defines how the proxy server behaves. Key configuration categories include:

    Routing & Path Handling

    • target: The destination URL or object.
    • forward: An alternative destination for requests.
    • prependPath: If true, prepends the target's path to the proxy path.
    • ignorePath: If true, ignores the proxy path of the incoming request.

    Protocol & Security

    • http2: Enables HTTP/2 listener (default: false).
    • ws: Enables WebSocket proxying.
    • secure: Verifies SSL certificates.
    • ssl: Configuration object passed to https.createServer() or http2.createSecureServer().
    • agent: Custom HTTP/HTTPS agent.
    • xfwd: Adds x-forwarded-* headers.
    • changeOrigin: Changes the origin of the Host header to match the target URL.
    • headers: An object of extra headers to add to outgoing requests to the target.
    • cookieDomainRewrite: Rewrites the domain of Set-Cookie headers. Can be false, a string, or a mapping object { [oldDomain: string]: string }.
    • cookiePathRewrite: Rewrites the path of Set-Cookie headers. Can be false, a string, or a mapping object { [oldPath: string]: string }.
    • preserveHeaderKeyCase: Keeps the original letter case of response header keys.

    Redirect & Timeout Management

    • followRedirects: Follows HTTP redirects from the target. Set to true for max 5 hops, or a number for a custom limit.
    • hostRewrite: Rewrites the Location hostname on redirects.
    • autoRewrite: Rewrites the Location host/port on redirects based on the requested host/port.
    • protocolRewrite: Rewrites the Location protocol on redirects.
    • proxyTimeout: Timeout in ms for when the proxy receives no response from the target (default: 120000).
    • timeout: Timeout in ms for incoming requests.

    Advanced Control

    • selfHandleResponse: If true, webOutgoing passes are skipped. You must manually return the response by listening to the proxyRes event.
  11. Configure `proxyUpgrade` via `ProxyUpgradeOptions`

    main

    The ProxyUpgradeOptions object allows you to fine-tune how WebSocket upgrades are proxied.

    OptionTypeDefaultDescription
    xfwdbooleantrueIf true, adds x-forwarded-for, x-forwarded-port, and x-forwarded-proto headers to the request.
    changeOriginbooleanfalseIf true, rewrites the Host header to match the target address.
    headersRecord<string, string>noneExtra headers to include in the upstream upgrade request.
    sslRecord<string, unknown>noneTLS options passed to https.request.
    securebooleantrueWhether to verify upstream TLS certificates.
    agentanyfalseHTTP/HTTPS agent used for the upstream request.
    localAddressstringOS-selectedLocal interface address to bind for upstream connections.
    authstringnoneBasic auth credentials in username:password format.
    prependPathbooleantrueIf true, prepends the target path to the proxied request path.
    ignorePathbooleanfalseIf true, ignores the incoming request path when building the upstream path.
    toProxybooleanfalseIf true, sends the absolute URL in the request path when proxying to another proxy.
  12. Configure `ProxyFetchOptions`

    main

    When calling proxyFetch, you can provide an options object to control how the request is proxied:

    OptionTypeDefaultDescription
    timeoutnumberundefinedTimeout in milliseconds for the upstream request. Rejects with an error if the upstream does not respond within this time.
    xfwdbooleanfalseIf true, adds x-forwarded-for, x-forwarded-port, x-forwarded-proto, and x-forwarded-host headers derived from the input URL.
    changeOriginbooleanfalseIf true, rewrites the Host header to match the target address.
    agentanyfalseHTTP agent for connection pooling/reuse. If false, no keep-alive is used.
    followRedirectsboolean | numberfalseIf true, follows up to 5 hops. If a number is provided, it sets a custom maximum number of hops. If false, raw 3xx responses are returned.
    sslRecord<string, unknown>noneTLS options forwarded to https.request. Use { rejectUnauthorized: false } to skip certificate verification.