mirror of
https://github.com/SukkaW/Surge.git
synced 2026-04-29 17:36:56 +08:00
Chore: fix domain alive check DoH [skip ci]
This commit is contained in:
@@ -195,25 +195,53 @@ export async function $$fetch(url: RequestInfo, init: RequestInit = defaultReque
|
|||||||
export { $$fetch as '~fetch' };
|
export { $$fetch as '~fetch' };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fetch wrapper for DoH (DNS-over-HTTPS) usage where the input may be a
|
* dohdec constructs its own `Request` object for its `hooks` from `globalThis.Request`
|
||||||
* `Request` object created by a different undici instance or Node.js globals.
|
*
|
||||||
* Without normalisation, undici's internal `instanceof Request` check fails and
|
* But we are using `undici.fetch` instead of `globalThis.fetch`, hence the version
|
||||||
* it tries to parse `[object Request]` as a URL.
|
* mismatch.
|
||||||
* See https://github.com/nodejs/undici/issues/2155
|
*
|
||||||
|
* undici, on the other hand, use `instanceof Request` internally for narrowing, resulting
|
||||||
|
* in it treats foreign `Request` objects as `URL` and try to parse them as URLs, causing
|
||||||
|
* `TypeError: Failed to construct 'URL': [object Request]`
|
||||||
|
*
|
||||||
|
* See also https://github.com/nodejs/undici/issues/2155
|
||||||
|
*
|
||||||
|
* We already know that dohdec will only pass one `Request` object to `fetch` because
|
||||||
|
* of its internal `hooks`:
|
||||||
|
*
|
||||||
|
* https://github.com/hildjj/dohdec/blob/d2f763db62d46f505d109be12bc697224cd42f93/pkg/dohdec/lib/doh.js#L291
|
||||||
*/
|
*/
|
||||||
export async function fetchForDoH(input: RequestInfo, init?: RequestInit) {
|
export async function fetchForDoH(input: RequestInfo, _init?: RequestInit) {
|
||||||
if (typeof input === 'object' && 'url' in input) {
|
if (typeof input === 'object' && 'url' in input) {
|
||||||
// Normalise the foreign Request into a proper undici Request, preserving all
|
// Read body as ArrayBuffer before re-wrapping. The original body is a ReadableStream
|
||||||
// of its properties. init is passed separately so undici merges them itself,
|
// from a foreign context (different undici instance / Node.js globals). Passing it
|
||||||
// exactly as real fetch(request, init) would — no manual header handling needed.
|
// directly to new UndiciRequest fails undici's instanceof ReadableStream check and
|
||||||
|
// silently drops the body. ArrayBuffer is a plain value with no cross-context issues,
|
||||||
|
// and also allows the retry interceptor to re-send the body on retries.
|
||||||
|
const body = input.body === null ? null : await input.arrayBuffer();
|
||||||
|
|
||||||
input = new UndiciRequest(input.url, {
|
input = new UndiciRequest(input.url, {
|
||||||
...input,
|
method: input.method,
|
||||||
// force no-referrer to avoid about:client
|
mode: input.mode,
|
||||||
|
credentials: input.credentials,
|
||||||
|
cache: input.cache,
|
||||||
|
redirect: input.redirect,
|
||||||
|
integrity: input.integrity,
|
||||||
|
keepalive: input.keepalive,
|
||||||
|
signal: input.signal,
|
||||||
|
headers: input.headers,
|
||||||
|
body,
|
||||||
|
|
||||||
|
referrer: '',
|
||||||
referrerPolicy: 'no-referrer',
|
referrerPolicy: 'no-referrer',
|
||||||
referrer: ''
|
dispatcher: agent
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return $$fetch(input, init);
|
|
||||||
|
// DoH servers may return a valid DNS wire format body with a non-200 status
|
||||||
|
// (e.g. 503 with a DNS SERVFAIL). Let the DoH client parse the body and decide
|
||||||
|
// — never throw on HTTP status here.
|
||||||
|
return undici.fetch(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @deprecated -- undici.requests doesn't support gzip/br/deflate, and has difficulty w/ undidi cache */
|
/** @deprecated -- undici.requests doesn't support gzip/br/deflate, and has difficulty w/ undidi cache */
|
||||||
|
|||||||
Reference in New Issue
Block a user