feat(net): add preferredPort option to getAvailablePort() (#4151)

* feat(net): add preferredPort option to getAvailablePort

* Apply suggestions from code review

---------

Co-authored-by: Asher Gomez <ashersaupingomez@gmail.com>
This commit is contained in:
Lino Le Van 2024-01-11 07:12:47 +01:00 committed by GitHub
parent 8ac25e3b0c
commit 6c615c976d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 4 deletions

View File

@ -1,5 +1,14 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
/** Options for {@linkcode getAvailablePort}. */
export interface GetAvailablePortOptions {
/**
* A port to check availability of first. If the port isn't available, fall
* back to another port.
*/
preferredPort?: number;
}
/**
* Returns an available network port.
*
@ -11,7 +20,21 @@
* Deno.serve({ port }, () => new Response("Hello, world!"));
* ```
*/
export function getAvailablePort(): number {
export function getAvailablePort(options?: GetAvailablePortOptions): number {
if (options?.preferredPort) {
try {
// Check if the preferred port is available
const listener = Deno.listen({ port: options.preferredPort });
listener.close();
return (listener.addr as Deno.NetAddr).port;
} catch (e) {
// If the preferred port is not available, fall through and find an available port
if (!(e instanceof Deno.errors.AddrInUse)) {
throw e;
}
}
}
const listener = Deno.listen({ port: 0 });
listener.close();
return (listener.addr as Deno.NetAddr).port;

View File

@ -3,9 +3,8 @@
import { getAvailablePort } from "./get_available_port.ts";
import { assertEquals } from "../assert/mod.ts";
Deno.test("getAvailablePort() gets an available port", async () => {
const port = getAvailablePort();
/** Helper function to see if a port is indeed available for listening (race-y) */
async function testWithPort(port: number) {
const server = Deno.serve({
port,
async onListen() {
@ -17,4 +16,14 @@ Deno.test("getAvailablePort() gets an available port", async () => {
}, () => new Response("hello"));
await server.finished;
}
Deno.test("getAvailablePort() gets an available port", async () => {
const port = getAvailablePort();
await testWithPort(port);
});
Deno.test("getAvailablePort() gets an available port with a preferred port", async () => {
const port = getAvailablePort({ preferredPort: 9563 });
await testWithPort(port);
});