mirror of
https://github.com/denoland/deno.git
synced 2024-12-24 16:19:12 -05:00
feat(unstable): add Deno.resolveDns API (#8790)
This commit is contained in:
parent
cf3202644d
commit
0ef8c915c0
12 changed files with 982 additions and 9 deletions
213
Cargo.lock
generated
213
Cargo.lock
generated
|
@ -397,6 +397,12 @@ dependencies = [
|
|||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "993a608597367c6377b258c25d7120740f00ed23a2252b729b1932dd7866f908"
|
||||
|
||||
[[package]]
|
||||
name = "deno"
|
||||
version = "1.6.3"
|
||||
|
@ -449,6 +455,8 @@ dependencies = [
|
|||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tower-test",
|
||||
"trust-dns-client",
|
||||
"trust-dns-server",
|
||||
"uuid",
|
||||
"walkdir",
|
||||
"winapi 0.3.9",
|
||||
|
@ -564,6 +572,8 @@ dependencies = [
|
|||
"test_util",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"trust-dns-proto",
|
||||
"trust-dns-resolver",
|
||||
"uuid",
|
||||
"webpki",
|
||||
"webpki-roots",
|
||||
|
@ -698,6 +708,24 @@ dependencies = [
|
|||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "endian-type"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
|
||||
|
||||
[[package]]
|
||||
name = "enum-as-inner"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.56",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum_kind"
|
||||
version = "0.2.0"
|
||||
|
@ -1080,6 +1108,17 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hostname"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"match_cfg",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.3"
|
||||
|
@ -1238,6 +1277,18 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipconfig"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
|
||||
dependencies = [
|
||||
"socket2",
|
||||
"widestring",
|
||||
"winapi 0.3.9",
|
||||
"winreg 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.3.0"
|
||||
|
@ -1306,6 +1357,12 @@ version = "0.2.82"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.2"
|
||||
|
@ -1325,6 +1382,15 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lru-cache"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lsp-types"
|
||||
version = "0.86.0"
|
||||
|
@ -1373,6 +1439,12 @@ dependencies = [
|
|||
"syn 1.0.56",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "match_cfg"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
version = "0.1.8"
|
||||
|
@ -1490,6 +1562,15 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||
|
||||
[[package]]
|
||||
name = "nibble_vec"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43"
|
||||
dependencies = [
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.19.1"
|
||||
|
@ -1848,6 +1929,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
|
@ -1878,6 +1965,16 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce082a9940a7ace2ad4a8b7d0b1eac6aa378895f18be598230c5f2284ac05426"
|
||||
|
||||
[[package]]
|
||||
name = "radix_trie"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd"
|
||||
dependencies = [
|
||||
"endian-type",
|
||||
"nibble_vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
|
@ -2042,7 +2139,17 @@ dependencies = [
|
|||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"webpki-roots",
|
||||
"winreg",
|
||||
"winreg 0.7.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resolv-conf"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00"
|
||||
dependencies = [
|
||||
"hostname",
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3030,6 +3137,95 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-client"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "498e4de74132fb535c0608d0f221a3e64ddf6585717296afb2baf5925b38f31f"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"chrono",
|
||||
"data-encoding",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"radix_trie",
|
||||
"rand 0.8.1",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"trust-dns-proto",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-proto"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98a0381b2864c2978db7f8e17c7b23cca5a3a5f99241076e13002261a8ecbabd"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"cfg-if 1.0.0",
|
||||
"data-encoding",
|
||||
"enum-as-inner",
|
||||
"futures-channel",
|
||||
"futures-io",
|
||||
"futures-util",
|
||||
"idna",
|
||||
"ipnet",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"rand 0.8.1",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-resolver"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3072d18c10bd621cb00507d59cfab5517862285c353160366e37fbf4c74856e4"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"futures-util",
|
||||
"ipconfig",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"lru-cache",
|
||||
"parking_lot",
|
||||
"resolv-conf",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"trust-dns-proto",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-server"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9da8b74feb06ae242b03f40f8da3a414e37827118200fcb3d03d8f825cbbff2c"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"cfg-if 1.0.0",
|
||||
"chrono",
|
||||
"enum-as-inner",
|
||||
"env_logger",
|
||||
"futures-executor",
|
||||
"futures-util",
|
||||
"log",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"toml",
|
||||
"trust-dns-client",
|
||||
"trust-dns-proto",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.3"
|
||||
|
@ -3301,6 +3497,12 @@ dependencies = [
|
|||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
|
@ -3344,6 +3546,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.7.0"
|
||||
|
|
|
@ -91,6 +91,8 @@ chrono = "0.4.19"
|
|||
os_pipe = "0.9.2"
|
||||
test_util = { path = "../test_util" }
|
||||
tower-test = "0.4.0"
|
||||
trust-dns-server = "0.20.0"
|
||||
trust-dns-client = "0.20.0"
|
||||
|
||||
[target.'cfg(unix)'.dev-dependencies]
|
||||
exec = "0.3.1" # Used in test_raw_tty
|
||||
|
|
86
cli/dts/lib.deno.unstable.d.ts
vendored
86
cli/dts/lib.deno.unstable.d.ts
vendored
|
@ -835,6 +835,92 @@ declare namespace Deno {
|
|||
mtime: number | Date,
|
||||
): Promise<void>;
|
||||
|
||||
/** The type of the resource record.
|
||||
* Only the listed types are supported currently. */
|
||||
export type RecordType =
|
||||
| "A"
|
||||
| "AAAA"
|
||||
| "ANAME"
|
||||
| "CNAME"
|
||||
| "MX"
|
||||
| "PTR"
|
||||
| "SRV"
|
||||
| "TXT";
|
||||
|
||||
export interface ResolveDnsOptions {
|
||||
/** The name server to be used for lookups.
|
||||
* If not specified, defaults to the system configuration e.g. `/etc/resolv.conf` on Unix. */
|
||||
nameServer?: {
|
||||
/** The IP address of the name server */
|
||||
ipAddr: string;
|
||||
/** The port number the query will be sent to.
|
||||
* If not specified, defaults to 53. */
|
||||
port?: number;
|
||||
};
|
||||
}
|
||||
|
||||
/** If `resolveDns` is called with "MX" record type specified, it will return an array of this interface. */
|
||||
export interface MXRecord {
|
||||
preference: number;
|
||||
exchange: string;
|
||||
}
|
||||
|
||||
/** If `resolveDns` is called with "SRV" record type specified, it will return an array of this interface. */
|
||||
export interface SRVRecord {
|
||||
priority: number;
|
||||
weight: number;
|
||||
port: number;
|
||||
target: string;
|
||||
}
|
||||
|
||||
export function resolveDns(
|
||||
query: string,
|
||||
recordType: "A" | "AAAA" | "ANAME" | "CNAME" | "PTR",
|
||||
options?: ResolveDnsOptions,
|
||||
): Promise<string[]>;
|
||||
|
||||
export function resolveDns(
|
||||
query: string,
|
||||
recordType: "MX",
|
||||
options?: ResolveDnsOptions,
|
||||
): Promise<MXRecord[]>;
|
||||
|
||||
export function resolveDns(
|
||||
query: string,
|
||||
recordType: "SRV",
|
||||
options?: ResolveDnsOptions,
|
||||
): Promise<SRVRecord[]>;
|
||||
|
||||
export function resolveDns(
|
||||
query: string,
|
||||
recordType: "TXT",
|
||||
options?: ResolveDnsOptions,
|
||||
): Promise<string[][]>;
|
||||
|
||||
/** ** UNSTABLE**: new API, yet to be vetted.
|
||||
*
|
||||
* Performs DNS resolution against the given query, returning resolved records.
|
||||
* Fails in the cases such as:
|
||||
* - the query is in invalid format
|
||||
* - the options have an invalid parameter, e.g. `nameServer.port` is beyond the range of 16-bit unsigned integer
|
||||
* - timed out
|
||||
*
|
||||
* ```ts
|
||||
* const a = await Deno.resolveDns("example.com", "A");
|
||||
*
|
||||
* const aaaa = await Deno.resolveDns("example.com", "AAAA", {
|
||||
* nameServer: { ipAddr: "8.8.8.8", port: 1234 },
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Requires `allow-net` permission.
|
||||
*/
|
||||
export function resolveDns(
|
||||
query: string,
|
||||
recordType: RecordType,
|
||||
options?: ResolveDnsOptions,
|
||||
): Promise<string[] | MXRecord[] | SRVRecord[] | string[][]>;
|
||||
|
||||
/** **UNSTABLE**: new API, yet to be vetted.
|
||||
*
|
||||
* A generic transport listener for message-oriented protocols. */
|
||||
|
|
|
@ -5367,3 +5367,279 @@ fn web_platform_tests() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_resolve_dns() {
|
||||
use std::collections::BTreeMap;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::net::Ipv6Addr;
|
||||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
use std::time::Duration;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::net::UdpSocket;
|
||||
use tokio::sync::oneshot;
|
||||
use trust_dns_client::rr::LowerName;
|
||||
use trust_dns_client::rr::RecordType;
|
||||
use trust_dns_client::rr::RrKey;
|
||||
use trust_dns_server::authority::Catalog;
|
||||
use trust_dns_server::authority::ZoneType;
|
||||
use trust_dns_server::proto::rr::rdata::mx::MX;
|
||||
use trust_dns_server::proto::rr::rdata::soa::SOA;
|
||||
use trust_dns_server::proto::rr::rdata::srv::SRV;
|
||||
use trust_dns_server::proto::rr::rdata::txt::TXT;
|
||||
use trust_dns_server::proto::rr::record_data::RData;
|
||||
use trust_dns_server::proto::rr::resource::Record;
|
||||
use trust_dns_server::proto::rr::Name;
|
||||
use trust_dns_server::proto::rr::RecordSet;
|
||||
use trust_dns_server::store::in_memory::InMemoryAuthority;
|
||||
use trust_dns_server::ServerFuture;
|
||||
|
||||
const DNS_PORT: u16 = 4553;
|
||||
|
||||
// Setup DNS server for testing
|
||||
async fn run_dns_server(tx: oneshot::Sender<()>) {
|
||||
let catalog = {
|
||||
let records = {
|
||||
let mut map = BTreeMap::new();
|
||||
let lookup_name = "www.example.com".parse::<Name>().unwrap();
|
||||
let lookup_name_lower = LowerName::new(&lookup_name);
|
||||
|
||||
// Inserts SOA record
|
||||
let soa = SOA::new(
|
||||
Name::from_str("net").unwrap(),
|
||||
Name::from_str("example").unwrap(),
|
||||
0,
|
||||
i32::MAX,
|
||||
i32::MAX,
|
||||
i32::MAX,
|
||||
0,
|
||||
);
|
||||
let rdata = RData::SOA(soa);
|
||||
let record = Record::from_rdata(Name::new(), u32::MAX, rdata);
|
||||
let record_set = RecordSet::from(record);
|
||||
map
|
||||
.insert(RrKey::new(Name::root().into(), RecordType::SOA), record_set);
|
||||
|
||||
// Inserts A record
|
||||
let rdata = RData::A(Ipv4Addr::new(1, 2, 3, 4));
|
||||
let record = Record::from_rdata(lookup_name.clone(), u32::MAX, rdata);
|
||||
let record_set = RecordSet::from(record);
|
||||
map.insert(
|
||||
RrKey::new(lookup_name_lower.clone(), RecordType::A),
|
||||
record_set,
|
||||
);
|
||||
|
||||
// Inserts AAAA record
|
||||
let rdata = RData::AAAA(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8));
|
||||
let record = Record::from_rdata(lookup_name.clone(), u32::MAX, rdata);
|
||||
let record_set = RecordSet::from(record);
|
||||
map.insert(
|
||||
RrKey::new(lookup_name_lower.clone(), RecordType::AAAA),
|
||||
record_set,
|
||||
);
|
||||
|
||||
// Inserts ANAME record
|
||||
let rdata = RData::ANAME(Name::from_str("aname.com").unwrap());
|
||||
let record = Record::from_rdata(lookup_name.clone(), u32::MAX, rdata);
|
||||
let record_set = RecordSet::from(record);
|
||||
map.insert(
|
||||
RrKey::new(lookup_name_lower.clone(), RecordType::ANAME),
|
||||
record_set,
|
||||
);
|
||||
|
||||
// Inserts CNAME record
|
||||
let rdata = RData::CNAME(Name::from_str("cname.com").unwrap());
|
||||
let record =
|
||||
Record::from_rdata(Name::from_str("foo").unwrap(), u32::MAX, rdata);
|
||||
let record_set = RecordSet::from(record);
|
||||
map.insert(
|
||||
RrKey::new(lookup_name_lower.clone(), RecordType::CNAME),
|
||||
record_set,
|
||||
);
|
||||
|
||||
// Inserts MX record
|
||||
let rdata = RData::MX(MX::new(0, Name::from_str("mx.com").unwrap()));
|
||||
let record = Record::from_rdata(lookup_name.clone(), u32::MAX, rdata);
|
||||
let record_set = RecordSet::from(record);
|
||||
map.insert(
|
||||
RrKey::new(lookup_name_lower.clone(), RecordType::MX),
|
||||
record_set,
|
||||
);
|
||||
|
||||
// Inserts PTR record
|
||||
let rdata = RData::PTR(Name::from_str("ptr.com").unwrap());
|
||||
let record = Record::from_rdata(
|
||||
Name::from_str("5.6.7.8").unwrap(),
|
||||
u32::MAX,
|
||||
rdata,
|
||||
);
|
||||
let record_set = RecordSet::from(record);
|
||||
map.insert(
|
||||
RrKey::new("5.6.7.8".parse().unwrap(), RecordType::PTR),
|
||||
record_set,
|
||||
);
|
||||
|
||||
// Inserts SRV record
|
||||
let rdata = RData::SRV(SRV::new(
|
||||
0,
|
||||
100,
|
||||
1234,
|
||||
Name::from_str("srv.com").unwrap(),
|
||||
));
|
||||
let record = Record::from_rdata(
|
||||
Name::from_str("_Service._TCP.example.com").unwrap(),
|
||||
u32::MAX,
|
||||
rdata,
|
||||
);
|
||||
let record_set = RecordSet::from(record);
|
||||
map.insert(
|
||||
RrKey::new(lookup_name_lower.clone(), RecordType::SRV),
|
||||
record_set,
|
||||
);
|
||||
|
||||
// Inserts TXT record
|
||||
let rdata =
|
||||
RData::TXT(TXT::new(vec!["foo".to_string(), "bar".to_string()]));
|
||||
let record = Record::from_rdata(lookup_name, u32::MAX, rdata);
|
||||
let record_set = RecordSet::from(record);
|
||||
map.insert(RrKey::new(lookup_name_lower, RecordType::TXT), record_set);
|
||||
|
||||
map
|
||||
};
|
||||
|
||||
let authority = Box::new(Arc::new(RwLock::new(
|
||||
InMemoryAuthority::new(
|
||||
Name::from_str("com").unwrap(),
|
||||
records,
|
||||
ZoneType::Primary,
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
)));
|
||||
let mut c = Catalog::new();
|
||||
c.upsert(Name::root().into(), authority);
|
||||
c
|
||||
};
|
||||
|
||||
let mut server_fut = ServerFuture::new(catalog);
|
||||
let socket_addr = SocketAddr::from(([127, 0, 0, 1], DNS_PORT));
|
||||
let tcp_listener = TcpListener::bind(socket_addr).await.unwrap();
|
||||
let udp_socket = UdpSocket::bind(socket_addr).await.unwrap();
|
||||
server_fut.register_socket(udp_socket);
|
||||
server_fut.register_listener(tcp_listener, Duration::from_secs(2));
|
||||
|
||||
// Notifies that the DNS server is ready
|
||||
tx.send(()).unwrap();
|
||||
|
||||
server_fut.block_until_done().await.unwrap();
|
||||
}
|
||||
|
||||
let (ready_tx, ready_rx) = oneshot::channel();
|
||||
let dns_server_fut = run_dns_server(ready_tx);
|
||||
let handle = tokio::spawn(dns_server_fut);
|
||||
|
||||
// Waits for the DNS server to be ready
|
||||
ready_rx.await.unwrap();
|
||||
|
||||
// Pass: `--allow-net`
|
||||
{
|
||||
let output = util::deno_cmd()
|
||||
.current_dir(util::tests_path())
|
||||
.env("NO_COLOR", "1")
|
||||
.arg("run")
|
||||
.arg("--allow-net")
|
||||
.arg("--unstable")
|
||||
.arg("resolve_dns.ts")
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.wait_with_output()
|
||||
.unwrap();
|
||||
let err = String::from_utf8_lossy(&output.stderr);
|
||||
let out = String::from_utf8_lossy(&output.stdout);
|
||||
assert!(output.status.success());
|
||||
assert!(err.starts_with("Check file"));
|
||||
|
||||
let expected =
|
||||
std::fs::read_to_string(util::tests_path().join("resolve_dns.ts.out"))
|
||||
.unwrap();
|
||||
assert_eq!(expected, out);
|
||||
}
|
||||
|
||||
// Pass: `--allow-net=127.0.0.1:4553`
|
||||
{
|
||||
let output = util::deno_cmd()
|
||||
.current_dir(util::tests_path())
|
||||
.env("NO_COLOR", "1")
|
||||
.arg("run")
|
||||
.arg("--allow-net=127.0.0.1:4553")
|
||||
.arg("--unstable")
|
||||
.arg("resolve_dns.ts")
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.wait_with_output()
|
||||
.unwrap();
|
||||
let err = String::from_utf8_lossy(&output.stderr);
|
||||
let out = String::from_utf8_lossy(&output.stdout);
|
||||
assert!(output.status.success());
|
||||
assert!(err.starts_with("Check file"));
|
||||
|
||||
let expected =
|
||||
std::fs::read_to_string(util::tests_path().join("resolve_dns.ts.out"))
|
||||
.unwrap();
|
||||
assert_eq!(expected, out);
|
||||
}
|
||||
|
||||
// Permission error: `--allow-net=deno.land`
|
||||
{
|
||||
let output = util::deno_cmd()
|
||||
.current_dir(util::tests_path())
|
||||
.env("NO_COLOR", "1")
|
||||
.arg("run")
|
||||
.arg("--allow-net=deno.land")
|
||||
.arg("--unstable")
|
||||
.arg("resolve_dns.ts")
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.wait_with_output()
|
||||
.unwrap();
|
||||
let err = String::from_utf8_lossy(&output.stderr);
|
||||
let out = String::from_utf8_lossy(&output.stdout);
|
||||
assert!(!output.status.success());
|
||||
assert!(err.starts_with("Check file"));
|
||||
assert!(err.contains(r#"error: Uncaught (in promise) PermissionDenied: network access to "127.0.0.1:4553""#));
|
||||
assert!(out.is_empty());
|
||||
}
|
||||
|
||||
// Permission error: no permission specified
|
||||
{
|
||||
let output = util::deno_cmd()
|
||||
.current_dir(util::tests_path())
|
||||
.env("NO_COLOR", "1")
|
||||
.arg("run")
|
||||
.arg("--unstable")
|
||||
.arg("resolve_dns.ts")
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.wait_with_output()
|
||||
.unwrap();
|
||||
let err = String::from_utf8_lossy(&output.stderr);
|
||||
let out = String::from_utf8_lossy(&output.stdout);
|
||||
assert!(!output.status.success());
|
||||
assert!(err.starts_with("Check file"));
|
||||
assert!(err.contains(r#"error: Uncaught (in promise) PermissionDenied: network access to "127.0.0.1:4553""#));
|
||||
assert!(out.is_empty());
|
||||
}
|
||||
|
||||
handle.abort();
|
||||
}
|
||||
|
|
36
cli/tests/resolve_dns.ts
Normal file
36
cli/tests/resolve_dns.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
const nameServer = { nameServer: { ipAddr: "127.0.0.1", port: 4553 } };
|
||||
|
||||
const [a, aaaa, aname, cname, mx, ptr, srv, txt] = await Promise.all([
|
||||
Deno.resolveDns("www.example.com", "A", nameServer),
|
||||
Deno.resolveDns("www.example.com", "AAAA", nameServer),
|
||||
Deno.resolveDns("www.example.com", "ANAME", nameServer),
|
||||
Deno.resolveDns("foo", "CNAME", nameServer),
|
||||
Deno.resolveDns("www.example.com", "MX", nameServer),
|
||||
Deno.resolveDns("5.6.7.8", "PTR", nameServer),
|
||||
Deno.resolveDns("_Service._TCP.example.com", "SRV", nameServer),
|
||||
Deno.resolveDns("www.example.com", "TXT", nameServer),
|
||||
]);
|
||||
|
||||
console.log("A");
|
||||
console.log(JSON.stringify(a));
|
||||
|
||||
console.log("AAAA");
|
||||
console.log(JSON.stringify(aaaa));
|
||||
|
||||
console.log("ANAME");
|
||||
console.log(JSON.stringify(aname));
|
||||
|
||||
console.log("CNAME");
|
||||
console.log(JSON.stringify(cname));
|
||||
|
||||
console.log("MX");
|
||||
console.log(JSON.stringify(mx));
|
||||
|
||||
console.log("PTR");
|
||||
console.log(JSON.stringify(ptr));
|
||||
|
||||
console.log("SRV");
|
||||
console.log(JSON.stringify(srv));
|
||||
|
||||
console.log("TXT");
|
||||
console.log(JSON.stringify(txt));
|
16
cli/tests/resolve_dns.ts.out
Normal file
16
cli/tests/resolve_dns.ts.out
Normal file
|
@ -0,0 +1,16 @@
|
|||
A
|
||||
["1.2.3.4"]
|
||||
AAAA
|
||||
["1:2:3:4:5:6:7:8"]
|
||||
ANAME
|
||||
["aname.com."]
|
||||
CNAME
|
||||
["cname.com."]
|
||||
MX
|
||||
[{"preference":0,"exchange":"mx.com."}]
|
||||
PTR
|
||||
["ptr.com."]
|
||||
SRV
|
||||
[{"priority":0,"weight":100,"port":1234,"target":"srv.com."}]
|
||||
TXT
|
||||
[["foo","bar"]]
|
|
@ -61,6 +61,8 @@ tokio-rustls = "0.22.0"
|
|||
uuid = { version = "0.8.2", features = ["v4"] }
|
||||
webpki = "0.21.4"
|
||||
webpki-roots = "0.21.0"
|
||||
trust-dns-proto = "0.20.0"
|
||||
trust-dns-resolver = { version = "0.20.0", features = ["tokio-runtime", "serde-config"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
fwdansi = "1.1.0"
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
return core.jsonOpAsync("op_datagram_send", args, zeroCopy);
|
||||
}
|
||||
|
||||
function resolveDns(query, recordType, options) {
|
||||
return core.jsonOpAsync("op_dns_resolve", { query, recordType, options });
|
||||
}
|
||||
|
||||
class Conn {
|
||||
#rid = 0;
|
||||
#remoteAddr = null;
|
||||
|
@ -210,5 +214,6 @@
|
|||
Listener,
|
||||
shutdown,
|
||||
Datagram,
|
||||
resolveDns,
|
||||
};
|
||||
})(this);
|
||||
|
|
|
@ -111,6 +111,7 @@
|
|||
applySourceMap: __bootstrap.errorStack.opApplySourceMap,
|
||||
formatDiagnostics: __bootstrap.errorStack.opFormatDiagnostics,
|
||||
shutdown: __bootstrap.net.shutdown,
|
||||
resolveDns: __bootstrap.net.resolveDns,
|
||||
listen: __bootstrap.netUnstable.listen,
|
||||
connect: __bootstrap.netUnstable.connect,
|
||||
listenDatagram: __bootstrap.netUnstable.listenDatagram,
|
||||
|
|
|
@ -22,6 +22,7 @@ use deno_core::RcRef;
|
|||
use deno_core::Resource;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::net::SocketAddr;
|
||||
|
@ -30,6 +31,13 @@ use tokio::io::AsyncWriteExt;
|
|||
use tokio::net::TcpListener;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::net::UdpSocket;
|
||||
use trust_dns_proto::rr::record_data::RData;
|
||||
use trust_dns_proto::rr::record_type::RecordType;
|
||||
use trust_dns_resolver::config::NameServerConfigGroup;
|
||||
use trust_dns_resolver::config::ResolverConfig;
|
||||
use trust_dns_resolver::config::ResolverOpts;
|
||||
use trust_dns_resolver::system_conf;
|
||||
use trust_dns_resolver::AsyncResolver;
|
||||
|
||||
#[cfg(unix)]
|
||||
use super::net_unix;
|
||||
|
@ -45,6 +53,7 @@ pub fn init(rt: &mut deno_core::JsRuntime) {
|
|||
super::reg_json_sync(rt, "op_listen", op_listen);
|
||||
super::reg_json_async(rt, "op_datagram_receive", op_datagram_receive);
|
||||
super::reg_json_async(rt, "op_datagram_send", op_datagram_send);
|
||||
super::reg_json_async(rt, "op_dns_resolve", op_dns_resolve);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -531,3 +540,249 @@ fn op_listen(
|
|||
_ => Err(type_error("Wrong argument format!")),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, PartialEq, Debug)]
|
||||
#[serde(untagged)]
|
||||
enum DnsReturnRecord {
|
||||
A(String),
|
||||
AAAA(String),
|
||||
ANAME(String),
|
||||
CNAME(String),
|
||||
MX {
|
||||
preference: u16,
|
||||
exchange: String,
|
||||
},
|
||||
PTR(String),
|
||||
SRV {
|
||||
priority: u16,
|
||||
weight: u16,
|
||||
port: u16,
|
||||
target: String,
|
||||
},
|
||||
TXT(Vec<String>),
|
||||
}
|
||||
|
||||
async fn op_dns_resolve(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
args: Value,
|
||||
_zero_copy: BufVec,
|
||||
) -> Result<Value, AnyError> {
|
||||
fn default_port() -> u16 {
|
||||
53
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct ResolveAddrArgs {
|
||||
query: String,
|
||||
record_type: RecordType,
|
||||
options: Option<ResolveDnsOption>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct ResolveDnsOption {
|
||||
name_server: Option<NameServer>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct NameServer {
|
||||
ip_addr: String,
|
||||
#[serde(default = "default_port")]
|
||||
port: u16,
|
||||
}
|
||||
|
||||
let ResolveAddrArgs {
|
||||
query,
|
||||
record_type,
|
||||
options,
|
||||
} = serde_json::from_value(args)?;
|
||||
|
||||
let (config, opts) = if let Some(name_server) =
|
||||
options.as_ref().and_then(|o| o.name_server.as_ref())
|
||||
{
|
||||
let group = NameServerConfigGroup::from_ips_clear(
|
||||
&[name_server.ip_addr.parse()?],
|
||||
name_server.port,
|
||||
true,
|
||||
);
|
||||
(
|
||||
ResolverConfig::from_parts(None, vec![], group),
|
||||
ResolverOpts::default(),
|
||||
)
|
||||
} else {
|
||||
system_conf::read_system_conf()?
|
||||
};
|
||||
|
||||
{
|
||||
let s = state.borrow();
|
||||
let perm = s.borrow::<Permissions>();
|
||||
|
||||
// Checks permission against the name servers which will be actually queried.
|
||||
for ns in config.name_servers() {
|
||||
let socker_addr = &ns.socket_addr;
|
||||
let ip = socker_addr.ip().to_string();
|
||||
let port = socker_addr.port();
|
||||
perm.check_net(&(ip, Some(port)))?;
|
||||
}
|
||||
}
|
||||
|
||||
let resolver = AsyncResolver::tokio(config, opts)?;
|
||||
|
||||
let results: Vec<DnsReturnRecord> = resolver
|
||||
.lookup(query, record_type, Default::default())
|
||||
.await?
|
||||
.iter()
|
||||
.filter_map(rdata_to_return_record(record_type))
|
||||
.collect();
|
||||
|
||||
Ok(json!(results))
|
||||
}
|
||||
|
||||
fn rdata_to_return_record(
|
||||
ty: RecordType,
|
||||
) -> impl Fn(&RData) -> Option<DnsReturnRecord> {
|
||||
use RecordType::*;
|
||||
move |r: &RData| -> Option<DnsReturnRecord> {
|
||||
match ty {
|
||||
A => r.as_a().map(ToString::to_string).map(DnsReturnRecord::A),
|
||||
AAAA => r
|
||||
.as_aaaa()
|
||||
.map(ToString::to_string)
|
||||
.map(DnsReturnRecord::AAAA),
|
||||
ANAME => r
|
||||
.as_aname()
|
||||
.map(ToString::to_string)
|
||||
.map(DnsReturnRecord::ANAME),
|
||||
CNAME => r
|
||||
.as_cname()
|
||||
.map(ToString::to_string)
|
||||
.map(DnsReturnRecord::CNAME),
|
||||
MX => r.as_mx().map(|mx| DnsReturnRecord::MX {
|
||||
preference: mx.preference(),
|
||||
exchange: mx.exchange().to_string(),
|
||||
}),
|
||||
PTR => r
|
||||
.as_ptr()
|
||||
.map(ToString::to_string)
|
||||
.map(DnsReturnRecord::PTR),
|
||||
SRV => r.as_srv().map(|srv| DnsReturnRecord::SRV {
|
||||
priority: srv.priority(),
|
||||
weight: srv.weight(),
|
||||
port: srv.port(),
|
||||
target: srv.target().to_string(),
|
||||
}),
|
||||
TXT => r.as_txt().map(|txt| {
|
||||
let texts: Vec<String> = txt
|
||||
.iter()
|
||||
.map(|bytes| {
|
||||
// Tries to parse these bytes as Latin-1
|
||||
bytes.iter().map(|&b| b as char).collect::<String>()
|
||||
})
|
||||
.collect();
|
||||
DnsReturnRecord::TXT(texts)
|
||||
}),
|
||||
// TODO(magurotuna): Other record types are not supported
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::net::Ipv6Addr;
|
||||
use trust_dns_proto::rr::rdata::mx::MX;
|
||||
use trust_dns_proto::rr::rdata::srv::SRV;
|
||||
use trust_dns_proto::rr::rdata::txt::TXT;
|
||||
use trust_dns_proto::rr::record_data::RData;
|
||||
use trust_dns_proto::rr::Name;
|
||||
|
||||
#[test]
|
||||
fn rdata_to_return_record_a() {
|
||||
let func = rdata_to_return_record(RecordType::A);
|
||||
let rdata = RData::A(Ipv4Addr::new(127, 0, 0, 1));
|
||||
assert_eq!(
|
||||
func(&rdata),
|
||||
Some(DnsReturnRecord::A("127.0.0.1".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rdata_to_return_record_aaaa() {
|
||||
let func = rdata_to_return_record(RecordType::AAAA);
|
||||
let rdata = RData::AAAA(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
|
||||
assert_eq!(func(&rdata), Some(DnsReturnRecord::AAAA("::1".to_string())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rdata_to_return_record_aname() {
|
||||
let func = rdata_to_return_record(RecordType::ANAME);
|
||||
let rdata = RData::ANAME(Name::new());
|
||||
assert_eq!(func(&rdata), Some(DnsReturnRecord::ANAME("".to_string())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rdata_to_return_record_cname() {
|
||||
let func = rdata_to_return_record(RecordType::CNAME);
|
||||
let rdata = RData::CNAME(Name::new());
|
||||
assert_eq!(func(&rdata), Some(DnsReturnRecord::CNAME("".to_string())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rdata_to_return_record_mx() {
|
||||
let func = rdata_to_return_record(RecordType::MX);
|
||||
let rdata = RData::MX(MX::new(10, Name::new()));
|
||||
assert_eq!(
|
||||
func(&rdata),
|
||||
Some(DnsReturnRecord::MX {
|
||||
preference: 10,
|
||||
exchange: "".to_string()
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rdata_to_return_record_ptr() {
|
||||
let func = rdata_to_return_record(RecordType::PTR);
|
||||
let rdata = RData::PTR(Name::new());
|
||||
assert_eq!(func(&rdata), Some(DnsReturnRecord::PTR("".to_string())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rdata_to_return_record_srv() {
|
||||
let func = rdata_to_return_record(RecordType::SRV);
|
||||
let rdata = RData::SRV(SRV::new(1, 2, 3, Name::new()));
|
||||
assert_eq!(
|
||||
func(&rdata),
|
||||
Some(DnsReturnRecord::SRV {
|
||||
priority: 1,
|
||||
weight: 2,
|
||||
port: 3,
|
||||
target: "".to_string()
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rdata_to_return_record_txt() {
|
||||
let func = rdata_to_return_record(RecordType::TXT);
|
||||
let rdata = RData::TXT(TXT::from_bytes(vec![
|
||||
"foo".as_bytes(),
|
||||
"bar".as_bytes(),
|
||||
&[0xa3], // "£" in Latin-1
|
||||
&[0xe3, 0x81, 0x82], // "あ" in UTF-8
|
||||
]));
|
||||
assert_eq!(
|
||||
func(&rdata),
|
||||
Some(DnsReturnRecord::TXT(vec![
|
||||
"foo".to_string(),
|
||||
"bar".to_string(),
|
||||
"£".to_string(),
|
||||
"ã\u{81}\u{82}".to_string(),
|
||||
]))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -818,7 +818,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_net() {
|
||||
fn test_check_net_with_values() {
|
||||
let perms = Permissions::from_options(&PermissionsOptions {
|
||||
allow_net: Some(svec![
|
||||
"localhost",
|
||||
|
@ -854,6 +854,93 @@ mod tests {
|
|||
("192.168.0.1", 0, false),
|
||||
];
|
||||
|
||||
for (host, port, is_ok) in domain_tests {
|
||||
assert_eq!(is_ok, perms.check_net(&(host, Some(port))).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_net_only_flag() {
|
||||
let perms = Permissions::from_options(&PermissionsOptions {
|
||||
allow_net: Some(svec![]), // this means `--allow-net` is present without values following `=` sign
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let domain_tests = vec![
|
||||
("localhost", 1234),
|
||||
("deno.land", 0),
|
||||
("deno.land", 3000),
|
||||
("deno.lands", 0),
|
||||
("deno.lands", 3000),
|
||||
("github.com", 3000),
|
||||
("github.com", 0),
|
||||
("github.com", 2000),
|
||||
("github.net", 3000),
|
||||
("127.0.0.1", 0),
|
||||
("127.0.0.1", 3000),
|
||||
("127.0.0.2", 0),
|
||||
("127.0.0.2", 3000),
|
||||
("172.16.0.2", 8000),
|
||||
("172.16.0.2", 0),
|
||||
("172.16.0.2", 6000),
|
||||
("172.16.0.1", 8000),
|
||||
("somedomain", 0),
|
||||
("192.168.0.1", 0),
|
||||
];
|
||||
|
||||
for (host, port) in domain_tests {
|
||||
assert!(perms.check_net(&(host, Some(port))).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_net_no_flag() {
|
||||
let perms = Permissions::from_options(&PermissionsOptions {
|
||||
allow_net: None,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let domain_tests = vec![
|
||||
("localhost", 1234),
|
||||
("deno.land", 0),
|
||||
("deno.land", 3000),
|
||||
("deno.lands", 0),
|
||||
("deno.lands", 3000),
|
||||
("github.com", 3000),
|
||||
("github.com", 0),
|
||||
("github.com", 2000),
|
||||
("github.net", 3000),
|
||||
("127.0.0.1", 0),
|
||||
("127.0.0.1", 3000),
|
||||
("127.0.0.2", 0),
|
||||
("127.0.0.2", 3000),
|
||||
("172.16.0.2", 8000),
|
||||
("172.16.0.2", 0),
|
||||
("172.16.0.2", 6000),
|
||||
("172.16.0.1", 8000),
|
||||
("somedomain", 0),
|
||||
("192.168.0.1", 0),
|
||||
];
|
||||
|
||||
for (host, port) in domain_tests {
|
||||
assert!(!perms.check_net(&(host, Some(port))).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_net_url() {
|
||||
let perms = Permissions::from_options(&PermissionsOptions {
|
||||
allow_net: Some(svec![
|
||||
"localhost",
|
||||
"deno.land",
|
||||
"github.com:3000",
|
||||
"127.0.0.1",
|
||||
"172.16.0.2:8000",
|
||||
"www.github.com:443"
|
||||
]),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let url_tests = vec![
|
||||
// Any protocol + port for localhost should be ok, since we don't specify
|
||||
("http://localhost", true),
|
||||
|
@ -893,13 +980,9 @@ mod tests {
|
|||
("https://www.github.com:443/robots.txt", true),
|
||||
];
|
||||
|
||||
for (url_str, is_ok) in url_tests.iter() {
|
||||
for (url_str, is_ok) in url_tests {
|
||||
let u = url::Url::parse(url_str).unwrap();
|
||||
assert_eq!(*is_ok, perms.check_net_url(&u).is_ok());
|
||||
}
|
||||
|
||||
for (hostname, port, is_ok) in domain_tests.iter() {
|
||||
assert_eq!(*is_ok, perms.check_net(&(hostname, Some(*port))).is_ok());
|
||||
assert_eq!(is_ok, perms.check_net_url(&u).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
use core::mem::replace;
|
||||
use futures::FutureExt;
|
||||
use futures::Stream;
|
||||
use futures::StreamExt;
|
||||
|
@ -28,6 +27,7 @@ use std::env;
|
|||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::mem::replace;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
|
|
Loading…
Reference in a new issue