Skip to content

Commit

Permalink
Throw if the user requests a port and it's already taken
Browse files Browse the repository at this point in the history
  • Loading branch information
marvinhagemeister committed Mar 27, 2021
1 parent 0db05e5 commit 8b784b9
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 15 deletions.
36 changes: 23 additions & 13 deletions packages/wmr/src/lib/net-utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
import net from 'net';
import os from 'os';

/**
* Check if a port is free
* @param {number} port
* @returns {Promise<boolean>}
*/
export async function isPortFree(port) {
try {
await new Promise((resolve, reject) => {
const server = net.createServer();
server.unref();
server.on('error', reject);
server.listen({ port }, () => {
server.close(resolve);
});
});
return true;
} catch (err) {
if (err.code !== 'EADDRINUSE') throw err;
return false;
}
}

/**
* Check if the requested port is free and increase port number
* sequentially until we find a free port.
Expand All @@ -15,19 +37,7 @@ export async function getFreePort(port) {

// Limit to 20 attempts for now
while (!found && attempts <= 20) {
try {
await new Promise((resolve, reject) => {
const server = net.createServer();
server.unref();
server.on('error', reject);
server.listen({ port }, () => {
port = server.address().port;
found = true;
server.close(resolve);
});
});
} catch (err) {
if (err.code !== 'EADDRINUSE') throw err;
if (!isPortFree(port)) {
port++;
attempts++;
}
Expand Down
16 changes: 14 additions & 2 deletions packages/wmr/src/start.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import server from './server.js';
import wmrMiddleware from './wmr-middleware.js';
import { getFreePort, getServerAddresses } from './lib/net-utils.js';
import { getFreePort, getServerAddresses, isPortFree } from './lib/net-utils.js';
import { normalizeOptions } from './lib/normalize-options.js';
import { setCwd } from './plugins/npm-plugin/registry.js';
import { formatBootMessage } from './lib/output-utils.js';
Expand All @@ -21,7 +21,19 @@ export default async function start(options = {}) {

options = await normalizeOptions(options, 'start');

options.port = await getFreePort(options.port || process.env.PORT || 8080);
// Don't use another free port if the user explicitely
// requested a specific one.
const userPort = options.port || process.env.PORT;
if (userPort !== undefined) {
if (await isPortFree(+userPort)) {
options.port = +userPort;
} else {
throw new Error(`Another process is already running on port ${userPort}. Please choose a different port.`);
}
} else {
options.port = await getFreePort(8080);
}

options.host = options.host || process.env.HOST;

options.middleware = [].concat(
Expand Down

0 comments on commit 8b784b9

Please sign in to comment.