@fedify/vocab-runtime 2.3.14 → 2.3.15
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-Bk32IaYB.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-DfWmIUIQ.cjs → body-BtW9TZGZ.cjs} +1 -1
- package/dist/tests/{body-DMMAC8hw.mjs → body-CmdrGt1w.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 +6 -6
- package/dist/tests/decimal.test.mjs +6 -6
- package/dist/tests/{docloader-zzQIwiJk.cjs → docloader-D34pSxKd.cjs} +106 -35
- package/dist/tests/{docloader-Bx4CBPlL.mjs → docloader-zoX3z1bj.mjs} +102 -37
- package/dist/tests/docloader.test.cjs +523 -1273
- package/dist/tests/docloader.test.mjs +469 -1238
- package/dist/tests/esm-C_ftyt-G.cjs +1208 -0
- package/dist/tests/esm-LaZ1p80h.mjs +1222 -0
- package/dist/tests/internal/multicodec.test.cjs +1 -1
- package/dist/tests/internal/multicodec.test.mjs +1 -1
- package/dist/tests/{key-Qj7u1qmH.mjs → key-2lZR0Cht.mjs} +2 -2
- package/dist/tests/{key-CWDxavIR.cjs → key-CnsHrQSU.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-C0iftNaR.cjs +90 -0
- package/dist/tests/node-C3bjFjL1.mjs +84 -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-D4UQ-HXm.cjs +221 -0
- package/dist/tests/pinners-ZgZDx9y6.mjs +203 -0
- package/dist/tests/public-fetch-BtiBjQPL.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-BBCe2UzV.mjs → request-BKFirRrO.mjs} +1 -1
- package/dist/tests/{request-Bgv8wfpZ.cjs → request-CqKju-Ll.cjs} +1 -1
- package/dist/tests/request.test.cjs +1 -1
- package/dist/tests/request.test.mjs +1 -1
- package/dist/tests/support-Cj0T6TP_.cjs +363 -0
- package/dist/tests/support-M5ClN-no.mjs +272 -0
- package/dist/tests/{url-4PAkYhZC.cjs → url-BR7UVTkW.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-BL45eko3.cjs → multibase-CPwWBzL3.cjs} +0 -0
- /package/dist/tests/{multibase-Da9VJCw8.mjs → multibase-D85wf3ZR.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-C2EiDwsr.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
2
|
+
const require_request = require("./request-CqKju-Ll.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-C2EiDwsr.cjs");
|
|
2
|
-
const require_body = require("./body-
|
|
2
|
+
const require_body = require("./body-BtW9TZGZ.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-CmdrGt1w.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-C2EiDwsr.cjs");
|
|
2
|
-
require("./docloader-
|
|
3
|
-
require("./url-
|
|
4
|
-
require("./key-
|
|
5
|
-
require("./multibase-
|
|
6
|
-
require("./langtag-
|
|
7
|
-
require("./langstr-
|
|
2
|
+
require("./docloader-D34pSxKd.cjs");
|
|
3
|
+
require("./url-BR7UVTkW.cjs");
|
|
4
|
+
require("./key-CnsHrQSU.cjs");
|
|
5
|
+
require("./multibase-CPwWBzL3.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-zoX3z1bj.mjs";
|
|
2
|
+
import "./url-DQWrMGhu.mjs";
|
|
3
|
+
import "./key-2lZR0Cht.mjs";
|
|
4
|
+
import "./multibase-D85wf3ZR.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,8 +1,9 @@
|
|
|
1
1
|
require("./chunk-C2EiDwsr.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
3
|
-
const require_body = require("./body-
|
|
2
|
+
const require_request = require("./request-CqKju-Ll.cjs");
|
|
3
|
+
const require_body = require("./body-BtW9TZGZ.cjs");
|
|
4
4
|
const require_link = require("./link-qDTmjPw_.cjs");
|
|
5
|
-
const require_url = require("./url-
|
|
5
|
+
const require_url = require("./url-BR7UVTkW.cjs");
|
|
6
|
+
const require_public_fetch = require("./public-fetch-BtiBjQPL.cjs");
|
|
6
7
|
let _logtape_logtape = require("@logtape/logtape");
|
|
7
8
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
8
9
|
//#region src/contexts/activitystreams.json
|
|
@@ -4541,13 +4542,47 @@ const DEFAULT_MAX_REDIRECTION = 20;
|
|
|
4541
4542
|
* Gets a {@link RemoteDocument} from the given response.
|
|
4542
4543
|
* @param url The URL of the document to load.
|
|
4543
4544
|
* @param response The response to get the document from.
|
|
4544
|
-
* @param fetch The function to fetch the document.
|
|
4545
|
+
* @param fetch The function to fetch the document. It is called with the URL
|
|
4546
|
+
* of an alternate document, if any, after the response body has
|
|
4547
|
+
* been either read or its cancellation has been started.
|
|
4545
4548
|
* @returns The loaded remote document.
|
|
4546
4549
|
* @throws {FetchError} If the response is not OK.
|
|
4547
4550
|
* @internal
|
|
4548
4551
|
*/
|
|
4549
4552
|
async function getRemoteDocument(url, response, fetch) {
|
|
4550
|
-
const
|
|
4553
|
+
const result = await parseRemoteDocument(url, response);
|
|
4554
|
+
if ("alternate" in result) return await fetch(result.alternate);
|
|
4555
|
+
return result.document;
|
|
4556
|
+
}
|
|
4557
|
+
/**
|
|
4558
|
+
* Starts cancelling the body of a response without waiting for it to settle.
|
|
4559
|
+
* The cancellation of a branch of a tee (e.g., a body cloned by a fetch mock)
|
|
4560
|
+
* settles only after the other branch is cancelled too, per the Streams
|
|
4561
|
+
* standard, so awaiting it could block forever. Failures are only logged.
|
|
4562
|
+
* @param response The response whose body is cancelled.
|
|
4563
|
+
* @param url The URL of the response, for logging.
|
|
4564
|
+
*/
|
|
4565
|
+
function cancelResponseBody(response, url) {
|
|
4566
|
+
response.body?.cancel().catch((error) => {
|
|
4567
|
+
logger.debug("Failed to cancel the response body from {url}: {error}", {
|
|
4568
|
+
url,
|
|
4569
|
+
error
|
|
4570
|
+
});
|
|
4571
|
+
});
|
|
4572
|
+
}
|
|
4573
|
+
/**
|
|
4574
|
+
* Gets a {@link RemoteDocument} from the given response, or the URL of an
|
|
4575
|
+
* alternate document to load instead. When an alternate document is found,
|
|
4576
|
+
* the response body has been either read or its cancellation has been started
|
|
4577
|
+
* (without waiting for it), so that the alternate document can be loaded after
|
|
4578
|
+
* the response's session is closed.
|
|
4579
|
+
* @param url The URL of the document to load.
|
|
4580
|
+
* @param response The response to get the document from.
|
|
4581
|
+
* @returns The loaded remote document, or the alternate document URL.
|
|
4582
|
+
* @throws {FetchError} If the response is not OK.
|
|
4583
|
+
*/
|
|
4584
|
+
async function parseRemoteDocument(url, response) {
|
|
4585
|
+
const documentUrl = url;
|
|
4551
4586
|
const docUrl = new URL(documentUrl);
|
|
4552
4587
|
if (!response.ok) {
|
|
4553
4588
|
logger.error("Failed to fetch document: {status} {url} {headers}", {
|
|
@@ -4584,7 +4619,8 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4584
4619
|
alternateUrl: altUri.href,
|
|
4585
4620
|
url: documentUrl
|
|
4586
4621
|
});
|
|
4587
|
-
|
|
4622
|
+
cancelResponseBody(response, documentUrl);
|
|
4623
|
+
return { alternate: altUri.href };
|
|
4588
4624
|
}
|
|
4589
4625
|
}
|
|
4590
4626
|
}
|
|
@@ -4609,7 +4645,7 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4609
4645
|
alternateUrl: attribs.href,
|
|
4610
4646
|
url: documentUrl
|
|
4611
4647
|
});
|
|
4612
|
-
return
|
|
4648
|
+
return { alternate: new URL(attribs.href, docUrl).href };
|
|
4613
4649
|
}
|
|
4614
4650
|
}
|
|
4615
4651
|
document = JSON.parse(html);
|
|
@@ -4619,11 +4655,11 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4619
4655
|
url: documentUrl,
|
|
4620
4656
|
headers: Object.fromEntries(response.headers.entries())
|
|
4621
4657
|
});
|
|
4622
|
-
return {
|
|
4658
|
+
return { document: {
|
|
4623
4659
|
contextUrl,
|
|
4624
4660
|
document,
|
|
4625
4661
|
documentUrl
|
|
4626
|
-
};
|
|
4662
|
+
} };
|
|
4627
4663
|
}
|
|
4628
4664
|
/**
|
|
4629
4665
|
* Creates a JSON-LD document loader that utilizes the browser's `fetch` API.
|
|
@@ -4649,9 +4685,54 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4649
4685
|
* @returns The document loader.
|
|
4650
4686
|
* @since 1.3.0
|
|
4651
4687
|
*/
|
|
4652
|
-
function getDocumentLoader(
|
|
4688
|
+
function getDocumentLoader(options = {}) {
|
|
4689
|
+
return createDocumentLoader(options);
|
|
4690
|
+
}
|
|
4691
|
+
/**
|
|
4692
|
+
* The implementation of {@link getDocumentLoader}, with injectable
|
|
4693
|
+
* dependencies. This is not exported from any entry point.
|
|
4694
|
+
* @param options Options for the document loader.
|
|
4695
|
+
* @param deps The dependencies.
|
|
4696
|
+
* @returns The document loader.
|
|
4697
|
+
*/
|
|
4698
|
+
function createDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedContexts, userAgent } = {}, deps = {}) {
|
|
4653
4699
|
const tracer = _opentelemetry_api.trace.getTracerProvider().getTracer(require_request.name, require_request.version);
|
|
4654
4700
|
const maximumRedirection = maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
4701
|
+
async function openHop(url, signal) {
|
|
4702
|
+
try {
|
|
4703
|
+
if (deps.openHop != null) return await deps.openHop(url);
|
|
4704
|
+
return allowPrivateAddress ? await require_public_fetch.openDirectFetch(url) : await require_public_fetch.openPublicFetch(url, { signal });
|
|
4705
|
+
} catch (error) {
|
|
4706
|
+
if (error instanceof require_url.UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
4707
|
+
url,
|
|
4708
|
+
error
|
|
4709
|
+
});
|
|
4710
|
+
else logger.error("Disallowed private URL: {url}", {
|
|
4711
|
+
url,
|
|
4712
|
+
error
|
|
4713
|
+
});
|
|
4714
|
+
throw error;
|
|
4715
|
+
}
|
|
4716
|
+
}
|
|
4717
|
+
async function fetchHop(session, url, span, options) {
|
|
4718
|
+
try {
|
|
4719
|
+
const request = require_request.createActivityPubRequest(url, { userAgent });
|
|
4720
|
+
require_request.logRequest(logger, request);
|
|
4721
|
+
const response = await session.fetch(request, {
|
|
4722
|
+
redirect: "manual",
|
|
4723
|
+
signal: options?.signal
|
|
4724
|
+
});
|
|
4725
|
+
span.setAttribute("http.response.status_code", response.status);
|
|
4726
|
+
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
4727
|
+
const location = response.headers.get("Location");
|
|
4728
|
+
cancelResponseBody(response, url);
|
|
4729
|
+
return { location };
|
|
4730
|
+
}
|
|
4731
|
+
return await parseRemoteDocument(url, response);
|
|
4732
|
+
} finally {
|
|
4733
|
+
await session.close();
|
|
4734
|
+
}
|
|
4735
|
+
}
|
|
4655
4736
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
4656
4737
|
options?.signal?.throwIfAborted();
|
|
4657
4738
|
const parsedUrl = new URL(url);
|
|
@@ -4666,33 +4747,15 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4666
4747
|
documentUrl: currentUrl
|
|
4667
4748
|
};
|
|
4668
4749
|
}
|
|
4669
|
-
|
|
4670
|
-
await require_url.validatePublicUrl(currentUrl);
|
|
4671
|
-
} catch (error) {
|
|
4672
|
-
if (error instanceof require_url.UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
4673
|
-
url: currentUrl,
|
|
4674
|
-
error
|
|
4675
|
-
});
|
|
4676
|
-
else logger.error("Disallowed private URL: {url}", {
|
|
4677
|
-
url: currentUrl,
|
|
4678
|
-
error
|
|
4679
|
-
});
|
|
4680
|
-
throw error;
|
|
4681
|
-
}
|
|
4750
|
+
const session = await openHop(currentUrl, options?.signal);
|
|
4682
4751
|
visited.add(currentUrl);
|
|
4683
4752
|
return await tracer.startActiveSpan("activitypub.fetch_document", {
|
|
4684
4753
|
kind: _opentelemetry_api.SpanKind.CLIENT,
|
|
4685
4754
|
attributes: { "url.full": currentUrl }
|
|
4686
4755
|
}, async (span) => {
|
|
4687
4756
|
try {
|
|
4688
|
-
const
|
|
4689
|
-
|
|
4690
|
-
const response = await fetch(request, {
|
|
4691
|
-
redirect: "manual",
|
|
4692
|
-
signal: options?.signal
|
|
4693
|
-
});
|
|
4694
|
-
span.setAttribute("http.response.status_code", response.status);
|
|
4695
|
-
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
4757
|
+
const outcome = await fetchHop(session, currentUrl, span, options);
|
|
4758
|
+
if ("location" in outcome) {
|
|
4696
4759
|
if (redirected >= maximumRedirection) {
|
|
4697
4760
|
logger.error("Too many redirections ({redirections}) while fetching document.", {
|
|
4698
4761
|
redirections: redirected + 1,
|
|
@@ -4700,7 +4763,7 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4700
4763
|
});
|
|
4701
4764
|
throw new require_request.FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
4702
4765
|
}
|
|
4703
|
-
const redirectUrl = new URL(
|
|
4766
|
+
const redirectUrl = new URL(outcome.location, currentUrl).href;
|
|
4704
4767
|
span.setAttribute("http.redirect.url", redirectUrl);
|
|
4705
4768
|
if (visited.has(redirectUrl)) {
|
|
4706
4769
|
logger.error("Detected a redirect loop while fetching document: {url} -> {redirectUrl}", {
|
|
@@ -4711,12 +4774,14 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4711
4774
|
}
|
|
4712
4775
|
return await load(redirectUrl, options, redirected + 1, visited);
|
|
4713
4776
|
}
|
|
4714
|
-
|
|
4777
|
+
let result;
|
|
4778
|
+
if ("alternate" in outcome) {
|
|
4779
|
+
const alternateUrl = outcome.alternate;
|
|
4715
4780
|
options?.signal?.throwIfAborted();
|
|
4716
4781
|
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new require_request.FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
4717
4782
|
if (visited.has(alternateUrl)) throw new require_request.FetchError(currentUrl, `Redirect loop detected: ${alternateUrl}`);
|
|
4718
|
-
|
|
4719
|
-
}
|
|
4783
|
+
result = await load(alternateUrl, options, redirected + 1, visited);
|
|
4784
|
+
} else result = outcome.document;
|
|
4720
4785
|
span.setAttribute("docloader.document_url", result.documentUrl);
|
|
4721
4786
|
if (result.contextUrl != null) span.setAttribute("docloader.context_url", result.contextUrl);
|
|
4722
4787
|
return result;
|
|
@@ -4741,6 +4806,12 @@ Object.defineProperty(exports, "cid_v1_default", {
|
|
|
4741
4806
|
return cid_v1_default;
|
|
4742
4807
|
}
|
|
4743
4808
|
});
|
|
4809
|
+
Object.defineProperty(exports, "createDocumentLoader", {
|
|
4810
|
+
enumerable: true,
|
|
4811
|
+
get: function() {
|
|
4812
|
+
return createDocumentLoader;
|
|
4813
|
+
}
|
|
4814
|
+
});
|
|
4744
4815
|
Object.defineProperty(exports, "getDocumentLoader", {
|
|
4745
4816
|
enumerable: true,
|
|
4746
4817
|
get: function() {
|
|
@@ -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-BKFirRrO.mjs";
|
|
2
|
+
import { n as MAX_BODY_SIZE, r as readBoundedText } from "./body-CmdrGt1w.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
|
|
@@ -4540,13 +4541,47 @@ const DEFAULT_MAX_REDIRECTION = 20;
|
|
|
4540
4541
|
* Gets a {@link RemoteDocument} from the given response.
|
|
4541
4542
|
* @param url The URL of the document to load.
|
|
4542
4543
|
* @param response The response to get the document from.
|
|
4543
|
-
* @param fetch The function to fetch the document.
|
|
4544
|
+
* @param fetch The function to fetch the document. It is called with the URL
|
|
4545
|
+
* of an alternate document, if any, after the response body has
|
|
4546
|
+
* been either read or its cancellation has been started.
|
|
4544
4547
|
* @returns The loaded remote document.
|
|
4545
4548
|
* @throws {FetchError} If the response is not OK.
|
|
4546
4549
|
* @internal
|
|
4547
4550
|
*/
|
|
4548
4551
|
async function getRemoteDocument(url, response, fetch) {
|
|
4549
|
-
const
|
|
4552
|
+
const result = await parseRemoteDocument(url, response);
|
|
4553
|
+
if ("alternate" in result) return await fetch(result.alternate);
|
|
4554
|
+
return result.document;
|
|
4555
|
+
}
|
|
4556
|
+
/**
|
|
4557
|
+
* Starts cancelling the body of a response without waiting for it to settle.
|
|
4558
|
+
* The cancellation of a branch of a tee (e.g., a body cloned by a fetch mock)
|
|
4559
|
+
* settles only after the other branch is cancelled too, per the Streams
|
|
4560
|
+
* standard, so awaiting it could block forever. Failures are only logged.
|
|
4561
|
+
* @param response The response whose body is cancelled.
|
|
4562
|
+
* @param url The URL of the response, for logging.
|
|
4563
|
+
*/
|
|
4564
|
+
function cancelResponseBody(response, url) {
|
|
4565
|
+
response.body?.cancel().catch((error) => {
|
|
4566
|
+
logger.debug("Failed to cancel the response body from {url}: {error}", {
|
|
4567
|
+
url,
|
|
4568
|
+
error
|
|
4569
|
+
});
|
|
4570
|
+
});
|
|
4571
|
+
}
|
|
4572
|
+
/**
|
|
4573
|
+
* Gets a {@link RemoteDocument} from the given response, or the URL of an
|
|
4574
|
+
* alternate document to load instead. When an alternate document is found,
|
|
4575
|
+
* the response body has been either read or its cancellation has been started
|
|
4576
|
+
* (without waiting for it), so that the alternate document can be loaded after
|
|
4577
|
+
* the response's session is closed.
|
|
4578
|
+
* @param url The URL of the document to load.
|
|
4579
|
+
* @param response The response to get the document from.
|
|
4580
|
+
* @returns The loaded remote document, or the alternate document URL.
|
|
4581
|
+
* @throws {FetchError} If the response is not OK.
|
|
4582
|
+
*/
|
|
4583
|
+
async function parseRemoteDocument(url, response) {
|
|
4584
|
+
const documentUrl = url;
|
|
4550
4585
|
const docUrl = new URL(documentUrl);
|
|
4551
4586
|
if (!response.ok) {
|
|
4552
4587
|
logger.error("Failed to fetch document: {status} {url} {headers}", {
|
|
@@ -4583,7 +4618,8 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4583
4618
|
alternateUrl: altUri.href,
|
|
4584
4619
|
url: documentUrl
|
|
4585
4620
|
});
|
|
4586
|
-
|
|
4621
|
+
cancelResponseBody(response, documentUrl);
|
|
4622
|
+
return { alternate: altUri.href };
|
|
4587
4623
|
}
|
|
4588
4624
|
}
|
|
4589
4625
|
}
|
|
@@ -4608,7 +4644,7 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4608
4644
|
alternateUrl: attribs.href,
|
|
4609
4645
|
url: documentUrl
|
|
4610
4646
|
});
|
|
4611
|
-
return
|
|
4647
|
+
return { alternate: new URL(attribs.href, docUrl).href };
|
|
4612
4648
|
}
|
|
4613
4649
|
}
|
|
4614
4650
|
document = JSON.parse(html);
|
|
@@ -4618,11 +4654,11 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4618
4654
|
url: documentUrl,
|
|
4619
4655
|
headers: Object.fromEntries(response.headers.entries())
|
|
4620
4656
|
});
|
|
4621
|
-
return {
|
|
4657
|
+
return { document: {
|
|
4622
4658
|
contextUrl,
|
|
4623
4659
|
document,
|
|
4624
4660
|
documentUrl
|
|
4625
|
-
};
|
|
4661
|
+
} };
|
|
4626
4662
|
}
|
|
4627
4663
|
/**
|
|
4628
4664
|
* Creates a JSON-LD document loader that utilizes the browser's `fetch` API.
|
|
@@ -4648,9 +4684,54 @@ async function getRemoteDocument(url, response, fetch) {
|
|
|
4648
4684
|
* @returns The document loader.
|
|
4649
4685
|
* @since 1.3.0
|
|
4650
4686
|
*/
|
|
4651
|
-
function getDocumentLoader(
|
|
4687
|
+
function getDocumentLoader(options = {}) {
|
|
4688
|
+
return createDocumentLoader(options);
|
|
4689
|
+
}
|
|
4690
|
+
/**
|
|
4691
|
+
* The implementation of {@link getDocumentLoader}, with injectable
|
|
4692
|
+
* dependencies. This is not exported from any entry point.
|
|
4693
|
+
* @param options Options for the document loader.
|
|
4694
|
+
* @param deps The dependencies.
|
|
4695
|
+
* @returns The document loader.
|
|
4696
|
+
*/
|
|
4697
|
+
function createDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedContexts, userAgent } = {}, deps = {}) {
|
|
4652
4698
|
const tracer = trace.getTracerProvider().getTracer(name, version);
|
|
4653
4699
|
const maximumRedirection = maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
4700
|
+
async function openHop(url, signal) {
|
|
4701
|
+
try {
|
|
4702
|
+
if (deps.openHop != null) return await deps.openHop(url);
|
|
4703
|
+
return allowPrivateAddress ? await openDirectFetch(url) : await openPublicFetch(url, { signal });
|
|
4704
|
+
} catch (error) {
|
|
4705
|
+
if (error instanceof UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
4706
|
+
url,
|
|
4707
|
+
error
|
|
4708
|
+
});
|
|
4709
|
+
else logger.error("Disallowed private URL: {url}", {
|
|
4710
|
+
url,
|
|
4711
|
+
error
|
|
4712
|
+
});
|
|
4713
|
+
throw error;
|
|
4714
|
+
}
|
|
4715
|
+
}
|
|
4716
|
+
async function fetchHop(session, url, span, options) {
|
|
4717
|
+
try {
|
|
4718
|
+
const request = createActivityPubRequest(url, { userAgent });
|
|
4719
|
+
logRequest(logger, request);
|
|
4720
|
+
const response = await session.fetch(request, {
|
|
4721
|
+
redirect: "manual",
|
|
4722
|
+
signal: options?.signal
|
|
4723
|
+
});
|
|
4724
|
+
span.setAttribute("http.response.status_code", response.status);
|
|
4725
|
+
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
4726
|
+
const location = response.headers.get("Location");
|
|
4727
|
+
cancelResponseBody(response, url);
|
|
4728
|
+
return { location };
|
|
4729
|
+
}
|
|
4730
|
+
return await parseRemoteDocument(url, response);
|
|
4731
|
+
} finally {
|
|
4732
|
+
await session.close();
|
|
4733
|
+
}
|
|
4734
|
+
}
|
|
4654
4735
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
4655
4736
|
options?.signal?.throwIfAborted();
|
|
4656
4737
|
const parsedUrl = new URL(url);
|
|
@@ -4665,33 +4746,15 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4665
4746
|
documentUrl: currentUrl
|
|
4666
4747
|
};
|
|
4667
4748
|
}
|
|
4668
|
-
|
|
4669
|
-
await validatePublicUrl(currentUrl);
|
|
4670
|
-
} catch (error) {
|
|
4671
|
-
if (error instanceof UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
4672
|
-
url: currentUrl,
|
|
4673
|
-
error
|
|
4674
|
-
});
|
|
4675
|
-
else logger.error("Disallowed private URL: {url}", {
|
|
4676
|
-
url: currentUrl,
|
|
4677
|
-
error
|
|
4678
|
-
});
|
|
4679
|
-
throw error;
|
|
4680
|
-
}
|
|
4749
|
+
const session = await openHop(currentUrl, options?.signal);
|
|
4681
4750
|
visited.add(currentUrl);
|
|
4682
4751
|
return await tracer.startActiveSpan("activitypub.fetch_document", {
|
|
4683
4752
|
kind: SpanKind.CLIENT,
|
|
4684
4753
|
attributes: { "url.full": currentUrl }
|
|
4685
4754
|
}, async (span) => {
|
|
4686
4755
|
try {
|
|
4687
|
-
const
|
|
4688
|
-
|
|
4689
|
-
const response = await fetch(request, {
|
|
4690
|
-
redirect: "manual",
|
|
4691
|
-
signal: options?.signal
|
|
4692
|
-
});
|
|
4693
|
-
span.setAttribute("http.response.status_code", response.status);
|
|
4694
|
-
if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
|
|
4756
|
+
const outcome = await fetchHop(session, currentUrl, span, options);
|
|
4757
|
+
if ("location" in outcome) {
|
|
4695
4758
|
if (redirected >= maximumRedirection) {
|
|
4696
4759
|
logger.error("Too many redirections ({redirections}) while fetching document.", {
|
|
4697
4760
|
redirections: redirected + 1,
|
|
@@ -4699,7 +4762,7 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4699
4762
|
});
|
|
4700
4763
|
throw new FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
4701
4764
|
}
|
|
4702
|
-
const redirectUrl = new URL(
|
|
4765
|
+
const redirectUrl = new URL(outcome.location, currentUrl).href;
|
|
4703
4766
|
span.setAttribute("http.redirect.url", redirectUrl);
|
|
4704
4767
|
if (visited.has(redirectUrl)) {
|
|
4705
4768
|
logger.error("Detected a redirect loop while fetching document: {url} -> {redirectUrl}", {
|
|
@@ -4710,12 +4773,14 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4710
4773
|
}
|
|
4711
4774
|
return await load(redirectUrl, options, redirected + 1, visited);
|
|
4712
4775
|
}
|
|
4713
|
-
|
|
4776
|
+
let result;
|
|
4777
|
+
if ("alternate" in outcome) {
|
|
4778
|
+
const alternateUrl = outcome.alternate;
|
|
4714
4779
|
options?.signal?.throwIfAborted();
|
|
4715
4780
|
if (redirected >= DEFAULT_MAX_REDIRECTION) throw new FetchError(currentUrl, `Too many redirections (${redirected + 1})`);
|
|
4716
4781
|
if (visited.has(alternateUrl)) throw new FetchError(currentUrl, `Redirect loop detected: ${alternateUrl}`);
|
|
4717
|
-
|
|
4718
|
-
}
|
|
4782
|
+
result = await load(alternateUrl, options, redirected + 1, visited);
|
|
4783
|
+
} else result = outcome.document;
|
|
4719
4784
|
span.setAttribute("docloader.document_url", result.documentUrl);
|
|
4720
4785
|
if (result.contextUrl != null) span.setAttribute("docloader.context_url", result.contextUrl);
|
|
4721
4786
|
return result;
|
|
@@ -4734,4 +4799,4 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
4734
4799
|
return (url, options) => load(url, options);
|
|
4735
4800
|
}
|
|
4736
4801
|
//#endregion
|
|
4737
|
-
export { cid_v1_default as i,
|
|
4802
|
+
export { cid_v1_default as a, preloadedContexts as i, getDocumentLoader as n, getRemoteDocument as r, createDocumentLoader as t };
|