0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

feat: add signal option to Deno.resolveDns (#17384)

Closes #14406
This commit is contained in:
Leo Kettmeir 2023-02-11 15:14:02 +01:00 committed by GitHub
parent e22ebc6b6b
commit a55f0eb2fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 5 deletions

View file

@ -69,3 +69,25 @@ try {
} catch (e) {
console.log(e.message);
}
try {
const ac = new AbortController();
queueMicrotask(() => ac.abort());
await Deno.resolveDns("www.example.com", "A", {
...nameServer,
signal: ac.signal,
});
} catch (e) {
console.log(e.name);
}
try {
const ac = new AbortController();
ac.abort();
await Deno.resolveDns("www.example.com", "A", {
...nameServer,
signal: ac.signal,
});
} catch (e) {
console.log(e.name);
}

View file

@ -24,3 +24,5 @@ TXT
[["I","am","a","txt","record"],["I","am","another","txt","record"],["I am a different","txt record"],["key=val"]]
Error NotFound thrown for not-found-example.com
Provided record type is not supported
AbortError
AbortError

View file

@ -4989,6 +4989,12 @@ declare namespace Deno {
* @default {53} */
port?: number;
};
/**
* An abort signal to allow cancellation of the DNS resolution operation.
* If the signal becomes aborted the resolveDns operation will be stopped
* and the promise returned will be rejected with an AbortError.
*/
signal?: AbortSignal;
}
/** If {@linkcode Deno.resolveDns} is called with `"CAA"` record type

View file

@ -8,6 +8,7 @@ import {
readableStreamForRidUnrefableUnref,
writableStreamForRid,
} from "internal:deno_web/06_streams.js";
import * as abortSignal from "internal:deno_web/03_abort_signal.js";
const primordials = globalThis.__bootstrap.primordials;
const {
Error,
@ -30,8 +31,31 @@ function shutdown(rid) {
return core.shutdown(rid);
}
function resolveDns(query, recordType, options) {
return core.opAsync("op_dns_resolve", { query, recordType, options });
async function resolveDns(query, recordType, options) {
let cancelRid;
let abortHandler;
if (options?.signal) {
options.signal.throwIfAborted();
cancelRid = ops.op_cancel_handle();
abortHandler = () => core.tryClose(cancelRid);
options.signal[abortSignal.add](abortHandler);
}
try {
return await core.opAsync("op_dns_resolve", {
cancelRid,
query,
recordType,
options,
});
} finally {
if (options?.signal) {
options.signal[abortSignal.remove](abortHandler);
// always throw the abort error when aborted
options.signal.throwIfAborted();
}
}
}
class Conn {

View file

@ -9,6 +9,7 @@ use deno_core::error::custom_error;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::CancelFuture;
use deno_core::AsyncRefCell;
use deno_core::ByteString;
@ -416,6 +417,7 @@ pub enum DnsReturnRecord {
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ResolveAddrArgs {
cancel_rid: Option<ResourceId>,
query: String,
record_type: RecordType,
options: Option<ResolveDnsOption>,
@ -451,6 +453,7 @@ where
query,
record_type,
options,
cancel_rid,
} = args;
let (config, opts) = if let Some(name_server) =
@ -484,9 +487,29 @@ where
let resolver = AsyncResolver::tokio(config, opts)?;
resolver
.lookup(query, record_type)
.await
let lookup_fut = resolver.lookup(query, record_type);
let cancel_handle = cancel_rid.and_then(|rid| {
state
.borrow_mut()
.resource_table
.get::<CancelHandle>(rid)
.ok()
});
let lookup = if let Some(cancel_handle) = cancel_handle {
let lookup_rv = lookup_fut.or_cancel(cancel_handle).await;
if let Some(cancel_rid) = cancel_rid {
state.borrow_mut().resource_table.close(cancel_rid).ok();
};
lookup_rv?
} else {
lookup_fut.await
};
lookup
.map_err(|e| {
let message = format!("{e}");
match e.kind() {