fix(server): preserve random port when restarting (#5793)

This commit is contained in:
Sébastien Chopin 2019-05-25 20:19:24 +02:00 committed by Pooya Parsa
parent 0fc8ee41d1
commit a0958f03f4
2 changed files with 34 additions and 7 deletions

View File

@ -5,6 +5,8 @@ import ip from 'ip'
import consola from 'consola'
import pify from 'pify'
let RANDOM_PORT = '0'
export default class Listener {
constructor({ port, host, socket, https, app, dev, baseURL }) {
// Options
@ -90,7 +92,7 @@ export default class Listener {
this.listening = true
}
serverErrorHandler(error) {
async serverErrorHandler(error) {
// Detect if port is not available
const addressInUse = error.code === 'EADDRINUSE'
@ -100,11 +102,14 @@ export default class Listener {
error.message = `Address \`${address}\` is already in use.`
// Listen to a random port on dev as a fallback
if (this.dev && !this.socket && this.port !== '0') {
if (this.dev && !this.socket && this.port !== RANDOM_PORT) {
consola.warn(error.message)
consola.info('Trying a random port...')
this.port = '0'
return this.close().then(() => this.listen())
this.port = RANDOM_PORT
await this.close()
await this.listen()
RANDOM_PORT = this.port
return
}
}

View File

@ -319,7 +319,7 @@ describe('server: listener', () => {
const listener = new Listener({})
const error = new Error('server error')
expect(() => listener.serverErrorHandler(error)).toThrow(error)
expect(listener.serverErrorHandler(error)).rejects.toThrow(error)
})
test('should throw address in use error', () => {
@ -329,7 +329,7 @@ describe('server: listener', () => {
const addressInUse = new Error()
addressInUse.code = 'EADDRINUSE'
expect(() => listener.serverErrorHandler(addressInUse)).toThrow('Address `localhost:3000` is already in use.')
expect(listener.serverErrorHandler(addressInUse)).rejects.toThrow('Address `localhost:3000` is already in use.')
})
test('should throw address in use error for socket', () => {
@ -338,7 +338,7 @@ describe('server: listener', () => {
const addressInUse = new Error()
addressInUse.code = 'EADDRINUSE'
expect(() => listener.serverErrorHandler(addressInUse)).toThrow('Address `nuxt.socket` is already in use.')
expect(listener.serverErrorHandler(addressInUse)).rejects.toThrow('Address `nuxt.socket` is already in use.')
})
test('should fallback to a random port in address in use error', async () => {
@ -362,6 +362,28 @@ describe('server: listener', () => {
expect(listener.listen).toBeCalledTimes(1)
})
test('should reuse last random port', async () => {
const listener = new Listener({ dev: true, host: 'localhost', port: 3000 })
listener.host = 'localhost'
listener.close = jest.fn()
listener.listen = function () {
if (this.port === '0') {
this.port = Math.random()
}
}
const addressInUse = new Error()
addressInUse.code = 'EADDRINUSE'
await listener.serverErrorHandler(addressInUse).catch(() => { })
const port1 = listener.port
await listener.serverErrorHandler(addressInUse).catch(() => { })
const port2 = listener.port
expect(port1).not.toBe(3000)
expect(port2).toBe(port1)
})
test('should close server', async () => {
const listener = new Listener({})
const server = mockServer()