Fix IPv6 hostname formatting in CLI (#43491)

Co-authored-by: Jan Kaifer <jan@kaifer.cz>
Fixes https://github.com/vercel/next.js/issues/21979
This commit is contained in:
Akshit Sinha 2023-01-10 15:36:25 +05:30 committed by GitHub
parent c7162c42b2
commit 9dedc94500
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 3 deletions

7
packages/next/src/cli/next-dev.ts Executable file → Normal file
View file

@ -13,6 +13,7 @@ import path from 'path'
import type { NextConfig } from '../../types'
import type { NextConfigComplete } from '../server/config-shared'
import { traceGlobals } from '../trace/shared'
import { isIPv6 } from 'net'
import cluster from 'cluster'
import { Telemetry } from '../telemetry/storage'
import loadConfig from '../server/config'
@ -403,7 +404,11 @@ If you cannot make the changes above, but still want to try out\nNext.js v13 wit
startServer(devServerOptions)
.then(async (app) => {
const appUrl = `http://${app.hostname}:${app.port}`
startedDevelopmentServer(appUrl, `${host || '0.0.0.0'}:${app.port}`)
const hostname = host || '0.0.0.0'
startedDevelopmentServer(
appUrl,
`${isIPv6(hostname) ? `[${hostname}]` : hostname}:${app.port}`
)
// Start preflight after server is listening and ignore errors:
preflight().catch(() => {})
// Finalize server bootup:

View file

@ -7,6 +7,7 @@ import * as Log from '../build/output/log'
import isError from '../lib/is-error'
import { getProjectDir } from '../lib/get-project-dir'
import { CliCommand } from '../lib/commands'
import { isIPv6 } from 'net'
const nextStart: CliCommand = (argv) => {
const validArgs: arg.Spec = {
@ -80,7 +81,8 @@ const nextStart: CliCommand = (argv) => {
})
.then(async (app) => {
const appUrl = `http://${app.hostname}:${app.port}`
Log.ready(`started server on ${host}:${app.port}, url: ${appUrl}`)
const hostname = isIPv6(host) ? `[${host}]` : host
Log.ready(`started server on ${hostname}:${app.port}, url: ${appUrl}`)
await app.prepare()
})
.catch((err) => {

View file

@ -2,8 +2,10 @@ import type { NextServerOptions, NextServer, RequestHandler } from '../next'
import { warn } from '../../build/output/log'
import http from 'http'
import next from '../next'
import { isIPv6 } from 'net'
import cluster from 'cluster'
import v8 from 'v8'
interface StartServerOptions extends NextServerOptions {
allowRetry?: boolean
keepAliveTimeout?: number
@ -60,10 +62,13 @@ export function startServer(opts: StartServerOptions) {
server.on('listening', () => {
const addr = server.address()
const hostname =
let hostname =
!opts.hostname || opts.hostname === '0.0.0.0'
? 'localhost'
: opts.hostname
if (isIPv6(hostname)) {
hostname = hostname === '::' ? '[::1]' : `[${hostname}]`
}
const app = next({
...opts,

View file

@ -277,6 +277,16 @@ describe('CLI Usage', () => {
expect(output).toMatch(new RegExp(`http://localhost:${port}`))
})
test('should format IPv6 addresses correctly', async () => {
const port = await findPort()
const output = await runNextCommandDev(
[dir, '--hostname', '::', '--port', port],
true
)
expect(output).toMatch(new RegExp(`on \\[::\\]:${port}`))
expect(output).toMatch(new RegExp(`http://\\[::1\\]:${port}`))
})
test('should warn when unknown argument provided', async () => {
const { stderr } = await runNextCommand(['dev', '--random'], {
stderr: true,
@ -346,6 +356,18 @@ describe('CLI Usage', () => {
expect(help.stdout).toMatch(/Starts the application in production mode/)
})
test('should format IPv6 addresses correctly', async () => {
const port = await findPort()
const output = await runNextCommand(
['start', '--hostname', '::', '--port', port],
{
stdout: true,
}
)
expect(output.stdout).toMatch(new RegExp(`on \\[::\\]:${port}`))
expect(output.stdout).toMatch(new RegExp(`http://\\[::1\\]:${port}`))
})
test('should warn when unknown argument provided', async () => {
const { stderr } = await runNextCommand(['start', '--random'], {
stderr: true,