portless 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,7 +53,7 @@ portless docs.myapp next dev
53
53
  # -> http://docs.myapp.localhost:1355
54
54
  ```
55
55
 
56
- Wildcard subdomain routing: any subdomain of a registered route routes to that app automatically (e.g. `tenant1.myapp.localhost:1355` routes to the `myapp` app without extra registration).
56
+ By default, only explicitly registered subdomains are routed (strict mode). Use `--wildcard` when starting the proxy to allow any subdomain of a registered route to fall back to that app (e.g. `tenant1.myapp.localhost:1355` routes to the `myapp` app without extra registration).
57
57
 
58
58
  ## Git Worktrees
59
59
 
@@ -152,6 +152,7 @@ portless proxy start # Start the proxy (port 1355, daemon)
152
152
  portless proxy start --https # Start with HTTP/2 + TLS
153
153
  portless proxy start -p 80 # Start on port 80 (requires sudo)
154
154
  portless proxy start --foreground # Start in foreground (for debugging)
155
+ portless proxy start --wildcard # Allow unregistered subdomains to fall back to parent
155
156
  portless proxy stop # Stop the proxy
156
157
  ```
157
158
 
@@ -165,6 +166,7 @@ portless proxy stop # Stop the proxy
165
166
  --no-tls Disable HTTPS (overrides PORTLESS_HTTPS)
166
167
  --foreground Run proxy in foreground instead of daemon
167
168
  --tld <tld> Use a custom TLD instead of .localhost (e.g. test)
169
+ --wildcard Allow unregistered subdomains to fall back to parent route
168
170
  --app-port <number> Use a fixed port for the app (skip auto-assignment)
169
171
  --force Override a route registered by another process
170
172
  --name <name> Use <name> as the app name
@@ -178,6 +180,7 @@ PORTLESS_PORT=<number> Override the default proxy port
178
180
  PORTLESS_APP_PORT=<number> Use a fixed port for the app (same as --app-port)
179
181
  PORTLESS_HTTPS=1 Always enable HTTPS
180
182
  PORTLESS_TLD=<tld> Use a custom TLD (e.g. test; default: localhost)
183
+ PORTLESS_WILDCARD=1 Allow unregistered subdomains to fall back to parent route
181
184
  PORTLESS_SYNC_HOSTS=1 Auto-sync /etc/hosts (auto-enabled for custom TLDs)
182
185
  PORTLESS_STATE_DIR=<path> Override the state directory
183
186
 
@@ -300,14 +300,15 @@ function buildForwardedHeaders(req, tls) {
300
300
  }
301
301
  var PORTLESS_HOPS_HEADER = "x-portless-hops";
302
302
  var MAX_PROXY_HOPS = 5;
303
- function findRoute(routes, host) {
304
- return routes.find((r) => r.hostname === host) || routes.find((r) => host.endsWith("." + r.hostname));
303
+ function findRoute(routes, host, strict) {
304
+ return routes.find((r) => r.hostname === host) || (strict ? void 0 : routes.find((r) => host.endsWith("." + r.hostname)));
305
305
  }
306
306
  function createProxyServer(options) {
307
307
  const {
308
308
  getRoutes,
309
309
  proxyPort,
310
310
  tld = "localhost",
311
+ strict = true,
311
312
  onError = (msg) => console.error(msg),
312
313
  tls
313
314
  } = options;
@@ -342,7 +343,7 @@ function createProxyServer(options) {
342
343
  );
343
344
  return;
344
345
  }
345
- const route = findRoute(routes, host);
346
+ const route = findRoute(routes, host, strict);
346
347
  if (!route) {
347
348
  const safeHost = escapeHtml(host);
348
349
  const strippedHost = host.endsWith(tldSuffix) ? host.slice(0, -tldSuffix.length) : host;
@@ -436,7 +437,7 @@ function createProxyServer(options) {
436
437
  }
437
438
  const routes = getRoutes();
438
439
  const host = getRequestHost(req).split(":")[0];
439
- const route = findRoute(routes, host);
440
+ const route = findRoute(routes, host, strict);
440
441
  if (!route) {
441
442
  socket.destroy();
442
443
  return;
@@ -748,6 +749,10 @@ function isHttpsEnvEnabled() {
748
749
  const val = process.env.PORTLESS_HTTPS;
749
750
  return val === "1" || val === "true";
750
751
  }
752
+ function isWildcardEnvEnabled() {
753
+ const val = process.env.PORTLESS_WILDCARD;
754
+ return val === "1" || val === "true";
755
+ }
751
756
  async function discoverState() {
752
757
  if (process.env.PORTLESS_STATE_DIR) {
753
758
  const dir = process.env.PORTLESS_STATE_DIR;
@@ -905,11 +910,20 @@ function augmentedPath(env) {
905
910
  return allBins.join(path2.delimiter) + path2.delimiter + base;
906
911
  }
907
912
  function spawnCommand(commandArgs, options) {
908
- const env = { ...options?.env ?? process.env, PATH: augmentedPath(options?.env) };
909
- const child = isWindows2 ? spawn(commandArgs[0], commandArgs.slice(1), {
913
+ const env = {
914
+ ...options?.env ?? process.env,
915
+ PATH: augmentedPath(options?.env)
916
+ };
917
+ if (isWindows2) {
918
+ for (const key of Object.keys(env)) {
919
+ if (key !== "PATH" && key.toUpperCase() === "PATH") {
920
+ delete env[key];
921
+ }
922
+ }
923
+ }
924
+ const child = isWindows2 ? spawn("cmd.exe", ["/d", "/s", "/c", commandArgs.join(" ")], {
910
925
  stdio: "inherit",
911
- env,
912
- shell: true
926
+ env
913
927
  }) : spawn("/bin/sh", ["-c", commandArgs.map(shellEscape).join(" ")], {
914
928
  stdio: "inherit",
915
929
  env
@@ -1225,6 +1239,7 @@ export {
1225
1239
  writeTldFile,
1226
1240
  getDefaultTld,
1227
1241
  isHttpsEnvEnabled,
1242
+ isWildcardEnvEnabled,
1228
1243
  discoverState,
1229
1244
  findFreePort,
1230
1245
  isProxyRunning,