From 1b9583969eedda7c87b0f314d87d70a5840a62c5 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 2 Aug 2026 08:30:14 +0000 Subject: [PATCH] fix(dev): restore isolated environment host defaults --- packages/nuxt-cli/src/dev/listen.ts | 3 ++- packages/nuxt-cli/test/unit/listen.spec.ts | 25 +++++++++++++++++++ .../test/unit/terminal-output.spec.ts | 8 +++--- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/packages/nuxt-cli/src/dev/listen.ts b/packages/nuxt-cli/src/dev/listen.ts index bba697aee..12b6020e6 100644 --- a/packages/nuxt-cli/src/dev/listen.ts +++ b/packages/nuxt-cli/src/dev/listen.ts @@ -152,7 +152,8 @@ function createSecureServer(certificate: ResolvedCertificate, handler: RequestLi } export async function listen(handler: RequestListener, options: ListenOptions = {}): Promise { - const hostname = validateHostname(options.hostname, options.public) ?? (options.public ? '' : 'localhost') + const isolatedEnvironment = options.hostname === undefined && !options.public && detectIsolatedEnvironment() + const hostname = validateHostname(options.hostname, options.public) ?? (options.public || isolatedEnvironment ? '' : 'localhost') const requestedPort = options.port === undefined || options.port === '' ? undefined : Number(options.port) const port = options.handover && requestedPort diff --git a/packages/nuxt-cli/test/unit/listen.spec.ts b/packages/nuxt-cli/test/unit/listen.spec.ts index afe9e49ad..04a9c90af 100644 --- a/packages/nuxt-cli/test/unit/listen.spec.ts +++ b/packages/nuxt-cli/test/unit/listen.spec.ts @@ -1,5 +1,6 @@ import type { Listener } from '../../src/dev/listen' +import { connect } from 'node:net' import { networkInterfaces } from 'node:os' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' @@ -7,8 +8,13 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { copyURL, formatDisplayURL, getNetworkAddresses, isReusePortSupported, listen, openBrowser, resolveOpenCommand, validateHostname } from '../../src/dev/listen' const writeText = vi.hoisted(() => vi.fn()) +const isolatedEnvironment = vi.hoisted(() => ({ current: undefined as string | undefined })) vi.mock('tinyclip', () => ({ writeText })) +vi.mock('../../src/dev/environment', () => ({ + detectIsolatedEnvironment: () => isolatedEnvironment.current, + isWsl: (platform: NodeJS.Platform, env: NodeJS.ProcessEnv) => platform === 'linux' && !!env.WSL_DISTRO_NAME, +})) const spawn = vi.hoisted(() => vi.fn((_command: string, _args: string[]) => ({ once: () => {}, @@ -146,6 +152,7 @@ describe('listen', () => { afterEach(async () => { restoreEnvironment() + isolatedEnvironment.current = undefined await Promise.all(listeners.splice(0).map(listener => listener.close())) }) @@ -155,6 +162,24 @@ describe('listen', () => { return listener } + it('should accept connections on both loopback addresses in an isolated environment', async () => { + isolatedEnvironment.current = 'the container' + const listener = await start({ port: 0 }) + const request = (host: string) => new Promise((resolve, reject) => { + const socket = connect({ host, port: listener.address.port }, () => socket.write('GET / HTTP/1.0\r\n\r\n')) + let response = '' + socket.setEncoding('utf8') + socket.on('data', chunk => response += chunk) + socket.on('end', () => resolve(response)) + socket.on('error', reject) + }) + + const responses = await Promise.all([request('127.0.0.1'), request('::1')]) + + expect(responses.every(response => response.endsWith('\r\n\r\nok'))).toBe(true) + expect(listener.url).toBe(`http://localhost:${listener.address.port}/`) + }) + it('should fall back to another port by default', async () => { const first = await start({ port: 0 }) const second = await start({ port: first.address.port }) diff --git a/packages/nuxt-cli/test/unit/terminal-output.spec.ts b/packages/nuxt-cli/test/unit/terminal-output.spec.ts index f186f9b13..0c22ae64f 100644 --- a/packages/nuxt-cli/test/unit/terminal-output.spec.ts +++ b/packages/nuxt-cli/test/unit/terminal-output.spec.ts @@ -101,14 +101,12 @@ describe('dev server terminal output', () => { `) }) - it('should say how to reach a loopback server from outside a container', async () => { + it('should expose the server inside a container', async () => { isolatedEnvironment.current = 'the container' const renderer = await render(() => start()) - expect(screen(renderer)).toMatchInlineSnapshot(` - " ➜ Local: http://localhost:/ - ➜ Network: use --host to reach this server from outside the container" - `) + expect(screen(renderer)).toContain('➜ Local: http://localhost:/') + expect(screen(renderer)).not.toContain('use --host') }) it('should colour each url type differently', async () => {