Skip to content

Commit

Permalink
Add support for ipv6 host
Browse files Browse the repository at this point in the history
  • Loading branch information
jspspike committed Aug 18, 2023
1 parent 3f5ab99 commit d61b3f7
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 5 deletions.
18 changes: 18 additions & 0 deletions packages/miniflare/src/http/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { networkInterfaces } from "os";

export function getAccessibleHosts(ipv4Only = false): string[] {
const hosts: string[] = [];
Object.values(networkInterfaces()).forEach((net) => {
net?.forEach(({ family, address }) => {
// The `family` property being numeric was reverted in Node 18.2
// https://github.com/nodejs/node/issues/43014
// @ts-expect-error the `family` property is numeric as of Node.js 18.0.0
if (family === "IPv4" || family === 4) {
hosts.push(address);
} else if (!ipv4Only && (family === "IPv6" || family === 6)) {
hosts.push(`[${address}]`);
}
});
});
return hosts;
}
1 change: 1 addition & 0 deletions packages/miniflare/src/http/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from "./request";
export * from "./response";
export * from "./websocket";
export * from "./server";
export * from "./helpers";

export { File, FormData, Headers } from "undici";
export type {
Expand Down
37 changes: 33 additions & 4 deletions packages/miniflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
configureEntrySocket,
coupleWebSocket,
fetch,
getAccessibleHosts,
} from "./http";
import {
D1_PLUGIN_NAME,
Expand Down Expand Up @@ -518,7 +519,14 @@ export class Miniflare {
this.#timers = this.#sharedOpts.core.timers ?? defaultTimers;
this.#host = this.#sharedOpts.core.host ?? "127.0.0.1";
this.#accessibleHost =
this.#host === "*" || this.#host === "0.0.0.0" ? "127.0.0.1" : this.#host;
this.#host === "*" || this.#host === "0.0.0.0" || this.#host === "::"
? "127.0.0.1"
: this.#host;

if (net.isIPv6(this.#accessibleHost)) {
this.#accessibleHost = `[${this.#accessibleHost}]`;
}

this.#initPlugins();

this.#liveReloadServer = new WebSocketServer({ noServer: true });
Expand Down Expand Up @@ -605,7 +613,7 @@ export class Miniflare {
// Start runtime
const port = this.#sharedOpts.core.port ?? 0;
const opts: RuntimeOptions = {
entryHost: this.#host,
entryHost: net.isIPv6(this.#host) ? `[${this.#host}]` : this.#host,
entryPort: port,
loopbackPort: this.#loopbackPort,
inspectorPort: this.#sharedOpts.core.inspectorPort,
Expand Down Expand Up @@ -702,7 +710,7 @@ export class Miniflare {
// Extract original URL passed to `fetch`
const url = new URL(
headers.get(CoreHeaders.ORIGINAL_URL) ?? req.url ?? "",
"http://127.0.0.1"
"http://localhost"
);
headers.delete(CoreHeaders.ORIGINAL_URL);

Expand Down Expand Up @@ -825,6 +833,10 @@ export class Miniflare {
port: number,
hostname: string
): Promise<StoppableServer> {
if (hostname === "*") {
hostname = "::";
}

return new Promise((resolve) => {
const server = stoppable(
http.createServer(this.#handleLoopback),
Expand Down Expand Up @@ -1018,7 +1030,24 @@ export class Miniflare {
if (!this.#runtimeMutex.hasWaiting) {
// Only log and trigger reload if there aren't pending updates
const ready = initial ? "Ready" : "Updated and ready";
this.#log.info(`${ready} on ${this.#runtimeEntryURL}`);
const host = net.isIPv6(this.#host) ? `[${this.#host}]` : this.#host;
this.#log.info(
`${ready} on ${secure ? "https" : "http"}://${host}:${maybePort} `
);

let hosts: string[];
if (this.#host === "::" || this.#host === "*") {
hosts = getAccessibleHosts(false);
} else if (this.#host === "0.0.0.0") {
hosts = getAccessibleHosts(true);
} else {
hosts = [];
}

for (const h of hosts) {
this.#log.info(`- ${secure ? "https" : "http"}://${h}:${maybePort}`);
}

this.#handleReload();
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/miniflare/src/runtime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export class Runtime {
];
if (this.opts.inspectorPort !== undefined) {
// Required to enable the V8 inspector
args.push(`--inspector-addr=127.0.0.1:${this.opts.inspectorPort}`);
args.push(`--inspector-addr=localhost:${this.opts.inspectorPort}`);
}
if (this.opts.verbose) {
args.push("--verbose");
Expand Down
27 changes: 27 additions & 0 deletions packages/miniflare/test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,33 @@ test("Miniflare: manually triggered scheduled events", async (t) => {
t.is(await res.text(), "true");
});

test("Miniflare: Listens on ipv6", async (t) => {
const log = new TestLog(t);

const mf = new Miniflare({
log,
modules: true,
host: "*",
script: `export default {
fetch() {
return new Response("Hello world");
}
}`,
});
t.teardown(() => mf.dispose());

const url = await mf.ready;

let response = await fetch(`http://localhost:${url.port}`);
t.true(response.ok);

response = await fetch(`http://[::1]:${url.port}`);
t.true(response.ok);

response = await fetch(`http://127.0.0.1:${url.port}`);
t.true(response.ok);
});

queuesTest("Miniflare: getBindings() returns all bindings", async (t) => {
const tmp = await useTmp(t);
const blobPath = path.join(tmp, "blob.txt");
Expand Down

0 comments on commit d61b3f7

Please sign in to comment.