mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
fix(ext/node): fix dns.lookup result ordering (#26264)
partially unblocks #25470 This PR aligns the resolution of `localhost` hostname to Node.js behavior. In Node.js `dns.lookup("localhost", (_, addr) => console.log(addr))` prints ipv6 address `::1`, but it prints ipv4 address `127.0.0.1` in Deno. That difference causes some errors in the work of enabling `createConnection` option in `http.request` (#25470). This PR fixes the issue by aligning `dns.lookup` behavior to Node.js. This PR also changes the following behaviors (resolving TODOs): - `http.createServer` now listens on ipv6 address `[::]` by default on linux/mac - `net.createServer` now listens on ipv6 address `[::]` by default on linux/mac These changes are also alignments to Node.js behaviors.
This commit is contained in:
parent
ea9c3ffaa2
commit
d59599fc18
6 changed files with 38 additions and 41 deletions
|
@ -50,6 +50,7 @@ import { urlToHttpOptions } from "ext:deno_node/internal/url.ts";
|
||||||
import { kEmptyObject } from "ext:deno_node/internal/util.mjs";
|
import { kEmptyObject } from "ext:deno_node/internal/util.mjs";
|
||||||
import { constants, TCP } from "ext:deno_node/internal_binding/tcp_wrap.ts";
|
import { constants, TCP } from "ext:deno_node/internal_binding/tcp_wrap.ts";
|
||||||
import { notImplemented, warnNotImplemented } from "ext:deno_node/_utils.ts";
|
import { notImplemented, warnNotImplemented } from "ext:deno_node/_utils.ts";
|
||||||
|
import { isWindows } from "ext:deno_node/_util/os.ts";
|
||||||
import {
|
import {
|
||||||
connResetException,
|
connResetException,
|
||||||
ERR_HTTP_HEADERS_SENT,
|
ERR_HTTP_HEADERS_SENT,
|
||||||
|
@ -1586,9 +1587,8 @@ export class ServerImpl extends EventEmitter {
|
||||||
port = options.port | 0;
|
port = options.port | 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bnoordhuis) Node prefers [::] when host is omitted,
|
// Use 0.0.0.0 for Windows, and [::] for other platforms.
|
||||||
// we on the other hand default to 0.0.0.0.
|
let hostname = options.host ?? (isWindows ? "0.0.0.0" : "[::]");
|
||||||
let hostname = options.host ?? "0.0.0.0";
|
|
||||||
if (hostname == "localhost") {
|
if (hostname == "localhost") {
|
||||||
hostname = "127.0.0.1";
|
hostname = "127.0.0.1";
|
||||||
}
|
}
|
||||||
|
|
|
@ -416,20 +416,10 @@ export function emitInvalidHostnameWarning(hostname: string) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dnsOrder = getOptionValue("--dns-result-order") || "ipv4first";
|
let dnsOrder = getOptionValue("--dns-result-order") || "verbatim";
|
||||||
|
|
||||||
export function getDefaultVerbatim() {
|
export function getDefaultVerbatim() {
|
||||||
switch (dnsOrder) {
|
return dnsOrder !== "ipv4first";
|
||||||
case "verbatim": {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case "ipv4first": {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -75,11 +75,18 @@ export function getaddrinfo(
|
||||||
|
|
||||||
const recordTypes: ("A" | "AAAA")[] = [];
|
const recordTypes: ("A" | "AAAA")[] = [];
|
||||||
|
|
||||||
if (family === 0 || family === 4) {
|
if (family === 6) {
|
||||||
recordTypes.push("A");
|
|
||||||
}
|
|
||||||
if (family === 0 || family === 6) {
|
|
||||||
recordTypes.push("AAAA");
|
recordTypes.push("AAAA");
|
||||||
|
} else if (family === 4) {
|
||||||
|
recordTypes.push("A");
|
||||||
|
} else if (family === 0 && hostname === "localhost") {
|
||||||
|
// Ipv6 is preferred over Ipv4 for localhost
|
||||||
|
recordTypes.push("AAAA");
|
||||||
|
recordTypes.push("A");
|
||||||
|
} else if (family === 0) {
|
||||||
|
// Only get Ipv4 addresses for the other hostnames
|
||||||
|
// This simulates what `getaddrinfo` does when the family is not specified
|
||||||
|
recordTypes.push("A");
|
||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
|
@ -1871,23 +1871,13 @@ function _setupListenHandle(
|
||||||
|
|
||||||
// Try to bind to the unspecified IPv6 address, see if IPv6 is available
|
// Try to bind to the unspecified IPv6 address, see if IPv6 is available
|
||||||
if (!address && typeof fd !== "number") {
|
if (!address && typeof fd !== "number") {
|
||||||
// TODO(@bartlomieju): differs from Node which tries to bind to IPv6 first
|
if (isWindows) {
|
||||||
// when no address is provided.
|
|
||||||
//
|
|
||||||
// Forcing IPv4 as a workaround for Deno not aligning with Node on
|
|
||||||
// implicit binding on Windows.
|
|
||||||
//
|
|
||||||
// REF: https://github.com/denoland/deno/issues/10762
|
|
||||||
// rval = _createServerHandle(DEFAULT_IPV6_ADDR, port, 6, fd, flags);
|
|
||||||
|
|
||||||
// if (typeof rval === "number") {
|
|
||||||
// rval = null;
|
|
||||||
address = DEFAULT_IPV4_ADDR;
|
address = DEFAULT_IPV4_ADDR;
|
||||||
addressType = 4;
|
addressType = 4;
|
||||||
// } else {
|
} else {
|
||||||
// address = DEFAULT_IPV6_ADDR;
|
address = DEFAULT_IPV6_ADDR;
|
||||||
// addressType = 6;
|
addressType = 6;
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rval === null) {
|
if (rval === null) {
|
||||||
|
|
|
@ -318,10 +318,14 @@ Deno.test("[node/http] IncomingRequest socket has remoteAddress + remotePort", a
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
const port = (server.address() as any).port;
|
const port = (server.address() as any).port;
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`http://127.0.0.1:${port}/`,
|
`http://localhost:${port}/`,
|
||||||
);
|
);
|
||||||
await res.arrayBuffer();
|
await res.arrayBuffer();
|
||||||
|
if (Deno.build.os === "windows") {
|
||||||
assertEquals(remoteAddress, "127.0.0.1");
|
assertEquals(remoteAddress, "127.0.0.1");
|
||||||
|
} else {
|
||||||
|
assertEquals(remoteAddress, "::1");
|
||||||
|
}
|
||||||
assertEquals(typeof remotePort, "number");
|
assertEquals(typeof remotePort, "number");
|
||||||
server.close(() => resolve());
|
server.close(() => resolve());
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,13 +32,15 @@ for (
|
||||||
) {
|
) {
|
||||||
Deno.test(`tls.connect sends correct ALPN: '${alpnServer}' + '${alpnClient}' = '${expected}'`, async () => {
|
Deno.test(`tls.connect sends correct ALPN: '${alpnServer}' + '${alpnClient}' = '${expected}'`, async () => {
|
||||||
const listener = Deno.listenTls({
|
const listener = Deno.listenTls({
|
||||||
|
hostname: "localhost",
|
||||||
port: 0,
|
port: 0,
|
||||||
key,
|
key,
|
||||||
cert,
|
cert,
|
||||||
alpnProtocols: alpnServer,
|
alpnProtocols: alpnServer,
|
||||||
});
|
});
|
||||||
const outgoing = tls.connect({
|
const outgoing = tls.connect({
|
||||||
host: "localhost",
|
host: "::1",
|
||||||
|
servername: "localhost",
|
||||||
port: listener.addr.port,
|
port: listener.addr.port,
|
||||||
ALPNProtocols: alpnClient,
|
ALPNProtocols: alpnClient,
|
||||||
secureContext: {
|
secureContext: {
|
||||||
|
@ -61,6 +63,7 @@ Deno.test("tls.connect makes tls connection", async () => {
|
||||||
const ctl = new AbortController();
|
const ctl = new AbortController();
|
||||||
let port;
|
let port;
|
||||||
const serve = Deno.serve({
|
const serve = Deno.serve({
|
||||||
|
hostname: "localhost",
|
||||||
port: 0,
|
port: 0,
|
||||||
key,
|
key,
|
||||||
cert,
|
cert,
|
||||||
|
@ -71,7 +74,8 @@ Deno.test("tls.connect makes tls connection", async () => {
|
||||||
await delay(200);
|
await delay(200);
|
||||||
|
|
||||||
const conn = tls.connect({
|
const conn = tls.connect({
|
||||||
host: "localhost",
|
host: "::1",
|
||||||
|
servername: "localhost",
|
||||||
port,
|
port,
|
||||||
secureContext: {
|
secureContext: {
|
||||||
ca: rootCaCert,
|
ca: rootCaCert,
|
||||||
|
@ -102,6 +106,7 @@ Deno.test("tls.connect mid-read tcp->tls upgrade", async () => {
|
||||||
const { promise, resolve } = Promise.withResolvers<void>();
|
const { promise, resolve } = Promise.withResolvers<void>();
|
||||||
const ctl = new AbortController();
|
const ctl = new AbortController();
|
||||||
const serve = Deno.serve({
|
const serve = Deno.serve({
|
||||||
|
hostname: "localhost",
|
||||||
port: 8443,
|
port: 8443,
|
||||||
key,
|
key,
|
||||||
cert,
|
cert,
|
||||||
|
@ -111,7 +116,8 @@ Deno.test("tls.connect mid-read tcp->tls upgrade", async () => {
|
||||||
await delay(200);
|
await delay(200);
|
||||||
|
|
||||||
const conn = tls.connect({
|
const conn = tls.connect({
|
||||||
host: "localhost",
|
host: "::1",
|
||||||
|
servername: "localhost",
|
||||||
port: 8443,
|
port: 8443,
|
||||||
secureContext: {
|
secureContext: {
|
||||||
ca: rootCaCert,
|
ca: rootCaCert,
|
||||||
|
|
Loading…
Reference in a new issue