@fedify/vocab-runtime 2.5.0-dev.2448 → 2.5.0-dev.2492
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deno.json +5 -2
- package/dist/{docloader-BBnBpbsG.d.cts → docloader-DD6binpN.d.cts} +4 -8
- package/dist/{docloader-BBnBpbsG.d.ts → docloader-DD6binpN.d.ts} +4 -8
- package/dist/internal/jsonld-cache.cjs +1 -1
- package/dist/internal/jsonld-cache.d.cts +1 -1
- package/dist/internal/jsonld-cache.d.ts +1 -1
- package/dist/internal/jsonld-cache.js +1 -1
- package/dist/internal/portable-dereference.cjs +1 -1
- package/dist/internal/portable-dereference.d.cts +2 -2
- package/dist/internal/portable-dereference.d.ts +2 -2
- package/dist/internal/portable-dereference.js +1 -1
- package/dist/internal.cjs +6 -0
- package/dist/internal.d.cts +108 -0
- package/dist/internal.d.ts +108 -0
- package/dist/internal.js +3 -0
- package/dist/mod.cjs +104 -38
- package/dist/mod.d.cts +3 -336
- package/dist/mod.d.ts +4 -336
- package/dist/mod.js +104 -38
- package/dist/{portable-BDydjp5H.d.ts → portable-1VSnSJFj.d.ts} +1 -1
- package/dist/{portable-Dfvcg_Wy.d.cts → portable-Cr7NwZwb.d.cts} +1 -1
- package/dist/public-fetch-Dvfvawei.cjs +527 -0
- package/dist/public-fetch-ziZ39L5I.js +510 -0
- package/dist/tests/{body-DP2u2wUX.cjs → body-C8d1PmDa.cjs} +1 -1
- package/dist/tests/{body-oV99TVdA.mjs → body-HSLxhexN.mjs} +1 -1
- package/dist/tests/body.test.cjs +1 -1
- package/dist/tests/body.test.mjs +1 -1
- package/dist/tests/decimal.test.cjs +4 -4
- package/dist/tests/decimal.test.mjs +4 -4
- package/dist/tests/{docloader-CwxZguqN.cjs → docloader-D1fNCGam.cjs} +111 -39
- package/dist/tests/{docloader-D3mA7aPJ.mjs → docloader-DkEUFJui.mjs} +106 -40
- package/dist/tests/docloader.test.cjs +531 -1293
- package/dist/tests/docloader.test.mjs +472 -1252
- package/dist/tests/esm-Ds-eHTfY.mjs +1229 -0
- package/dist/tests/esm-Q2tdh5f3.cjs +1215 -0
- package/dist/tests/internal/portable-dereference.test.cjs +3 -3
- package/dist/tests/internal/portable-dereference.test.mjs +3 -3
- package/dist/tests/{jsonld-cache-BEXiiM-V.cjs → jsonld-cache-DKIWKxEX.cjs} +1 -1
- package/dist/tests/{jsonld-cache-DFnWsLuZ.mjs → jsonld-cache-KH40z9_7.mjs} +1 -1
- package/dist/tests/jsonld-cache.test.cjs +2 -2
- package/dist/tests/jsonld-cache.test.mjs +2 -2
- package/dist/tests/node-CbBR-th-.mjs +84 -0
- package/dist/tests/node-Ch29PDXR.cjs +89 -0
- package/dist/tests/pin-grant-CPrpk1l4.cjs +70 -0
- package/dist/tests/pin-grant-H5XhM1Xs.mjs +53 -0
- package/dist/tests/pin-grant.test.cjs +87 -0
- package/dist/tests/pin-grant.test.d.cts +1 -0
- package/dist/tests/pin-grant.test.d.mts +1 -0
- package/dist/tests/pin-grant.test.mjs +88 -0
- package/dist/tests/pinners/bun.test.cjs +166 -0
- package/dist/tests/pinners/bun.test.d.cts +1 -0
- package/dist/tests/pinners/bun.test.d.mts +1 -0
- package/dist/tests/pinners/bun.test.mjs +167 -0
- package/dist/tests/pinners/node.test.cjs +269 -0
- package/dist/tests/pinners/node.test.d.cts +1 -0
- package/dist/tests/pinners/node.test.d.mts +1 -0
- package/dist/tests/pinners/node.test.mjs +268 -0
- package/dist/tests/pinners/pinners.test.cjs +196 -0
- package/dist/tests/pinners/pinners.test.d.cts +1 -0
- package/dist/tests/pinners/pinners.test.d.mts +1 -0
- package/dist/tests/pinners/pinners.test.mjs +197 -0
- package/dist/tests/pinners/testdata/node-child.cjs +135 -0
- package/dist/tests/pinners/testdata/node-child.d.cts +1 -0
- package/dist/tests/pinners/testdata/node-child.d.mts +1 -0
- package/dist/tests/pinners/testdata/node-child.mjs +134 -0
- package/dist/tests/pinners-DLH_npLf.cjs +220 -0
- package/dist/tests/pinners-tGcl49uF.mjs +203 -0
- package/dist/tests/{portable-dereference-DaTBBvCj.cjs → portable-dereference-BUoDzMxk.cjs} +2 -2
- package/dist/tests/{portable-dereference-sGRs_qdT.mjs → portable-dereference-Du2k3ngE.mjs} +2 -2
- package/dist/tests/{portable-media-D7ClSjFO.cjs → portable-media-BM9zgj9g.cjs} +3 -3
- package/dist/tests/{portable-media-B-oCeotd.mjs → portable-media-CTxGibcj.mjs} +3 -3
- package/dist/tests/portable-media.test.cjs +1 -1
- package/dist/tests/portable-media.test.mjs +1 -1
- package/dist/tests/portable-workers.test.cjs +2 -2
- package/dist/tests/portable-workers.test.mjs +2 -2
- package/dist/tests/public-fetch-BGj5pzUD.cjs +186 -0
- package/dist/tests/public-fetch-Cxo3Yzdf.mjs +170 -0
- package/dist/tests/public-fetch.test.cjs +1073 -0
- package/dist/tests/public-fetch.test.d.cts +1 -0
- package/dist/tests/public-fetch.test.d.mts +1 -0
- package/dist/tests/public-fetch.test.mjs +1074 -0
- package/dist/tests/{request-B77_oZnk.cjs → request-7q-Zfe1p.cjs} +2 -2
- package/dist/tests/{request-BlLYI4x3.mjs → request-D5uGtmmq.mjs} +2 -2
- package/dist/tests/request.test.cjs +2 -2
- package/dist/tests/request.test.mjs +2 -2
- package/dist/tests/support-Bj44xlQu.mjs +272 -0
- package/dist/tests/support-BrdlbLJk.cjs +363 -0
- package/dist/tests/{url-BNakuZ8k.cjs → url-Bdj-rTcC.cjs} +88 -12
- package/dist/tests/{url-DMxmp7ZG.mjs → url-COj5Q8mb.mjs} +65 -13
- package/dist/tests/url.test.cjs +4 -1
- package/dist/tests/url.test.mjs +4 -1
- package/dist/url-4EE56sNP.d.cts +352 -0
- package/dist/url-4EE56sNP.d.ts +352 -0
- package/dist/{url-DrGTR8yv.cjs → url-DIKZnaJv.cjs} +88 -12
- package/dist/{url-Dzyp-NsC.js → url-mWveR5GA.js} +65 -13
- package/package.json +14 -3
- package/src/docloader.test.ts +696 -48
- package/src/docloader.ts +186 -75
- package/src/internal.ts +13 -0
- package/src/pin-grant.test.ts +118 -0
- package/src/pin-grant.ts +99 -0
- package/src/pinners/bun.test.ts +278 -0
- package/src/pinners/bun.ts +223 -0
- package/src/pinners/mod.ts +59 -0
- package/src/pinners/node.test.ts +415 -0
- package/src/pinners/node.ts +144 -0
- package/src/pinners/pinners.test.ts +316 -0
- package/src/pinners/testdata/node-child.ts +147 -0
- package/src/pinners/testdata/proxy-child.ts +82 -0
- package/src/pinners/testdata/support.ts +343 -0
- package/src/pinners/testdata/tls-cert.pem +12 -0
- package/src/pinners/testdata/tls-child.ts +88 -0
- package/src/pinners/testdata/tls-key.pem +5 -0
- package/src/pinners/types.ts +48 -0
- package/src/public-fetch.test.ts +1286 -0
- package/src/public-fetch.ts +338 -0
- package/src/testdata/public-fetch-deno-worker.ts +74 -0
- package/src/url.test.ts +11 -0
- package/src/url.ts +113 -22
- package/tsdown.config.ts +7 -2
package/dist/mod.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
|
-
import { _ as
|
|
3
|
-
import { i as
|
|
2
|
+
import { _ as parseJsonLdId, a as expandIPv6Address, b as withGatewayHints, c as getFe34Origin, d as haveSameIriOrigin, f as isGatewayUrl, g as parseIri, h as parseGatewayUrl, i as canonicalizePortableUri, l as getGatewayHints, m as isValidPublicIPv6Address, n as UrlError, o as formatIri, p as isValidPublicIPv4Address, r as arePortableUrisEqual, s as fromCompatibleEf61Id, u as haveSameFe34Origin, v as toCompatibleEf61Id, x as withoutGatewayHints, y as validatePublicUrl } from "./url-4EE56sNP.js";
|
|
3
|
+
import { _ as isTransientFetchError, a as DocumentLoaderOptions, c as getDocumentLoader, d as withDocumentLoaderTimeout, f as CreateRequestOptions, g as getUserAgent, h as createActivityPubRequest, i as DocumentLoaderFactoryOptions, l as getRemoteDocument, m as GetUserAgentOptions, n as DocumentLoader, o as GetDocumentLoaderOptions, p as FetchError, r as DocumentLoaderFactory, s as RemoteDocument, t as AuthenticatedDocumentLoaderFactory, u as resolveDocumentLoaderTimeout, v as logRequest } from "./docloader-DD6binpN.js";
|
|
4
|
+
import { i as PortableObjectVerifierOptions, n as PortableObjectVerification, r as PortableObjectVerifier, t as PortableObjectReferrer } from "./portable-1VSnSJFj.js";
|
|
4
5
|
import { TracerProvider } from "@opentelemetry/api";
|
|
6
|
+
|
|
5
7
|
//#region src/contexts.d.ts
|
|
6
8
|
declare const preloadedContexts: Record<string, unknown>;
|
|
7
9
|
//#endregion
|
|
@@ -468,338 +470,4 @@ interface PropertyPreprocessorContext {
|
|
|
468
470
|
*/
|
|
469
471
|
type PropertyPreprocessor<T = unknown> = (value: Json, context: PropertyPreprocessorContext) => T | undefined | Error | Promise<T | undefined | Error>;
|
|
470
472
|
//#endregion
|
|
471
|
-
//#region src/url.d.ts
|
|
472
|
-
declare class UrlError extends Error {
|
|
473
|
-
/**
|
|
474
|
-
* The failure category. Defaults to `"disallowed"`.
|
|
475
|
-
* `"dns"` includes lookup errors and results with no usable IP addresses.
|
|
476
|
-
* @since 2.0.29
|
|
477
|
-
*/
|
|
478
|
-
readonly reason: "dns" | "disallowed";
|
|
479
|
-
constructor(message: string, options?: {
|
|
480
|
-
cause?: unknown;
|
|
481
|
-
reason?: "dns" | "disallowed";
|
|
482
|
-
});
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* Parses a JSON-LD `@id` value as an IRI, including FEP-ef61 portable
|
|
486
|
-
* ActivityPub IRIs. See {@link parseIri} for how IRIs are parsed.
|
|
487
|
-
* @param id The `@id` value.
|
|
488
|
-
* @param base The base IRI to resolve a relative `@id` against.
|
|
489
|
-
* @returns The parsed IRI, or `undefined` if `id` is missing or a blank node
|
|
490
|
-
* identifier.
|
|
491
|
-
* @throws {TypeError} If `id` is not a valid IRI.
|
|
492
|
-
* @since 2.4.0
|
|
493
|
-
*/
|
|
494
|
-
declare function parseJsonLdId(id: string | undefined, base?: string | URL): URL | undefined;
|
|
495
|
-
/**
|
|
496
|
-
* Parses an IRI as a URL, including FEP-ef61 portable ActivityPub IRIs.
|
|
497
|
-
* Portable URI and FEP-ef61 compatible identifier strings whose path contains
|
|
498
|
-
* a `.` or `..` segment, including percent-encoded spellings, throw a
|
|
499
|
-
* `TypeError`: JavaScript `URL` would otherwise identify a different object.
|
|
500
|
-
* This also applies to compatible identifier strings used as relative bases.
|
|
501
|
-
* A `URL` argument may already have lost such segments before this function
|
|
502
|
-
* receives it.
|
|
503
|
-
*
|
|
504
|
-
* Portable IRIs, e.g., `ap://did:key:z6Mk.../actor`, cannot be represented by
|
|
505
|
-
* JavaScript `URL` as they are, so the returned `URL` keeps the DID authority
|
|
506
|
-
* percent-encoded, e.g., `ap+ef61://did%3Akey%3Az6Mk.../actor`. Use
|
|
507
|
-
* {@link formatIri} to get the canonical string back.
|
|
508
|
-
* @param iri The IRI to parse.
|
|
509
|
-
* @param base The base IRI to resolve a relative IRI against.
|
|
510
|
-
* @returns The parsed IRI.
|
|
511
|
-
* @throws {TypeError} If the IRI is malformed.
|
|
512
|
-
* @since 2.4.0
|
|
513
|
-
*/
|
|
514
|
-
declare function parseIri(iri: string | URL, base?: string | URL): URL;
|
|
515
|
-
/**
|
|
516
|
-
* Formats a URL as an IRI, including FEP-ef61 portable ActivityPub IRIs.
|
|
517
|
-
* Portable URI and FEP-ef61 compatible identifier strings with dot segments
|
|
518
|
-
* throw a `TypeError` because their paths cannot be represented by JavaScript
|
|
519
|
-
* `URL` without normalization.
|
|
520
|
-
*
|
|
521
|
-
* Portable IRIs are formatted with the `ap+ef61:` scheme and a decoded DID
|
|
522
|
-
* authority, even if they were parsed from `ap:` IRIs. FEP-ef61 currently
|
|
523
|
-
* recommends the `ap:` scheme, so a future major version of Fedify may change
|
|
524
|
-
* the scheme this function produces. Do not compare its results as strings to
|
|
525
|
-
* tell whether two portable IRIs identify the same object; use
|
|
526
|
-
* `arePortableUrisEqual()` instead.
|
|
527
|
-
* @param iri The IRI to format.
|
|
528
|
-
* @returns The formatted IRI. A string that cannot be parsed as a URL at all
|
|
529
|
-
* is returned unchanged.
|
|
530
|
-
* @throws {TypeError} If the IRI is a malformed portable IRI or FEP-ef61
|
|
531
|
-
* compatible identifier, e.g., one with dot segments.
|
|
532
|
-
* @since 2.4.0
|
|
533
|
-
*/
|
|
534
|
-
declare function formatIri(iri: string | URL): string;
|
|
535
|
-
/**
|
|
536
|
-
* Canonicalizes a FEP-ef61 portable ActivityPub URI for comparison.
|
|
537
|
-
*
|
|
538
|
-
* This accepts both `ap:` and `ap+ef61:` URI strings with decoded or
|
|
539
|
-
* percent-encoded DID authorities. The returned value uses the `ap+ef61:`
|
|
540
|
-
* scheme, a decoded DID authority, and no query component. Pass the raw URI
|
|
541
|
-
* string, not a `URL` object, because JavaScript `URL` normalizes opaque path
|
|
542
|
-
* segments before Fedify can compare them.
|
|
543
|
-
*
|
|
544
|
-
* The `ap+ef61:` scheme of the result is a choice of Fedify's, whereas
|
|
545
|
-
* FEP-ef61 currently canonicalizes portable URIs with the `ap:` scheme.
|
|
546
|
-
* A future major version of Fedify may change the scheme of the result, so
|
|
547
|
-
* do not persist the result as the only copy of an identifier; keep the
|
|
548
|
-
* original URI, and canonicalize it again when comparing.
|
|
549
|
-
*
|
|
550
|
-
* @param input The raw portable ActivityPub URI string to canonicalize.
|
|
551
|
-
* @returns The canonical portable ActivityPub URI string.
|
|
552
|
-
* @throws {TypeError} If the input is not a valid portable ActivityPub IRI.
|
|
553
|
-
* @since 2.4.0
|
|
554
|
-
*/
|
|
555
|
-
declare function canonicalizePortableUri(input: string): string;
|
|
556
|
-
/**
|
|
557
|
-
* Checks whether two FEP-ef61 portable ActivityPub URIs identify the same
|
|
558
|
-
* portable object.
|
|
559
|
-
*
|
|
560
|
-
* Non-string inputs return `false`. Non-portable URI strings use strict string
|
|
561
|
-
* equality. Portable URI strings are compared through
|
|
562
|
-
* {@link canonicalizePortableUri}; malformed portable URI strings return
|
|
563
|
-
* `false` unless they are exactly equal.
|
|
564
|
-
*
|
|
565
|
-
* @since 2.4.0
|
|
566
|
-
*/
|
|
567
|
-
declare function arePortableUrisEqual(left: string, right: string): boolean;
|
|
568
|
-
/**
|
|
569
|
-
* Computes an IRI's FEP-fe34 origin.
|
|
570
|
-
*
|
|
571
|
-
* HTTP(S) IRIs use their web origin. FEP-ef61 portable ActivityPub IRIs and
|
|
572
|
-
* DID URLs use their DID as a cryptographic origin.
|
|
573
|
-
*
|
|
574
|
-
* @throws {TypeError} If the IRI does not have a supported FEP-fe34 origin.
|
|
575
|
-
* @since 2.4.0
|
|
576
|
-
*/
|
|
577
|
-
declare function getFe34Origin(input: string | URL): string;
|
|
578
|
-
/**
|
|
579
|
-
* Checks whether two IRIs have the same FEP-fe34 origin.
|
|
580
|
-
*
|
|
581
|
-
* Malformed or unsupported IRIs are treated as non-matching.
|
|
582
|
-
*
|
|
583
|
-
* @since 2.4.0
|
|
584
|
-
*/
|
|
585
|
-
declare function haveSameFe34Origin(left: string | URL, right: string | URL): boolean;
|
|
586
|
-
/**
|
|
587
|
-
* Checks whether two IRIs have the same origin. Unlike comparing
|
|
588
|
-
* `URL.origin`, which is `"null"` for URLs with non-special schemes, this
|
|
589
|
-
* compares FEP-ef61 portable ActivityPub IRIs by their schemes and DIDs, so
|
|
590
|
-
* that `ap:` and `ap+ef61:` IRIs of the same DID with decoded or
|
|
591
|
-
* percent-encoded authorities have the same origin. Other IRIs with
|
|
592
|
-
* a non-special scheme and a host are compared by their schemes and hosts.
|
|
593
|
-
*
|
|
594
|
-
* This is not an FEP-fe34 origin check: an `ap+ef61:` IRI and the `did:key`
|
|
595
|
-
* verification method of the same DID have different origins here. Use
|
|
596
|
-
* {@link haveSameFe34Origin} for that.
|
|
597
|
-
* @param left The first IRI.
|
|
598
|
-
* @param right The second IRI.
|
|
599
|
-
* @returns `true` if the IRIs have the same origin.
|
|
600
|
-
* @since 2.4.0
|
|
601
|
-
*/
|
|
602
|
-
declare function haveSameIriOrigin(left: URL, right: URL): boolean;
|
|
603
|
-
/**
|
|
604
|
-
* Checks whether the URL is an FEP-ef61 gateway base URI, i.e., an HTTP(S)
|
|
605
|
-
* URI with no credentials, path, query, or fragment, such as
|
|
606
|
-
* `https://example.com/`. FEP-ef61 requires every item of a portable actor's
|
|
607
|
-
* `gateways` to be such a URI. A URI with an empty query or fragment
|
|
608
|
-
* delimiter, such as `https://example.com/?`, is not a gateway base URI.
|
|
609
|
-
*
|
|
610
|
-
* Note that the `URL` class normalizes `https://example.com` to
|
|
611
|
-
* `https://example.com/`, so both are gateway base URIs.
|
|
612
|
-
* @param url The URL to check.
|
|
613
|
-
* @returns `true` if the URL is an FEP-ef61 gateway base URI.
|
|
614
|
-
* @since 2.4.0
|
|
615
|
-
*/
|
|
616
|
-
declare function isGatewayUrl(url: URL): boolean;
|
|
617
|
-
/**
|
|
618
|
-
* Parses and validates an FEP-ef61 gateway base URI, i.e., an HTTP(S) URI with
|
|
619
|
-
* no credentials, path, query, or fragment, such as `https://example.com`.
|
|
620
|
-
* See {@link isGatewayUrl} for the rules.
|
|
621
|
-
* @param url The gateway base URI to parse.
|
|
622
|
-
* @returns The parsed gateway base URI, whose path is `/`.
|
|
623
|
-
* @throws {TypeError} If the URI is malformed, or is not an HTTP(S) base URI
|
|
624
|
-
* with no credentials, path, query, or fragment. In the
|
|
625
|
-
* latter case, the message starts with
|
|
626
|
-
* `Invalid FEP-ef61 gateway:`.
|
|
627
|
-
* @since 2.4.0
|
|
628
|
-
*/
|
|
629
|
-
declare function parseGatewayUrl(url: string): URL;
|
|
630
|
-
/**
|
|
631
|
-
* Converts an [FEP-ef61] compatible identifier into a portable ActivityPub
|
|
632
|
-
* URI.
|
|
633
|
-
*
|
|
634
|
-
* A compatible identifier is an HTTP(S) URL under a gateway's fixed
|
|
635
|
-
* `/.well-known/apgateway/` path, such as
|
|
636
|
-
* `https://server.example/.well-known/apgateway/did:key:z6Mk.../objects/1`.
|
|
637
|
-
* This function removes the gateway part and returns the corresponding
|
|
638
|
-
* portable URI, e.g., `ap+ef61://did:key:z6Mk.../objects/1`, in the same
|
|
639
|
-
* internal `URL` form that {@link parseIri} produces. The path, query, and
|
|
640
|
-
* fragment are preserved, so the result is a portable URI, not a comparison
|
|
641
|
-
* form; pass its `href` to {@link canonicalizePortableUri} or
|
|
642
|
-
* {@link arePortableUrisEqual} to compare it with other portable URIs.
|
|
643
|
-
*
|
|
644
|
-
* The conversion only reveals the *claimed* portable identifier. Anyone can
|
|
645
|
-
* publish a compatible identifier for any DID on their own server, so the
|
|
646
|
-
* gateway that served it is neither the object's origin nor authorized to act
|
|
647
|
-
* for the DID. Callers must still verify the retrieved document's Object
|
|
648
|
-
* Integrity Proof against the DID, as FEP-ef61 requires, and should keep the
|
|
649
|
-
* original URL if they need the gateway as a retrieval hint.
|
|
650
|
-
*
|
|
651
|
-
* Arbitrary gateway paths are not supported.
|
|
652
|
-
*
|
|
653
|
-
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
654
|
-
*
|
|
655
|
-
* @param input The URL to convert.
|
|
656
|
-
* @returns The portable ActivityPub URI, or `null` if the input is not an
|
|
657
|
-
* HTTP(S) URL whose path starts with `/.well-known/apgateway/did:`.
|
|
658
|
-
* Other gateway routes, such as the gateway discovery endpoint and
|
|
659
|
-
* hashlink media URLs, also yield `null`.
|
|
660
|
-
* @throws {TypeError} If the input looks like a compatible identifier but is
|
|
661
|
-
* malformed, e.g., it has an invalid DID, no object path,
|
|
662
|
-
* invalid percent-encoding, credentials, or location
|
|
663
|
-
* hints (`@gateway` query parameters, or the legacy
|
|
664
|
-
* `gateways` parameter), or its raw string path would
|
|
665
|
-
* change during URL parsing. Already-parsed `URL`
|
|
666
|
-
* arguments cannot reveal segments lost by their parser.
|
|
667
|
-
* @since 2.4.0
|
|
668
|
-
*/
|
|
669
|
-
declare function fromCompatibleEf61Id(input: string | URL): URL | null;
|
|
670
|
-
/**
|
|
671
|
-
* Converts a portable ActivityPub URI into an [FEP-ef61] compatible
|
|
672
|
-
* identifier, which is an HTTP(S) URL under the gateway's fixed
|
|
673
|
-
* `/.well-known/apgateway/` path.
|
|
674
|
-
*
|
|
675
|
-
* For example, `ap+ef61://did:key:z6Mk.../objects/1` and
|
|
676
|
-
* `https://server.example` yield
|
|
677
|
-
* `https://server.example/.well-known/apgateway/did:key:z6Mk.../objects/1`.
|
|
678
|
-
* Both `ap:` and `ap+ef61:` URIs with decoded or percent-encoded DID
|
|
679
|
-
* authorities are accepted. Publishers should use the first gateway in the
|
|
680
|
-
* actor's `gateways` list, as FEP-ef61 requires.
|
|
681
|
-
*
|
|
682
|
-
* The path and fragment are preserved, with characters that are not allowed
|
|
683
|
-
* in HTTP(S) URLs percent-encoded the same way as
|
|
684
|
-
* {@link canonicalizePortableUri} does. FEP-ef61 location hints (`@gateway`
|
|
685
|
-
* query parameters, and the legacy `gateways` parameter) are removed, since
|
|
686
|
-
* compatible identifiers must not have them; other query parameters are kept
|
|
687
|
-
* in order.
|
|
688
|
-
*
|
|
689
|
-
* Arbitrary gateway paths are not supported.
|
|
690
|
-
*
|
|
691
|
-
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
692
|
-
*
|
|
693
|
-
* @param portableId The `ap:` or `ap+ef61:` URI to convert.
|
|
694
|
-
* @param gateway The gateway's HTTP(S) origin, e.g., `https://server.example`.
|
|
695
|
-
* @returns The compatible identifier.
|
|
696
|
-
* @throws {TypeError} If the portable ID is not a valid `ap:` or `ap+ef61:`
|
|
697
|
-
* URI, if its path has `.` or `..` segments (which
|
|
698
|
-
* HTTP(S) URLs cannot represent without changing the
|
|
699
|
-
* identified object), or if the gateway is
|
|
700
|
-
* not an HTTP(S) origin with no credentials, path, query,
|
|
701
|
-
* or fragment.
|
|
702
|
-
* @since 2.4.0
|
|
703
|
-
*/
|
|
704
|
-
declare function toCompatibleEf61Id(portableId: string | URL, gateway: string | URL): URL;
|
|
705
|
-
/**
|
|
706
|
-
* Returns a copy of an [FEP-ef61] portable ActivityPub URI with `@gateway`
|
|
707
|
-
* location hints for the given gateways, which tell consumers where they can
|
|
708
|
-
* retrieve the object. Put hints on *references* to portable actors, e.g.,
|
|
709
|
-
* in `actor`, `attributedTo`, `to`, or `cc`, when constructing an object, as
|
|
710
|
-
* FEP-ef61 recommends:
|
|
711
|
-
*
|
|
712
|
-
* ~~~~ typescript
|
|
713
|
-
* withGatewayHints("ap://did:key:z6Mk.../actor", [
|
|
714
|
-
* "https://server1.example",
|
|
715
|
-
* "https://server2.example",
|
|
716
|
-
* ]);
|
|
717
|
-
* // ap+ef61://did:key:z6Mk.../actor?@gateway=https%3A%2F%2Fserver1.example&@gateway=https%3A%2F%2Fserver2.example
|
|
718
|
-
* ~~~~
|
|
719
|
-
*
|
|
720
|
-
* Do not put hints on an object's own `id`. Hints do not change the
|
|
721
|
-
* identity of a portable URI, since FEP-ef61 drops the query when comparing
|
|
722
|
-
* portable URIs, but implementations that do not canonicalize portable URIs
|
|
723
|
-
* would take a hinted ID for another object. Add hints before signing the
|
|
724
|
-
* object, since its Object Integrity Proof covers its references too.
|
|
725
|
-
*
|
|
726
|
-
* The hints that the URI already has, including the legacy `gateways`
|
|
727
|
-
* parameter, are replaced. Each gateway becomes a `@gateway` query
|
|
728
|
-
* parameter whose value is its URI-encoded origin, e.g.,
|
|
729
|
-
* `@gateway=https%3A%2F%2Fserver1.example`, in the given order after the
|
|
730
|
-
* other query parameters. Duplicate gateways are dropped, and an empty list
|
|
731
|
-
* removes the hints as {@link withoutGatewayHints} does. The other query
|
|
732
|
-
* parameters, their order, and the fragment are kept, but percent-encoding
|
|
733
|
-
* is normalized the same way as {@link canonicalizePortableUri} does it.
|
|
734
|
-
*
|
|
735
|
-
* Fedify follows at most five hints when dereferencing a portable URI
|
|
736
|
-
* (three for the key ID of an HTTP Signature), so list the preferred
|
|
737
|
-
* gateways first; there is no limit on the number of hints added here.
|
|
738
|
-
*
|
|
739
|
-
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
740
|
-
*
|
|
741
|
-
* @param portableId The `ap:` or `ap+ef61:` URI. Pass the raw string rather
|
|
742
|
-
* than a `URL` if its path may have `.` or `..` segments,
|
|
743
|
-
* because the `URL` class resolves them.
|
|
744
|
-
* @param gateways The gateways, e.g., the `gateways` of the actor that the
|
|
745
|
-
* URI refers to. Each has to be an HTTP(S) origin with no
|
|
746
|
-
* credentials, path, query, or fragment.
|
|
747
|
-
* @returns The portable URI with the hints, in the same internal `URL` form
|
|
748
|
-
* as {@link parseIri} returns. Use {@link formatIri} to get its
|
|
749
|
-
* canonical string.
|
|
750
|
-
* @throws {TypeError} If the portable ID is not a valid `ap:` or `ap+ef61:`
|
|
751
|
-
* URI, e.g., it is a compatible identifier, which must
|
|
752
|
-
* not have location hints; if its path has `.` or `..`
|
|
753
|
-
* segments, which the `URL` class cannot represent; or
|
|
754
|
-
* if a gateway is invalid.
|
|
755
|
-
* @since 2.4.0
|
|
756
|
-
*/
|
|
757
|
-
declare function withGatewayHints(portableId: string | URL, gateways: Iterable<string | URL>): URL;
|
|
758
|
-
/**
|
|
759
|
-
* Returns a copy of an [FEP-ef61] portable ActivityPub URI without its
|
|
760
|
-
* location hints, i.e., `@gateway` query parameters and the legacy
|
|
761
|
-
* `gateways` parameter. The other query parameters, their order, and the
|
|
762
|
-
* fragment are kept, but percent-encoding is normalized the same way as
|
|
763
|
-
* {@link canonicalizePortableUri} does it.
|
|
764
|
-
*
|
|
765
|
-
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
766
|
-
*
|
|
767
|
-
* @param portableId The `ap:` or `ap+ef61:` URI. Pass the raw string rather
|
|
768
|
-
* than a `URL` if its path may have `.` or `..` segments,
|
|
769
|
-
* because the `URL` class resolves them.
|
|
770
|
-
* @returns The portable URI without the hints, in the same internal `URL`
|
|
771
|
-
* form as {@link parseIri} returns.
|
|
772
|
-
* @throws {TypeError} If the portable ID is not a valid `ap:` or `ap+ef61:`
|
|
773
|
-
* URI, or if its path has `.` or `..` segments, which
|
|
774
|
-
* the `URL` class cannot represent.
|
|
775
|
-
* @since 2.4.0
|
|
776
|
-
*/
|
|
777
|
-
declare function withoutGatewayHints(portableId: string | URL): URL;
|
|
778
|
-
/**
|
|
779
|
-
* Gets the gateways in the `@gateway` location hints of an [FEP-ef61]
|
|
780
|
-
* portable ActivityPub URI, in order. Hints that are not valid gateways,
|
|
781
|
-
* i.e., HTTP(S) origins with no credentials, path, query, or fragment, are
|
|
782
|
-
* skipped, and so are duplicates. The legacy `gateways` parameter is not
|
|
783
|
-
* read.
|
|
784
|
-
*
|
|
785
|
-
* Unlike Fedify's dereferencing, which follows at most five hints, this
|
|
786
|
-
* returns all of them.
|
|
787
|
-
*
|
|
788
|
-
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
789
|
-
*
|
|
790
|
-
* @param portableId The `ap:` or `ap+ef61:` URI.
|
|
791
|
-
* @returns The gateways, e.g., `https://server1.example/`.
|
|
792
|
-
* @throws {TypeError} If the portable ID is not a valid `ap:` or `ap+ef61:`
|
|
793
|
-
* URI.
|
|
794
|
-
* @since 2.4.0
|
|
795
|
-
*/
|
|
796
|
-
declare function getGatewayHints(portableId: string | URL): URL[];
|
|
797
|
-
/**
|
|
798
|
-
* Validates a URL to prevent SSRF attacks.
|
|
799
|
-
*/
|
|
800
|
-
declare function validatePublicUrl(url: string): Promise<void>;
|
|
801
|
-
declare function isValidPublicIPv4Address(address: string): boolean;
|
|
802
|
-
declare function isValidPublicIPv6Address(address: string): boolean;
|
|
803
|
-
declare function expandIPv6Address(address: string): string;
|
|
804
|
-
//#endregion
|
|
805
473
|
export { type AuthenticatedDocumentLoaderFactory, type CreateRequestOptions, type Decimal, type DidKeyVerificationMethod, type DocumentLoader, type DocumentLoaderFactory, type DocumentLoaderFactoryOptions, type DocumentLoaderOptions, FetchError, type FetchPortableMediaOptions, type GetDocumentLoaderOptions, type GetUserAgentOptions, type Json, LanguageString, type ParsedDigestMultibase, type ParsedHashlink, type PortableMedia, type PortableObjectReferrer, type PortableObjectVerification, type PortableObjectVerifier, type PortableObjectVerifierOptions, type PropertyPreprocessor, type PropertyPreprocessorContext, type RemoteDocument, UrlError, arePortableUrisEqual, canParseDecimal, canonicalizePortableUri, computeDigestMultibase, createActivityPubRequest, createHashlink, decodeMultibase, encodeMultibase, encodingFromBaseData, expandIPv6Address, exportDidKey, exportMultibaseKey, exportSpki, fetchPortableMedia, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, getGatewayHints, getRemoteDocument, getUserAgent, haveSameFe34Origin, haveSameIriOrigin, importDidKey, importMultibaseKey, importPem, importPkcs1, importSpki, isDecimal, isGatewayUrl, isTransientFetchError, isValidPublicIPv4Address, isValidPublicIPv6Address, logRequest, normalizeLanguageTag, parseDecimal, parseDidKeyVerificationMethod, parseDigestMultibase, parseGatewayUrl, parseHashlink, parseIri, parseJsonLdId, preloadedContexts, resolveDocumentLoaderTimeout, toCompatibleEf61Id, validatePublicUrl, verifyDigestMultibase, verifyHashlink, withDocumentLoaderTimeout, withGatewayHints, withoutGatewayHints };
|
package/dist/mod.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import { t as preloadedContexts } from "./contexts-DWrj4AGR.js";
|
|
3
|
-
import {
|
|
3
|
+
import { C as toCompatibleEf61Id, E as withoutGatewayHints, T as withGatewayHints, a as canonicalizePortableUri, b as parseIri, c as fromCompatibleEf61Id, d as haveSameFe34Origin, f as haveSameIriOrigin, h as isValidPublicIPv6Address, l as getFe34Origin, m as isValidPublicIPv4Address, n as UrlError, o as expandIPv6Address, p as isGatewayUrl, r as arePortableUrisEqual, s as formatIri, u as getGatewayHints, w as validatePublicUrl, x as parseJsonLdId, y as parseGatewayUrl } from "./url-mWveR5GA.js";
|
|
4
|
+
import { n as openPublicFetch, t as openDirectFetch } from "./public-fetch-ziZ39L5I.js";
|
|
4
5
|
import { getLogger } from "@logtape/logtape";
|
|
5
6
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
6
7
|
import process from "node:process";
|
|
@@ -12,7 +13,7 @@ import { PublicKeyInfo } from "pkijs";
|
|
|
12
13
|
import baseX from "@multiformats/base-x";
|
|
13
14
|
//#region deno.json
|
|
14
15
|
var name = "@fedify/vocab-runtime";
|
|
15
|
-
var version = "2.5.0-dev.
|
|
16
|
+
var version = "2.5.0-dev.2492+4648c04e";
|
|
16
17
|
//#endregion
|
|
17
18
|
//#region src/request.ts
|
|
18
19
|
/**
|
|
@@ -521,7 +522,7 @@ async function bufferErrorResponse(response, url, signal) {
|
|
|
521
522
|
try {
|
|
522
523
|
await readBoundedBytes(response, MAX_ERROR_BODY_SIZE, url);
|
|
523
524
|
} catch (error) {
|
|
524
|
-
|
|
525
|
+
clone.body?.cancel().catch(() => {});
|
|
525
526
|
if (signal?.aborted) throw error;
|
|
526
527
|
logger.debug("Failed to read the error response body from {url}: {error}", {
|
|
527
528
|
url,
|
|
@@ -553,14 +554,48 @@ async function bufferErrorResponse(response, url, signal) {
|
|
|
553
554
|
* Gets a {@link RemoteDocument} from the given response.
|
|
554
555
|
* @param url The URL of the document to load.
|
|
555
556
|
* @param response The response to get the document from.
|
|
556
|
-
* @param fetch The function to fetch the document.
|
|
557
|
+
* @param fetch The function to fetch the document. It is called with the URL
|
|
558
|
+
* of an alternate document, if any, after the response body has
|
|
559
|
+
* been either read or its cancellation has been started.
|
|
557
560
|
* @param options The options for loading the document.
|
|
558
561
|
* @returns The loaded remote document.
|
|
559
562
|
* @throws {FetchError} If the response is not OK.
|
|
560
563
|
* @internal
|
|
561
564
|
*/
|
|
562
565
|
async function getRemoteDocument(url, response, fetch, options) {
|
|
563
|
-
const
|
|
566
|
+
const result = await parseRemoteDocument(url, response, options);
|
|
567
|
+
if ("alternate" in result) return await fetch(result.alternate, options);
|
|
568
|
+
return result.document;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Starts cancelling the body of a response without waiting for it to settle.
|
|
572
|
+
* The cancellation of a branch of a tee (e.g., a body cloned by a fetch mock)
|
|
573
|
+
* settles only after the other branch is cancelled too, per the Streams
|
|
574
|
+
* standard, so awaiting it could block forever. Failures are only logged.
|
|
575
|
+
* @param response The response whose body is cancelled.
|
|
576
|
+
* @param url The URL of the response, for logging.
|
|
577
|
+
*/
|
|
578
|
+
function cancelResponseBody(response, url) {
|
|
579
|
+
response.body?.cancel().catch((error) => {
|
|
580
|
+
logger.debug("Failed to cancel the response body from {url}: {error}", {
|
|
581
|
+
url,
|
|
582
|
+
error
|
|
583
|
+
});
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Gets a {@link RemoteDocument} from the given response, or the URL of an
|
|
588
|
+
* alternate document to load instead. When an alternate document is found,
|
|
589
|
+
* the response body has been either read or its cancellation has been started
|
|
590
|
+
* (without waiting for it), so that the alternate document can be loaded after
|
|
591
|
+
* the response's session is closed.
|
|
592
|
+
* @param url The URL of the document to load.
|
|
593
|
+
* @param response The response to get the document from.
|
|
594
|
+
* @returns The loaded remote document, or the alternate document URL.
|
|
595
|
+
* @throws {FetchError} If the response is not OK.
|
|
596
|
+
*/
|
|
597
|
+
async function parseRemoteDocument(url, response, options) {
|
|
598
|
+
const documentUrl = url;
|
|
564
599
|
const docUrl = new URL(documentUrl);
|
|
565
600
|
if (!response.ok) {
|
|
566
601
|
if (options?.suppressError) logger.warn("Failed to fetch document: {status} {url} {headers}", {
|
|
@@ -602,7 +637,8 @@ async function getRemoteDocument(url, response, fetch, options) {
|
|
|
602
637
|
alternateUrl: altUri.href,
|
|
603
638
|
url: documentUrl
|
|
604
639
|
});
|
|
605
|
-
|
|
640
|
+
cancelResponseBody(response, documentUrl);
|
|
641
|
+
return { alternate: altUri.href };
|
|
606
642
|
}
|
|
607
643
|
}
|
|
608
644
|
}
|
|
@@ -638,7 +674,7 @@ async function getRemoteDocument(url, response, fetch, options) {
|
|
|
638
674
|
alternateUrl: attribs.href,
|
|
639
675
|
url: documentUrl
|
|
640
676
|
});
|
|
641
|
-
return
|
|
677
|
+
return { alternate: new URL(attribs.href, docUrl).href };
|
|
642
678
|
}
|
|
643
679
|
}
|
|
644
680
|
try {
|
|
@@ -653,11 +689,11 @@ async function getRemoteDocument(url, response, fetch, options) {
|
|
|
653
689
|
url: documentUrl,
|
|
654
690
|
headers: Object.fromEntries(response.headers.entries())
|
|
655
691
|
});
|
|
656
|
-
return {
|
|
692
|
+
return { document: {
|
|
657
693
|
contextUrl,
|
|
658
694
|
document,
|
|
659
695
|
documentUrl
|
|
660
|
-
};
|
|
696
|
+
} };
|
|
661
697
|
}
|
|
662
698
|
/**
|
|
663
699
|
* Resolves {@link DocumentLoaderFactoryOptions.timeout} into milliseconds.
|
|
@@ -762,10 +798,59 @@ function withDocumentLoaderTimeout(loader, timeout) {
|
|
|
762
798
|
* @returns The document loader.
|
|
763
799
|
* @since 1.3.0
|
|
764
800
|
*/
|
|
765
|
-
function getDocumentLoader(
|
|
801
|
+
function getDocumentLoader(options = {}) {
|
|
802
|
+
return createDocumentLoader(options);
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* The implementation of {@link getDocumentLoader}, with injectable
|
|
806
|
+
* dependencies. This is not exported from any entry point.
|
|
807
|
+
* @param options Options for the document loader.
|
|
808
|
+
* @param deps The dependencies.
|
|
809
|
+
* @returns The document loader.
|
|
810
|
+
*/
|
|
811
|
+
function createDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedContexts, timeout, userAgent } = {}, deps = {}) {
|
|
766
812
|
const resolvedTimeout = resolveDocumentLoaderTimeout(timeout);
|
|
767
813
|
const tracer = trace.getTracerProvider().getTracer(name, version);
|
|
768
814
|
const maximumRedirection = maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
815
|
+
async function openHop(url, options) {
|
|
816
|
+
try {
|
|
817
|
+
const session = deps.openHop != null ? await deps.openHop(url) : allowPrivateAddress ? await openDirectFetch(url) : await openPublicFetch(url, { signal: options?.signal });
|
|
818
|
+
if (options?.signal?.aborted) {
|
|
819
|
+
await session.close();
|
|
820
|
+
options.signal.throwIfAborted();
|
|
821
|
+
}
|
|
822
|
+
return session;
|
|
823
|
+
} catch (error) {
|
|
824
|
+
if (error instanceof UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
825
|
+
url,
|
|
826
|
+
error
|
|
827
|
+
});
|
|
828
|
+
else logger[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
829
|
+
url,
|
|
830
|
+
error
|
|
831
|
+
});
|
|
832
|
+
throw error;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
async function fetchHop(session, url, span, options) {
|
|
836
|
+
try {
|
|
837
|
+
const request = createActivityPubRequest(url, { userAgent });
|
|
838
|
+
logRequest(logger, request);
|
|
839
|
+
const response = await session.fetch(request, {
|
|
840
|
+
redirect: "manual",
|
|
841
|
+
signal: options?.signal
|
|
842
|
+
});
|
|
843
|
+
span.setAttribute("http.response.status_code", response.status);
|
|
844
|
+
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
845
|
+
const location = response.headers.get("Location");
|
|
846
|
+
cancelResponseBody(response, url);
|
|
847
|
+
return { location };
|
|
848
|
+
}
|
|
849
|
+
return await parseRemoteDocument(url, response, options);
|
|
850
|
+
} finally {
|
|
851
|
+
await session.close();
|
|
852
|
+
}
|
|
853
|
+
}
|
|
769
854
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
770
855
|
options?.signal?.throwIfAborted();
|
|
771
856
|
const parsedUrl = new URL(url);
|
|
@@ -780,36 +865,15 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
780
865
|
documentUrl: currentUrl
|
|
781
866
|
};
|
|
782
867
|
}
|
|
783
|
-
|
|
784
|
-
try {
|
|
785
|
-
await validatePublicUrl(currentUrl);
|
|
786
|
-
} catch (error) {
|
|
787
|
-
if (error instanceof UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
788
|
-
url: currentUrl,
|
|
789
|
-
error
|
|
790
|
-
});
|
|
791
|
-
else logger[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
792
|
-
url: currentUrl,
|
|
793
|
-
error
|
|
794
|
-
});
|
|
795
|
-
throw error;
|
|
796
|
-
}
|
|
797
|
-
options?.signal?.throwIfAborted();
|
|
798
|
-
}
|
|
868
|
+
const session = await openHop(currentUrl, options);
|
|
799
869
|
visited.add(currentUrl);
|
|
800
870
|
return await tracer.startActiveSpan("activitypub.fetch_document", {
|
|
801
871
|
kind: SpanKind.CLIENT,
|
|
802
872
|
attributes: { "url.full": currentUrl }
|
|
803
873
|
}, async (span) => {
|
|
804
874
|
try {
|
|
805
|
-
const
|
|
806
|
-
|
|
807
|
-
const response = await fetch(request, {
|
|
808
|
-
redirect: "manual",
|
|
809
|
-
signal: options?.signal
|
|
810
|
-
});
|
|
811
|
-
span.setAttribute("http.response.status_code", response.status);
|
|
812
|
-
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
875
|
+
const outcome = await fetchHop(session, currentUrl, span, options);
|
|
876
|
+
if ("location" in outcome) {
|
|
813
877
|
if (redirected >= maximumRedirection) {
|
|
814
878
|
logger[options?.suppressError ? "warn" : "error"]("Too many redirections ({redirections}) while fetching document.", {
|
|
815
879
|
redirections: redirected + 1,
|
|
@@ -817,7 +881,7 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
817
881
|
});
|
|
818
882
|
throw new FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
819
883
|
}
|
|
820
|
-
const redirectUrl = new URL(
|
|
884
|
+
const redirectUrl = new URL(outcome.location, currentUrl).href;
|
|
821
885
|
span.setAttribute("http.redirect.url", redirectUrl);
|
|
822
886
|
if (visited.has(redirectUrl)) {
|
|
823
887
|
logger[options?.suppressError ? "warn" : "error"]("Detected a redirect loop while fetching document: {url} -> {redirectUrl}", {
|
|
@@ -828,12 +892,14 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
828
892
|
}
|
|
829
893
|
return await load(redirectUrl, options, redirected + 1, visited);
|
|
830
894
|
}
|
|
831
|
-
|
|
895
|
+
let result;
|
|
896
|
+
if ("alternate" in outcome) {
|
|
897
|
+
const alternateUrl = outcome.alternate;
|
|
832
898
|
options?.signal?.throwIfAborted();
|
|
833
899
|
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
834
900
|
if (visited.has(alternateUrl)) throw new FetchError(currentUrl, `Redirect loop detected: ${alternateUrl}`);
|
|
835
|
-
|
|
836
|
-
}
|
|
901
|
+
result = await load(alternateUrl, options, redirected + 1, visited);
|
|
902
|
+
} else result = outcome.document;
|
|
837
903
|
span.setAttribute("docloader.document_url", result.documentUrl);
|
|
838
904
|
if (result.contextUrl != null) span.setAttribute("docloader.context_url", result.contextUrl);
|
|
839
905
|
return result;
|