diff --git a/.changeset/quick-pens-develop.md b/.changeset/quick-pens-develop.md new file mode 100644 index 000000000000..8c762c019888 --- /dev/null +++ b/.changeset/quick-pens-develop.md @@ -0,0 +1,7 @@ +--- +"wrangler": minor +--- + +fix: listen on IPv4 loopback only by default on Windows + +Due to a [known issue](https://github.com/cloudflare/workerd/issues/1408), `workerd` will only listen on the IPv4 loopback address `127.0.0.1` when it's asked to listen on `localhost`. On Node.js > 17, `localhost` will resolve to the IPv6 loopback address, meaning requests to `workerd` would fail. This change switches to using the IPv4 loopback address throughout Wrangler on Windows, while [workerd#1408](https://github.com/cloudflare/workerd/issues/1408) gets fixed. diff --git a/packages/wrangler/src/__tests__/configuration.test.ts b/packages/wrangler/src/__tests__/configuration.test.ts index 01d4f23b53fd..acccd1a54a3a 100644 --- a/packages/wrangler/src/__tests__/configuration.test.ts +++ b/packages/wrangler/src/__tests__/configuration.test.ts @@ -30,7 +30,7 @@ describe("normalizeAndValidateConfig()", () => { constellation: [], hyperdrive: [], dev: { - ip: "localhost", + ip: process.platform === "win32" ? "127.0.0.1" : "localhost", local_protocol: "http", port: undefined, // the default of 8787 is set at runtime upstream_protocol: "https", diff --git a/packages/wrangler/src/__tests__/dev.test.tsx b/packages/wrangler/src/__tests__/dev.test.tsx index b5a4b9c2b7a2..0ddf62596e96 100644 --- a/packages/wrangler/src/__tests__/dev.test.tsx +++ b/packages/wrangler/src/__tests__/dev.test.tsx @@ -840,7 +840,7 @@ describe("wrangler dev", () => { fs.writeFileSync("index.js", `export default {};`); await runWrangler("dev"); expect((Dev as jest.Mock).mock.calls[0][0].initialIp).toEqual( - "localhost" + process.platform === "win32" ? "127.0.0.1" : "localhost" ); expect(std.out).toMatchInlineSnapshot(`""`); expect(std.warn).toMatchInlineSnapshot(`""`); @@ -1060,7 +1060,7 @@ describe("wrangler dev", () => { fs.writeFileSync("index.js", `export default {};`); await runWrangler("dev"); expect((Dev as jest.Mock).mock.calls[0][0].initialIp).toEqual( - "localhost" + process.platform === "win32" ? "127.0.0.1" : "localhost" ); expect(std.out).toMatchInlineSnapshot(` "Your worker has access to the following bindings: diff --git a/packages/wrangler/src/config/validation.ts b/packages/wrangler/src/config/validation.ts index bcf7631bcabc..588fd424527a 100644 --- a/packages/wrangler/src/config/validation.ts +++ b/packages/wrangler/src/config/validation.ts @@ -390,7 +390,14 @@ function normalizeAndValidateDev( rawDev: RawDevConfig ): DevConfig { const { - ip = "localhost", + // On Windows, when specifying `localhost` as the socket hostname, `workerd` + // will only listen on the IPv4 loopback `127.0.0.1`, not the IPv6 `::1`: + // https://github.com/cloudflare/workerd/issues/1408 + // On Node 17+, `fetch()` will only try to fetch the IPv6 address. + // For now, on Windows, we default to listening on IPv4 only and using + // `127.0.0.1` when sending control requests to `workerd` (e.g. with the + // `ProxyController`). + ip = process.platform === "win32" ? "127.0.0.1" : "localhost", port, inspector_port, local_protocol = "http", diff --git a/packages/wrangler/src/pages/dev.ts b/packages/wrangler/src/pages/dev.ts index 9edcf8da1009..2ab0182d2edb 100644 --- a/packages/wrangler/src/pages/dev.ts +++ b/packages/wrangler/src/pages/dev.ts @@ -99,7 +99,14 @@ export function Options(yargs: CommonYargsArgv) { }, ip: { type: "string", - default: "localhost", + // On Windows, when specifying `localhost` as the socket hostname, + // `workerd` will only listen on the IPv4 loopback `127.0.0.1`, not the + // IPv6 `::1`: https://github.com/cloudflare/workerd/issues/1408 + // On Node 17+, `fetch()` will only try to fetch the IPv6 address. + // For now, on Windows, we default to listening on IPv4 only and using + // `127.0.0.1` when sending control requests to `workerd` (e.g. with the + // `ProxyController`). + default: process.platform === "win32" ? "127.0.0.1" : "localhost", description: "The IP address to listen on", }, port: {