Skip to content

Commit a0958f0

Browse files
atinuxPooya Parsa
authored andcommitted
fix(server): preserve random port when restarting (nuxt#5793)
1 parent 0fc8ee4 commit a0958f0

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

packages/server/src/listener.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import ip from 'ip'
55
import consola from 'consola'
66
import pify from 'pify'
77

8+
let RANDOM_PORT = '0'
9+
810
export default class Listener {
911
constructor({ port, host, socket, https, app, dev, baseURL }) {
1012
// Options
@@ -90,7 +92,7 @@ export default class Listener {
9092
this.listening = true
9193
}
9294

93-
serverErrorHandler(error) {
95+
async serverErrorHandler(error) {
9496
// Detect if port is not available
9597
const addressInUse = error.code === 'EADDRINUSE'
9698

@@ -100,11 +102,14 @@ export default class Listener {
100102
error.message = `Address \`${address}\` is already in use.`
101103

102104
// Listen to a random port on dev as a fallback
103-
if (this.dev && !this.socket && this.port !== '0') {
105+
if (this.dev && !this.socket && this.port !== RANDOM_PORT) {
104106
consola.warn(error.message)
105107
consola.info('Trying a random port...')
106-
this.port = '0'
107-
return this.close().then(() => this.listen())
108+
this.port = RANDOM_PORT
109+
await this.close()
110+
await this.listen()
111+
RANDOM_PORT = this.port
112+
return
108113
}
109114
}
110115

packages/server/test/listener.test.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ describe('server: listener', () => {
319319
const listener = new Listener({})
320320

321321
const error = new Error('server error')
322-
expect(() => listener.serverErrorHandler(error)).toThrow(error)
322+
expect(listener.serverErrorHandler(error)).rejects.toThrow(error)
323323
})
324324

325325
test('should throw address in use error', () => {
@@ -329,7 +329,7 @@ describe('server: listener', () => {
329329

330330
const addressInUse = new Error()
331331
addressInUse.code = 'EADDRINUSE'
332-
expect(() => listener.serverErrorHandler(addressInUse)).toThrow('Address `localhost:3000` is already in use.')
332+
expect(listener.serverErrorHandler(addressInUse)).rejects.toThrow('Address `localhost:3000` is already in use.')
333333
})
334334

335335
test('should throw address in use error for socket', () => {
@@ -338,7 +338,7 @@ describe('server: listener', () => {
338338

339339
const addressInUse = new Error()
340340
addressInUse.code = 'EADDRINUSE'
341-
expect(() => listener.serverErrorHandler(addressInUse)).toThrow('Address `nuxt.socket` is already in use.')
341+
expect(listener.serverErrorHandler(addressInUse)).rejects.toThrow('Address `nuxt.socket` is already in use.')
342342
})
343343

344344
test('should fallback to a random port in address in use error', async () => {
@@ -362,6 +362,28 @@ describe('server: listener', () => {
362362
expect(listener.listen).toBeCalledTimes(1)
363363
})
364364

365+
test('should reuse last random port', async () => {
366+
const listener = new Listener({ dev: true, host: 'localhost', port: 3000 })
367+
listener.host = 'localhost'
368+
listener.close = jest.fn()
369+
listener.listen = function () {
370+
if (this.port === '0') {
371+
this.port = Math.random()
372+
}
373+
}
374+
375+
const addressInUse = new Error()
376+
addressInUse.code = 'EADDRINUSE'
377+
378+
await listener.serverErrorHandler(addressInUse).catch(() => { })
379+
const port1 = listener.port
380+
await listener.serverErrorHandler(addressInUse).catch(() => { })
381+
const port2 = listener.port
382+
383+
expect(port1).not.toBe(3000)
384+
expect(port2).toBe(port1)
385+
})
386+
365387
test('should close server', async () => {
366388
const listener = new Listener({})
367389
const server = mockServer()

0 commit comments

Comments
 (0)