ReviewOS

stacks/rpx

Single port - multiple proxies

#54
Closed upeguiborja opened this 11 days ago ·
11 days ago

Clear and concise description of the problem

As a developer I want to access different proxied paths and/or subdomains without having to add different ports for each.

Right now @stacksjs/rpx creates different listeners on different ports

import startProxies, { MultiProxyConfig } from "@stacksjs/rpx";

const config: MultiProxyConfig = {
  https: true,
  cleanup: {
    hosts: true,
    certs: true,
  },
  cleanUrls: false,
  vitePluginUsage: false,

  proxies: [
    {
      from: "localhost:3000",
      to: "foo.myservice.local",
      cleanUrls: true,
    },
    {
      from: "localhost:3001",
      to: "myservice.local/bar",
      cleanUrls: false,
    },
    {
      from: "localhost:3003",
      to: "*.myservice.local",
      cleanUrls: true,
    },
  ],

  verbose: false,
};

startProxies(config);

Output:

  rpx v0.10.0

  ➜  localhost:3000 ➜ https://foo.myservice.local
  ➜  SSL enabled with:
     - TLS 1.2/1.3
     - Modern cipher suite
     - HTTP/2 enabled
     - HSTS enabled

 WARN  Port 80 is in use, HTTP to HTTPS redirect will not be available                                                                                                                   10:25:39 PM


 WARN  Port 443 is in use. Using port 8443 instead.                                                                                                                                      10:25:39 PM

ℹ You can use 'sudo lsof -i :443' (Unix) or 'netstat -ano | findstr :443' (Windows) to check what's using the port.                                                                     10:25:39 PM

  rpx v0.10.0

  ➜  localhost:3001 ➜ https://myservice.local
  ➜  Listening on port 8443
  ➜  SSL enabled with:
     - TLS 1.2/1.3
     - Modern cipher suite
     - HTTP/2 enabled
     - HSTS enabled

 WARN  Port 80 is in use, HTTP to HTTPS redirect will not be available                                                                                                                   10:25:39 PM


 WARN  Port 443 is in use. Using port 8444 instead.                                                                                                                                      10:25:39 PM

ℹ You can use 'sudo lsof -i :443' (Unix) or 'netstat -ano | findstr :443' (Windows) to check what's using the port.                                                                     10:25:39 PM

  rpx v0.10.0

  ➜  localhost:3003 ➜ *.myservice.local"
  ➜  Listening on port 8444
  ➜  SSL enabled with:
     - TLS 1.2/1.3
     - Modern cipher suite
     - HTTP/2 enabled
     - HSTS enabled

It created 3 different servers listening on ports 80, 443, 8443 and 8444.

Suggested solution

Add a singlePortMode parameter that starts only one server in a configurable port (default to 80 and 443) and proxies all traffic based on the from parameter patterns.

Alternative

No response

Additional context

No response

Validations

11 days ago

Implemented in 128c33e — singlePortMode is now supported! 🎉

By default rpx binds one listener per proxy (:443, then :8443, :8444, … when a port is taken), which is exactly the scattering you hit. Setting singlePortMode: true collapses every proxy onto one shared listener and routes each request to the right upstream by its Host header (and path). The port is configurable via httpPort (default 80) and httpsPort (default 443):

import startProxies, { MultiProxyConfig } from "@stacksjs/rpx"

const config: MultiProxyConfig = {
  https: false,
  singlePortMode: true,
  httpPort: 8080,   // shared HTTP listener + redirect port
  httpsPort: 8443,  // shared HTTPS listener port
  proxies: [
    { from: "localhost:3000", to: "foo.myservice.local" },
    { from: "localhost:3001", to: "bar.myservice.local" },
    { from: "localhost:3003", to: "*.myservice.local" },
  ],
}

startProxies(config)

Or from the CLI:

rpx start --single-port-mode --https-port 8443

Now all three domains are served from a single port instead of :443/:8443/:8444.

A note for anyone landing here: when HTTPS is enabled and you configure more than one proxy, rpx already shares a single :443 listener automatically and routes by Host. singlePortMode extends that to the HTTP-only and single-proxy cases and makes the port configurable.

Shipped with routing tests (multiple domains + path-based routing through one port) and docs under Multiple Proxies → Single-Port Mode. Thanks for the detailed write-up, @upeguiborja!

Sign in to comment on this issue.