From f3f3d7df5bc31df339c421cb017bd79baf8827f3 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Tue, 13 Sep 2022 11:38:42 -0700 Subject: [PATCH] [cli] Replace "0.0.0.0" with "localhost" in `vc dev` (#8547) Instead of replacing "127.0.0.1" in `vc dev`, replace "0.0.0.0" when rendering the URL to access the `vc dev` server. The thought here is that the IPv6 form is replacing the catch-all host name (`::`), but the IPv4 version is only replacing the explicit "127.0.0.1" version, so there's an inconsistency. Considering the catch-all host names are not usually intended to be routable anyways, we will fix the inconsistency by only replacing the catch-all versions instead of localhost. Also, since Node.js will default to binding to the catch-all address when not explicitly specifying a host, this replacement will only happen in that case. If the user is explicitly specifing a host to bind to (i.e. `vc dev -l 127.0.0.1:8080` or `vc dev -l tcp://[::1]:8080`) then it makes more sense to print explicitly what the user specified. --- packages/cli/src/commands/dev/dev.ts | 2 +- packages/cli/src/util/dev/parse-listen.ts | 9 +++++---- packages/cli/src/util/dev/server.ts | 5 ++--- .../cli/test/unit/util/dev/parse-listen.test.ts | 17 ++++++++++++++++- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/cli/src/commands/dev/dev.ts b/packages/cli/src/commands/dev/dev.ts index ccdf78f06..42e0af5fd 100644 --- a/packages/cli/src/commands/dev/dev.ts +++ b/packages/cli/src/commands/dev/dev.ts @@ -2,7 +2,7 @@ import { resolve, join } from 'path'; import fs from 'fs-extra'; import DevServer from '../../util/dev/server'; -import parseListen from '../../util/dev/parse-listen'; +import { parseListen } from '../../util/dev/parse-listen'; import { ProjectEnvVariable } from '../../types'; import Client from '../../util/client'; import { getLinkedProject } from '../../util/projects/link'; diff --git a/packages/cli/src/util/dev/parse-listen.ts b/packages/cli/src/util/dev/parse-listen.ts index ca6ac4875..0b3556bc0 100644 --- a/packages/cli/src/util/dev/parse-listen.ts +++ b/packages/cli/src/util/dev/parse-listen.ts @@ -1,10 +1,7 @@ import { parse } from 'url'; import { ListenSpec } from './types'; -export default function parseListen( - str: string, - defaultPort = 3000 -): ListenSpec { +export function parseListen(str: string, defaultPort = 3000): ListenSpec { let port = Number(str); if (!isNaN(port)) { @@ -50,3 +47,7 @@ export default function parseListen( ); } } + +export function replaceLocalhost(address: string): string { + return address.replace('[::]', 'localhost').replace('0.0.0.0', 'localhost'); +} diff --git a/packages/cli/src/util/dev/server.ts b/packages/cli/src/util/dev/server.ts index 92b3ab721..13e28dff7 100644 --- a/packages/cli/src/util/dev/server.ts +++ b/packages/cli/src/util/dev/server.ts @@ -103,6 +103,7 @@ import { } from '../is-error'; import isURL from './is-url'; import { pickOverrides } from '../projects/project-settings'; +import { replaceLocalhost } from './parse-listen'; const frontendRuntimeSet = new Set( frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build') @@ -930,9 +931,7 @@ export default class DevServer { } } - this._address = new URL( - address.replace('[::]', 'localhost').replace('127.0.0.1', 'localhost') - ); + this._address = new URL(replaceLocalhost(address)); const vercelConfig = await this.getVercelConfig(); const devCommandPromise = this.runDevCommand(); diff --git a/packages/cli/test/unit/util/dev/parse-listen.test.ts b/packages/cli/test/unit/util/dev/parse-listen.test.ts index 9d3f36d09..b37c2fecb 100644 --- a/packages/cli/test/unit/util/dev/parse-listen.test.ts +++ b/packages/cli/test/unit/util/dev/parse-listen.test.ts @@ -1,4 +1,7 @@ -import parseListen from '../../../../src/util/dev/parse-listen'; +import { + parseListen, + replaceLocalhost, +} from '../../../../src/util/dev/parse-listen'; const IS_WINDOWS = process.platform === 'win32'; @@ -69,3 +72,15 @@ describe('parseListen', () => { expect(err.message).toEqual('Unknown `--listen` scheme (protocol): bad:'); }); }); + +describe('replaceLocalhost', () => { + test.each([ + { input: 'http://192.168.0.1:1234', output: 'http://192.168.0.1:1234' }, + { input: 'http://127.0.0.1:4000', output: 'http://127.0.0.1:4000' }, + { input: 'http://[::1]:3001', output: 'http://[::1]:3001' }, + { input: 'http://0.0.0.0:3000', output: 'http://localhost:3000' }, + { input: 'http://[::]:3002', output: 'http://localhost:3002' }, + ])('"$input" → "$output"', ({ input, output }) => { + expect(replaceLocalhost(input)).toEqual(output); + }); +});