@fedify/vocab-runtime 2.2.19 → 2.2.20
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/internal.cjs +6 -0
- package/dist/internal.d.cts +3 -0
- package/dist/internal.d.ts +3 -0
- package/dist/internal.js +3 -0
- package/dist/mod.cjs +105 -253
- package/dist/mod.d.cts +5 -28
- package/dist/mod.d.ts +6 -28
- package/dist/mod.js +98 -245
- package/dist/public-fetch-BC-nWJNM.d.ts +143 -0
- package/dist/public-fetch-CFnW7XMn.cjs +821 -0
- package/dist/public-fetch-DBpt3xxf.d.cts +143 -0
- package/dist/public-fetch-Dfmc_Kfy.js +772 -0
- package/dist/tests/{body-BOnyCa1y.mjs → body-B9_hb-GO.mjs} +1 -1
- package/dist/tests/{body-DhbRZ6Ps.cjs → body-pOSG2RFb.cjs} +1 -1
- package/dist/tests/body.test.cjs +1 -1
- package/dist/tests/body.test.mjs +1 -1
- package/dist/tests/decimal.test.cjs +6 -6
- package/dist/tests/decimal.test.mjs +6 -6
- package/dist/tests/{docloader-BjyFsnAA.mjs → docloader-Bdlp7FkK.mjs} +102 -37
- package/dist/tests/{docloader-BhSiTajy.cjs → docloader-Ck3VfY29.cjs} +106 -35
- package/dist/tests/docloader.test.cjs +523 -1273
- package/dist/tests/docloader.test.mjs +469 -1238
- package/dist/tests/esm-CnLt0wAF.mjs +1225 -0
- package/dist/tests/esm-CxbqfkLP.cjs +1208 -0
- package/dist/tests/internal/multicodec.test.cjs +1 -1
- package/dist/tests/internal/multicodec.test.mjs +1 -1
- package/dist/tests/{key-BDIsC6hV.mjs → key-GEdpxA4M.mjs} +2 -2
- package/dist/tests/{key-BarKGLQz.cjs → key-L6ReMuUb.cjs} +2 -2
- package/dist/tests/key.test.cjs +2 -2
- package/dist/tests/key.test.mjs +2 -2
- package/dist/tests/{langstr-BsqFJupv.cjs → langstr-CZpWmpo5.cjs} +1 -1
- package/dist/tests/{langstr-ABdAOKlF.mjs → langstr-DTB4sl0a.mjs} +1 -1
- package/dist/tests/langstr.test.cjs +1 -1
- package/dist/tests/langstr.test.mjs +1 -1
- package/dist/tests/langtag.test.cjs +1 -1
- package/dist/tests/langtag.test.mjs +1 -1
- package/dist/tests/link.test.mjs +1 -1
- package/dist/tests/multibase/multibase.test.cjs +1 -1
- package/dist/tests/multibase/multibase.test.mjs +1 -1
- package/dist/tests/node-C3bjFjL1.mjs +84 -0
- package/dist/tests/node-DWD76vPo.cjs +90 -0
- package/dist/tests/pin-grant-CU-o367k.cjs +70 -0
- package/dist/tests/pin-grant-HW3B6SKv.mjs +53 -0
- package/dist/tests/pin-grant.test.cjs +88 -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 +167 -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 +197 -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-BjE-YJLL.cjs +221 -0
- package/dist/tests/pinners-ZgZDx9y6.mjs +203 -0
- package/dist/tests/public-fetch-Ddjfxbwc.cjs +187 -0
- package/dist/tests/public-fetch-Yi7Vks9s.mjs +170 -0
- package/dist/tests/public-fetch.test.cjs +1074 -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-DGtx5MkG.cjs → request-B3NUKbyk.cjs} +1 -1
- package/dist/tests/{request-yCis9VCB.mjs → request-BSg3IQzf.mjs} +1 -1
- package/dist/tests/request.test.cjs +1 -1
- package/dist/tests/request.test.mjs +1 -1
- package/dist/tests/support-D5-KVjWZ.cjs +363 -0
- package/dist/tests/support-M5ClN-no.mjs +272 -0
- package/dist/tests/{url-vZTgkIZg.cjs → url-DLuSj57U.cjs} +88 -12
- package/dist/tests/{url-3fyJuqC0.mjs → url-DQWrMGhu.mjs} +65 -13
- package/dist/tests/url.test.cjs +4 -1
- package/dist/tests/url.test.mjs +4 -1
- package/package.json +14 -3
- package/src/docloader.test.ts +700 -32
- package/src/docloader.ts +174 -67
- 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 +12 -3
- /package/dist/tests/{langtag-LDBqlxHv.mjs → langtag-D8FWxjv8.mjs} +0 -0
- /package/dist/tests/{langtag-DgySESmk.cjs → langtag-a2-s9uyi.cjs} +0 -0
- /package/dist/tests/{link-CYszIegt.mjs → link-CHMtH2-k.mjs} +0 -0
- /package/dist/tests/{multibase-8zhYPa7o.cjs → multibase-BmWaK56H.cjs} +0 -0
- /package/dist/tests/{multibase-Ds75BvXs.mjs → multibase-D642Uv3S.mjs} +0 -0
- /package/dist/tests/{multicodec-ByS9XLsw.cjs → multicodec-B-_CSt1M.cjs} +0 -0
- /package/dist/tests/{multicodec-BBPZjRfg.mjs → multicodec-caWdG98t.mjs} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require("./chunk-Do9eywBl.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
2
|
+
const require_request = require("./request-B3NUKbyk.cjs");
|
|
3
3
|
let _logtape_logtape = require("@logtape/logtape");
|
|
4
4
|
//#region src/body.ts
|
|
5
5
|
/** Decoded JSON body limit: 16 MiB. @internal */
|
package/dist/tests/body.test.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require("./chunk-Do9eywBl.cjs");
|
|
2
|
-
const require_body = require("./body-
|
|
2
|
+
const require_body = require("./body-pOSG2RFb.cjs");
|
|
3
3
|
let node_assert_strict = require("node:assert/strict");
|
|
4
4
|
let node_test = require("node:test");
|
|
5
5
|
let node_zlib = require("node:zlib");
|
package/dist/tests/body.test.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as readBoundedText, t as BodyTooLargeError } from "./body-
|
|
1
|
+
import { r as readBoundedText, t as BodyTooLargeError } from "./body-B9_hb-GO.mjs";
|
|
2
2
|
import { deepStrictEqual, ok, rejects } from "node:assert/strict";
|
|
3
3
|
import { test } from "node:test";
|
|
4
4
|
import { gunzipSync, gzipSync } from "node:zlib";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
require("./chunk-Do9eywBl.cjs");
|
|
2
|
-
require("./docloader-
|
|
3
|
-
require("./url-
|
|
4
|
-
require("./key-
|
|
5
|
-
require("./multibase-
|
|
6
|
-
require("./langtag-
|
|
7
|
-
require("./langstr-
|
|
2
|
+
require("./docloader-Ck3VfY29.cjs");
|
|
3
|
+
require("./url-DLuSj57U.cjs");
|
|
4
|
+
require("./key-L6ReMuUb.cjs");
|
|
5
|
+
require("./multibase-BmWaK56H.cjs");
|
|
6
|
+
require("./langtag-a2-s9uyi.cjs");
|
|
7
|
+
require("./langstr-CZpWmpo5.cjs");
|
|
8
8
|
let node_test = require("node:test");
|
|
9
9
|
let node_assert = require("node:assert");
|
|
10
10
|
//#region src/decimal.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import "./docloader-
|
|
2
|
-
import "./url-
|
|
3
|
-
import "./key-
|
|
4
|
-
import "./multibase-
|
|
5
|
-
import "./langtag-
|
|
6
|
-
import "./langstr-
|
|
1
|
+
import "./docloader-Bdlp7FkK.mjs";
|
|
2
|
+
import "./url-DQWrMGhu.mjs";
|
|
3
|
+
import "./key-GEdpxA4M.mjs";
|
|
4
|
+
import "./multibase-D642Uv3S.mjs";
|
|
5
|
+
import "./langtag-D8FWxjv8.mjs";
|
|
6
|
+
import "./langstr-DTB4sl0a.mjs";
|
|
7
7
|
import { test } from "node:test";
|
|
8
8
|
import { deepStrictEqual, throws } from "node:assert";
|
|
9
9
|
//#region src/decimal.ts
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { a as name, i as logRequest, n as createActivityPubRequest, o as version, t as FetchError } from "./request-
|
|
2
|
-
import { n as MAX_BODY_SIZE, r as readBoundedText } from "./body-
|
|
3
|
-
import { t as HttpHeaderLink } from "./link-
|
|
4
|
-
import {
|
|
1
|
+
import { a as name, i as logRequest, n as createActivityPubRequest, o as version, t as FetchError } from "./request-BSg3IQzf.mjs";
|
|
2
|
+
import { n as MAX_BODY_SIZE, r as readBoundedText } from "./body-B9_hb-GO.mjs";
|
|
3
|
+
import { t as HttpHeaderLink } from "./link-CHMtH2-k.mjs";
|
|
4
|
+
import { t as UrlError } from "./url-DQWrMGhu.mjs";
|
|
5
|
+
import { n as openDirectFetch, r as openPublicFetch } from "./public-fetch-Yi7Vks9s.mjs";
|
|
5
6
|
import { getLogger } from "@logtape/logtape";
|
|
6
7
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
7
8
|
//#region src/contexts/activitystreams.json
|
|
@@ -4591,13 +4592,47 @@ const DEFAULT_MAX_REDIRECTION = 20;
|
|
|
4591
4592
|
* Gets a {@link RemoteDocument} from the given response.
|
|
4592
4593
|
* @param url The URL of the document to load.
|
|
4593
4594
|
* @param response The response to get the document from.
|
|
4594
|
-
* @param fetch The function to fetch the document.
|
|
4595
|
+
* @param fetch The function to fetch the document. It is called with the URL
|
|
4596
|
+
* of an alternate document, if any, after the response body has
|
|
4597
|
+
* been either read or its cancellation has been started.
|
|
4595
4598
|
* @returns The loaded remote document.
|
|
4596
4599
|
* @throws {FetchError} If the response is not OK.
|
|
4597
4600
|
* @internal
|
|
4598
4601
|
*/
|
|
4599
4602
|
async function getRemoteDocument(url, response, fetch) {
|
|
4600
|
-
const
|
|
4603
|
+
const result = await parseRemoteDocument(url, response);
|
|
4604
|
+
if ("alternate" in result) return await fetch(result.alternate);
|
|
4605
|
+
return result.document;
|
|
4606
|
+
}
|
|
4607
|
+
/**
|
|
4608
|
+
* Starts cancelling the body of a response without waiting for it to settle.
|
|
4609
|
+
* The cancellation of a branch of a tee (e.g., a body cloned by a fetch mock)
|
|
4610
|
+
* settles only after the other branch is cancelled too, per the Streams
|
|
4611
|
+
* standard, so awaiting it could block forever. Failures are only logged.
|
|
4612
|
+
* @param response The response whose body is cancelled.
|
|
4613
|
+
* @param url The URL of the response, for logging.
|
|
4614
|
+
*/
|
|
4615
|
+
function cancelResponseBody(response, url) {
|
|
4616
|
+
response.body?.cancel().catch((error) => {
|
|
4617
|
+
logger.debug("Failed to cancel the response body from {url}: {error}", {
|
|
4618
|
+
url,
|
|
4619
|
+
error
|
|
4620
|
+
});
|
|
4621
|
+
});
|
|
4622
|
+
}
|
|
4623
|
+
/**
|
|
4624
|
+
* Gets a {@link RemoteDocument} from the given response, or the URL of an
|
|
4625
|
+
* alternate document to load instead. When an alternate document is found,
|
|
4626
|
+
* the response body has been either read or its cancellation has been started
|
|
4627
|
+
* (without waiting for it), so that the alternate document can be loaded after
|
|
4628
|
+
* the response's session is closed.
|
|
4629
|
+
* @param url The URL of the document to load.
|
|
4630
|
+
* @param response The response to get the document from.
|
|
4631
|
+
* @returns The loaded remote document, or the alternate document URL.
|
|
4632
|
+
* @throws {FetchError} If the response is not OK.
|
|
4633
|
+
*/
|
|
4634
|
+
async function parseRemoteDocument(url, response) {
|
|
4635
|
+
const documentUrl = url;
|
|
4601
4636
|
const docUrl = new URL(documentUrl);
|
|
4602
4637
|
if (!response.ok) {
|
|
4603
4638
|
logger.error("Failed to fetch document: {status} {url} {headers}", {
|
|
@@ -4634,7 +4669,8 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4634
4669
|
alternateUrl: altUri.href,
|
|
4635
4670
|
url: documentUrl
|
|
4636
4671
|
});
|
|
4637
|
-
|
|
4672
|
+
cancelResponseBody(response, documentUrl);
|
|
4673
|
+
return { alternate: altUri.href };
|
|
4638
4674
|
}
|
|
4639
4675
|
}
|
|
4640
4676
|
}
|
|
@@ -4659,7 +4695,7 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4659
4695
|
alternateUrl: attribs.href,
|
|
4660
4696
|
url: documentUrl
|
|
4661
4697
|
});
|
|
4662
|
-
return
|
|
4698
|
+
return { alternate: new URL(attribs.href, docUrl).href };
|
|
4663
4699
|
}
|
|
4664
4700
|
}
|
|
4665
4701
|
document = JSON.parse(html);
|
|
@@ -4669,11 +4705,11 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4669
4705
|
url: documentUrl,
|
|
4670
4706
|
headers: Object.fromEntries(response.headers.entries())
|
|
4671
4707
|
});
|
|
4672
|
-
return {
|
|
4708
|
+
return { document: {
|
|
4673
4709
|
contextUrl,
|
|
4674
4710
|
document,
|
|
4675
4711
|
documentUrl
|
|
4676
|
-
};
|
|
4712
|
+
} };
|
|
4677
4713
|
}
|
|
4678
4714
|
/**
|
|
4679
4715
|
* Creates a JSON-LD document loader that utilizes the browser's `fetch` API.
|
|
@@ -4699,9 +4735,54 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4699
4735
|
* @returns The document loader.
|
|
4700
4736
|
* @since 1.3.0
|
|
4701
4737
|
*/
|
|
4702
|
-
function getDocumentLoader(
|
|
4738
|
+
function getDocumentLoader(options = {}) {
|
|
4739
|
+
return createDocumentLoader(options);
|
|
4740
|
+
}
|
|
4741
|
+
/**
|
|
4742
|
+
* The implementation of {@link getDocumentLoader}, with injectable
|
|
4743
|
+
* dependencies. This is not exported from any entry point.
|
|
4744
|
+
* @param options Options for the document loader.
|
|
4745
|
+
* @param deps The dependencies.
|
|
4746
|
+
* @returns The document loader.
|
|
4747
|
+
*/
|
|
4748
|
+
function createDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedContexts, userAgent } = {}, deps = {}) {
|
|
4703
4749
|
const tracer = trace.getTracerProvider().getTracer(name, version);
|
|
4704
4750
|
const maximumRedirection = maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
4751
|
+
async function openHop(url, signal) {
|
|
4752
|
+
try {
|
|
4753
|
+
if (deps.openHop != null) return await deps.openHop(url);
|
|
4754
|
+
return allowPrivateAddress ? await openDirectFetch(url) : await openPublicFetch(url, { signal });
|
|
4755
|
+
} catch (error) {
|
|
4756
|
+
if (error instanceof UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
4757
|
+
url,
|
|
4758
|
+
error
|
|
4759
|
+
});
|
|
4760
|
+
else logger.error("Disallowed private URL: {url}", {
|
|
4761
|
+
url,
|
|
4762
|
+
error
|
|
4763
|
+
});
|
|
4764
|
+
throw error;
|
|
4765
|
+
}
|
|
4766
|
+
}
|
|
4767
|
+
async function fetchHop(session, url, span, options) {
|
|
4768
|
+
try {
|
|
4769
|
+
const request = createActivityPubRequest(url, { userAgent });
|
|
4770
|
+
logRequest(logger, request);
|
|
4771
|
+
const response = await session.fetch(request, {
|
|
4772
|
+
redirect: "manual",
|
|
4773
|
+
signal: options?.signal
|
|
4774
|
+
});
|
|
4775
|
+
span.setAttribute("http.response.status_code", response.status);
|
|
4776
|
+
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
4777
|
+
const location = response.headers.get("Location");
|
|
4778
|
+
cancelResponseBody(response, url);
|
|
4779
|
+
return { location };
|
|
4780
|
+
}
|
|
4781
|
+
return await parseRemoteDocument(url, response);
|
|
4782
|
+
} finally {
|
|
4783
|
+
await session.close();
|
|
4784
|
+
}
|
|
4785
|
+
}
|
|
4705
4786
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
4706
4787
|
options?.signal?.throwIfAborted();
|
|
4707
4788
|
const parsedUrl = new URL(url);
|
|
@@ -4716,33 +4797,15 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4716
4797
|
documentUrl: currentUrl
|
|
4717
4798
|
};
|
|
4718
4799
|
}
|
|
4719
|
-
|
|
4720
|
-
await validatePublicUrl(currentUrl);
|
|
4721
|
-
} catch (error) {
|
|
4722
|
-
if (error instanceof UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
4723
|
-
url: currentUrl,
|
|
4724
|
-
error
|
|
4725
|
-
});
|
|
4726
|
-
else logger.error("Disallowed private URL: {url}", {
|
|
4727
|
-
url: currentUrl,
|
|
4728
|
-
error
|
|
4729
|
-
});
|
|
4730
|
-
throw error;
|
|
4731
|
-
}
|
|
4800
|
+
const session = await openHop(currentUrl, options?.signal);
|
|
4732
4801
|
visited.add(currentUrl);
|
|
4733
4802
|
return await tracer.startActiveSpan("activitypub.fetch_document", {
|
|
4734
4803
|
kind: SpanKind.CLIENT,
|
|
4735
4804
|
attributes: { "url.full": currentUrl }
|
|
4736
4805
|
}, async (span) => {
|
|
4737
4806
|
try {
|
|
4738
|
-
const
|
|
4739
|
-
|
|
4740
|
-
const response = await fetch(request, {
|
|
4741
|
-
redirect: "manual",
|
|
4742
|
-
signal: options?.signal
|
|
4743
|
-
});
|
|
4744
|
-
span.setAttribute("http.response.status_code", response.status);
|
|
4745
|
-
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
4807
|
+
const outcome = await fetchHop(session, currentUrl, span, options);
|
|
4808
|
+
if ("location" in outcome) {
|
|
4746
4809
|
if (redirected >= maximumRedirection) {
|
|
4747
4810
|
logger.error("Too many redirections ({redirections}) while fetching document.", {
|
|
4748
4811
|
redirections: redirected + 1,
|
|
@@ -4750,7 +4813,7 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4750
4813
|
});
|
|
4751
4814
|
throw new FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
4752
4815
|
}
|
|
4753
|
-
const redirectUrl = new URL(
|
|
4816
|
+
const redirectUrl = new URL(outcome.location, currentUrl).href;
|
|
4754
4817
|
span.setAttribute("http.redirect.url", redirectUrl);
|
|
4755
4818
|
if (visited.has(redirectUrl)) {
|
|
4756
4819
|
logger.error("Detected a redirect loop while fetching document: {url} -> {redirectUrl}", {
|
|
@@ -4761,12 +4824,14 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4761
4824
|
}
|
|
4762
4825
|
return await load(redirectUrl, options, redirected + 1, visited);
|
|
4763
4826
|
}
|
|
4764
|
-
|
|
4827
|
+
let result;
|
|
4828
|
+
if ("alternate" in outcome) {
|
|
4829
|
+
const alternateUrl = outcome.alternate;
|
|
4765
4830
|
options?.signal?.throwIfAborted();
|
|
4766
4831
|
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
4767
4832
|
if (visited.has(alternateUrl)) throw new FetchError(currentUrl, `Redirect loop detected: ${alternateUrl}`);
|
|
4768
|
-
|
|
4769
|
-
}
|
|
4833
|
+
result = await load(alternateUrl, options, redirected + 1, visited);
|
|
4834
|
+
} else result = outcome.document;
|
|
4770
4835
|
span.setAttribute("docloader.document_url", result.documentUrl);
|
|
4771
4836
|
if (result.contextUrl != null) span.setAttribute("docloader.context_url", result.contextUrl);
|
|
4772
4837
|
return result;
|
|
@@ -4785,4 +4850,4 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4785
4850
|
return (url, options) => load(url, options);
|
|
4786
4851
|
}
|
|
4787
4852
|
//#endregion
|
|
4788
|
-
export { cid_v1_default as i,
|
|
4853
|
+
export { cid_v1_default as a, preloadedContexts as i, getDocumentLoader as n, getRemoteDocument as r, createDocumentLoader as t };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
require("./chunk-Do9eywBl.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
3
|
-
const require_body = require("./body-
|
|
2
|
+
const require_request = require("./request-B3NUKbyk.cjs");
|
|
3
|
+
const require_body = require("./body-pOSG2RFb.cjs");
|
|
4
4
|
const require_link = require("./link-qDTmjPw_.cjs");
|
|
5
|
-
const require_url = require("./url-
|
|
5
|
+
const require_url = require("./url-DLuSj57U.cjs");
|
|
6
|
+
const require_public_fetch = require("./public-fetch-Ddjfxbwc.cjs");
|
|
6
7
|
let _logtape_logtape = require("@logtape/logtape");
|
|
7
8
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
8
9
|
//#region src/contexts/activitystreams.json
|
|
@@ -4592,13 +4593,47 @@ const DEFAULT_MAX_REDIRECTION = 20;
|
|
|
4592
4593
|
* Gets a {@link RemoteDocument} from the given response.
|
|
4593
4594
|
* @param url The URL of the document to load.
|
|
4594
4595
|
* @param response The response to get the document from.
|
|
4595
|
-
* @param fetch The function to fetch the document.
|
|
4596
|
+
* @param fetch The function to fetch the document. It is called with the URL
|
|
4597
|
+
* of an alternate document, if any, after the response body has
|
|
4598
|
+
* been either read or its cancellation has been started.
|
|
4596
4599
|
* @returns The loaded remote document.
|
|
4597
4600
|
* @throws {FetchError} If the response is not OK.
|
|
4598
4601
|
* @internal
|
|
4599
4602
|
*/
|
|
4600
4603
|
async function getRemoteDocument(url, response, fetch) {
|
|
4601
|
-
const
|
|
4604
|
+
const result = await parseRemoteDocument(url, response);
|
|
4605
|
+
if ("alternate" in result) return await fetch(result.alternate);
|
|
4606
|
+
return result.document;
|
|
4607
|
+
}
|
|
4608
|
+
/**
|
|
4609
|
+
* Starts cancelling the body of a response without waiting for it to settle.
|
|
4610
|
+
* The cancellation of a branch of a tee (e.g., a body cloned by a fetch mock)
|
|
4611
|
+
* settles only after the other branch is cancelled too, per the Streams
|
|
4612
|
+
* standard, so awaiting it could block forever. Failures are only logged.
|
|
4613
|
+
* @param response The response whose body is cancelled.
|
|
4614
|
+
* @param url The URL of the response, for logging.
|
|
4615
|
+
*/
|
|
4616
|
+
function cancelResponseBody(response, url) {
|
|
4617
|
+
response.body?.cancel().catch((error) => {
|
|
4618
|
+
logger.debug("Failed to cancel the response body from {url}: {error}", {
|
|
4619
|
+
url,
|
|
4620
|
+
error
|
|
4621
|
+
});
|
|
4622
|
+
});
|
|
4623
|
+
}
|
|
4624
|
+
/**
|
|
4625
|
+
* Gets a {@link RemoteDocument} from the given response, or the URL of an
|
|
4626
|
+
* alternate document to load instead. When an alternate document is found,
|
|
4627
|
+
* the response body has been either read or its cancellation has been started
|
|
4628
|
+
* (without waiting for it), so that the alternate document can be loaded after
|
|
4629
|
+
* the response's session is closed.
|
|
4630
|
+
* @param url The URL of the document to load.
|
|
4631
|
+
* @param response The response to get the document from.
|
|
4632
|
+
* @returns The loaded remote document, or the alternate document URL.
|
|
4633
|
+
* @throws {FetchError} If the response is not OK.
|
|
4634
|
+
*/
|
|
4635
|
+
async function parseRemoteDocument(url, response) {
|
|
4636
|
+
const documentUrl = url;
|
|
4602
4637
|
const docUrl = new URL(documentUrl);
|
|
4603
4638
|
if (!response.ok) {
|
|
4604
4639
|
logger.error("Failed to fetch document: {status} {url} {headers}", {
|
|
@@ -4635,7 +4670,8 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4635
4670
|
alternateUrl: altUri.href,
|
|
4636
4671
|
url: documentUrl
|
|
4637
4672
|
});
|
|
4638
|
-
|
|
4673
|
+
cancelResponseBody(response, documentUrl);
|
|
4674
|
+
return { alternate: altUri.href };
|
|
4639
4675
|
}
|
|
4640
4676
|
}
|
|
4641
4677
|
}
|
|
@@ -4660,7 +4696,7 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4660
4696
|
alternateUrl: attribs.href,
|
|
4661
4697
|
url: documentUrl
|
|
4662
4698
|
});
|
|
4663
|
-
return
|
|
4699
|
+
return { alternate: new URL(attribs.href, docUrl).href };
|
|
4664
4700
|
}
|
|
4665
4701
|
}
|
|
4666
4702
|
document = JSON.parse(html);
|
|
@@ -4670,11 +4706,11 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4670
4706
|
url: documentUrl,
|
|
4671
4707
|
headers: Object.fromEntries(response.headers.entries())
|
|
4672
4708
|
});
|
|
4673
|
-
return {
|
|
4709
|
+
return { document: {
|
|
4674
4710
|
contextUrl,
|
|
4675
4711
|
document,
|
|
4676
4712
|
documentUrl
|
|
4677
|
-
};
|
|
4713
|
+
} };
|
|
4678
4714
|
}
|
|
4679
4715
|
/**
|
|
4680
4716
|
* Creates a JSON-LD document loader that utilizes the browser's `fetch` API.
|
|
@@ -4700,9 +4736,54 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4700
4736
|
* @returns The document loader.
|
|
4701
4737
|
* @since 1.3.0
|
|
4702
4738
|
*/
|
|
4703
|
-
function getDocumentLoader(
|
|
4739
|
+
function getDocumentLoader(options = {}) {
|
|
4740
|
+
return createDocumentLoader(options);
|
|
4741
|
+
}
|
|
4742
|
+
/**
|
|
4743
|
+
* The implementation of {@link getDocumentLoader}, with injectable
|
|
4744
|
+
* dependencies. This is not exported from any entry point.
|
|
4745
|
+
* @param options Options for the document loader.
|
|
4746
|
+
* @param deps The dependencies.
|
|
4747
|
+
* @returns The document loader.
|
|
4748
|
+
*/
|
|
4749
|
+
function createDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedContexts, userAgent } = {}, deps = {}) {
|
|
4704
4750
|
const tracer = _opentelemetry_api.trace.getTracerProvider().getTracer(require_request.name, require_request.version);
|
|
4705
4751
|
const maximumRedirection = maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
4752
|
+
async function openHop(url, signal) {
|
|
4753
|
+
try {
|
|
4754
|
+
if (deps.openHop != null) return await deps.openHop(url);
|
|
4755
|
+
return allowPrivateAddress ? await require_public_fetch.openDirectFetch(url) : await require_public_fetch.openPublicFetch(url, { signal });
|
|
4756
|
+
} catch (error) {
|
|
4757
|
+
if (error instanceof require_url.UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
4758
|
+
url,
|
|
4759
|
+
error
|
|
4760
|
+
});
|
|
4761
|
+
else logger.error("Disallowed private URL: {url}", {
|
|
4762
|
+
url,
|
|
4763
|
+
error
|
|
4764
|
+
});
|
|
4765
|
+
throw error;
|
|
4766
|
+
}
|
|
4767
|
+
}
|
|
4768
|
+
async function fetchHop(session, url, span, options) {
|
|
4769
|
+
try {
|
|
4770
|
+
const request = require_request.createActivityPubRequest(url, { userAgent });
|
|
4771
|
+
require_request.logRequest(logger, request);
|
|
4772
|
+
const response = await session.fetch(request, {
|
|
4773
|
+
redirect: "manual",
|
|
4774
|
+
signal: options?.signal
|
|
4775
|
+
});
|
|
4776
|
+
span.setAttribute("http.response.status_code", response.status);
|
|
4777
|
+
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
4778
|
+
const location = response.headers.get("Location");
|
|
4779
|
+
cancelResponseBody(response, url);
|
|
4780
|
+
return { location };
|
|
4781
|
+
}
|
|
4782
|
+
return await parseRemoteDocument(url, response);
|
|
4783
|
+
} finally {
|
|
4784
|
+
await session.close();
|
|
4785
|
+
}
|
|
4786
|
+
}
|
|
4706
4787
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
4707
4788
|
options?.signal?.throwIfAborted();
|
|
4708
4789
|
const parsedUrl = new URL(url);
|
|
@@ -4717,33 +4798,15 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4717
4798
|
documentUrl: currentUrl
|
|
4718
4799
|
};
|
|
4719
4800
|
}
|
|
4720
|
-
|
|
4721
|
-
await require_url.validatePublicUrl(currentUrl);
|
|
4722
|
-
} catch (error) {
|
|
4723
|
-
if (error instanceof require_url.UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
4724
|
-
url: currentUrl,
|
|
4725
|
-
error
|
|
4726
|
-
});
|
|
4727
|
-
else logger.error("Disallowed private URL: {url}", {
|
|
4728
|
-
url: currentUrl,
|
|
4729
|
-
error
|
|
4730
|
-
});
|
|
4731
|
-
throw error;
|
|
4732
|
-
}
|
|
4801
|
+
const session = await openHop(currentUrl, options?.signal);
|
|
4733
4802
|
visited.add(currentUrl);
|
|
4734
4803
|
return await tracer.startActiveSpan("activitypub.fetch_document", {
|
|
4735
4804
|
kind: _opentelemetry_api.SpanKind.CLIENT,
|
|
4736
4805
|
attributes: { "url.full": currentUrl }
|
|
4737
4806
|
}, async (span) => {
|
|
4738
4807
|
try {
|
|
4739
|
-
const
|
|
4740
|
-
|
|
4741
|
-
const response = await fetch(request, {
|
|
4742
|
-
redirect: "manual",
|
|
4743
|
-
signal: options?.signal
|
|
4744
|
-
});
|
|
4745
|
-
span.setAttribute("http.response.status_code", response.status);
|
|
4746
|
-
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
4808
|
+
const outcome = await fetchHop(session, currentUrl, span, options);
|
|
4809
|
+
if ("location" in outcome) {
|
|
4747
4810
|
if (redirected >= maximumRedirection) {
|
|
4748
4811
|
logger.error("Too many redirections ({redirections}) while fetching document.", {
|
|
4749
4812
|
redirections: redirected + 1,
|
|
@@ -4751,7 +4814,7 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4751
4814
|
});
|
|
4752
4815
|
throw new require_request.FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
4753
4816
|
}
|
|
4754
|
-
const redirectUrl = new URL(
|
|
4817
|
+
const redirectUrl = new URL(outcome.location, currentUrl).href;
|
|
4755
4818
|
span.setAttribute("http.redirect.url", redirectUrl);
|
|
4756
4819
|
if (visited.has(redirectUrl)) {
|
|
4757
4820
|
logger.error("Detected a redirect loop while fetching document: {url} -> {redirectUrl}", {
|
|
@@ -4762,12 +4825,14 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4762
4825
|
}
|
|
4763
4826
|
return await load(redirectUrl, options, redirected + 1, visited);
|
|
4764
4827
|
}
|
|
4765
|
-
|
|
4828
|
+
let result;
|
|
4829
|
+
if ("alternate" in outcome) {
|
|
4830
|
+
const alternateUrl = outcome.alternate;
|
|
4766
4831
|
options?.signal?.throwIfAborted();
|
|
4767
4832
|
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new require_request.FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
4768
4833
|
if (visited.has(alternateUrl)) throw new require_request.FetchError(currentUrl, `Redirect loop detected: ${alternateUrl}`);
|
|
4769
|
-
|
|
4770
|
-
}
|
|
4834
|
+
result = await load(alternateUrl, options, redirected + 1, visited);
|
|
4835
|
+
} else result = outcome.document;
|
|
4771
4836
|
span.setAttribute("docloader.document_url", result.documentUrl);
|
|
4772
4837
|
if (result.contextUrl != null) span.setAttribute("docloader.context_url", result.contextUrl);
|
|
4773
4838
|
return result;
|
|
@@ -4792,6 +4857,12 @@ Object.defineProperty(exports, "cid_v1_default", {
|
|
|
4792
4857
|
return cid_v1_default;
|
|
4793
4858
|
}
|
|
4794
4859
|
});
|
|
4860
|
+
Object.defineProperty(exports, "createDocumentLoader", {
|
|
4861
|
+
enumerable: true,
|
|
4862
|
+
get: function() {
|
|
4863
|
+
return createDocumentLoader;
|
|
4864
|
+
}
|
|
4865
|
+
});
|
|
4795
4866
|
Object.defineProperty(exports, "getDocumentLoader", {
|
|
4796
4867
|
enumerable: true,
|
|
4797
4868
|
get: function() {
|