Skip to content

Commit

Permalink
fix: invalid ipv6 hostname on deno serve (denoland#25482)
Browse files Browse the repository at this point in the history
This PR fixes an invalid URL being printed when running `deno serve`

Before: invalid URL

```sh
$ deno serve --host localhost
deno serve: Listening on http://::1:8000/
```

After: valid URL

```sh
$ deno serve --host localhost
deno serve: Listening on http://[::1]:8000/
```
  • Loading branch information
marvinhagemeister authored Sep 6, 2024
1 parent dcf1555 commit 73ab32c
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
17 changes: 9 additions & 8 deletions ext/http/00_serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ type RawServeOptions = {

const kLoadBalanced = Symbol("kLoadBalanced");

function mapAnyAddrToLocalhostForWindows(hostname: string) {
function formatHostName(hostname: string): string {
// If the hostname is "0.0.0.0", we display "localhost" in console
// because browsers in Windows don't resolve "0.0.0.0".
// See the discussion in https://github.com/denoland/deno_std/issues/1165
Expand All @@ -593,7 +593,9 @@ function mapAnyAddrToLocalhostForWindows(hostname: string) {
) {
return "localhost";
}
return hostname;

// Add brackets around ipv6 hostname
return StringPrototypeIncludes(hostname, ":") ? `[${hostname}]` : hostname;
}

function serve(arg1, arg2) {
Expand Down Expand Up @@ -690,10 +692,8 @@ function serve(arg1, arg2) {
if (options.onListen) {
options.onListen(addr);
} else {
const hostname = mapAnyAddrToLocalhostForWindows(addr.hostname);
const host = StringPrototypeIncludes(hostname, ":")
? `[${hostname}]`
: hostname;
const host = formatHostName(addr.hostname);

// deno-lint-ignore no-console
console.log(`Listening on ${scheme}${host}:${addr.port}/`);
}
Expand Down Expand Up @@ -868,10 +868,11 @@ function registerDeclarativeServer(exports) {
const nThreads = serveWorkerCount > 1
? ` with ${serveWorkerCount} threads`
: "";
const hostname_ = mapAnyAddrToLocalhostForWindows(hostname);
const host = formatHostName(hostname);

// deno-lint-ignore no-console
console.debug(
`%cdeno serve%c: Listening on %chttp://${hostname_}:${port}/%c${nThreads}`,
`%cdeno serve%c: Listening on %chttp://${host}:${port}/%c${nThreads}`,
"color: green",
"color: inherit",
"color: yellow",
Expand Down
30 changes: 30 additions & 0 deletions tests/unit/serve_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,36 @@ Deno.test({ permissions: { net: true } }, async function validPortString() {
await server.shutdown();
});

Deno.test({ permissions: { net: true } }, async function ipv6Hostname() {
const ac = new AbortController();
let url = "";

const consoleLog = console.log;
console.log = (msg) => {
try {
const match = msg.match(/Listening on (http:\/\/(.*?):(\d+)\/)/);
assert(!!match, `Didn't match ${msg}`);
url = match[1];
} finally {
ac.abort();
}
};

try {
const server = Deno.serve({
handler: () => new Response(),
hostname: "::1",
port: 0,
signal: ac.signal,
});
assertEquals(server.addr.transport, "tcp");
assert(new URL(url), `Not a valid URL "${url}"`);
await server.shutdown();
} finally {
console.log = consoleLog;
}
});

Deno.test({ permissions: { net: true } }, function invalidPortFloat() {
assertThrows(
() =>
Expand Down

0 comments on commit 73ab32c

Please sign in to comment.