@fedify/vocab-runtime 2.5.0-dev.2378 → 2.5.0-dev.2424
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 +1 -1
- package/dist/mod.cjs +4 -2
- package/dist/mod.js +4 -2
- package/dist/tests/{body-BvFSJ8MX.cjs → body-DVcRd85t.cjs} +1 -1
- package/dist/tests/{body-Dw-TME37.mjs → body-Djuimvjd.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 +3 -3
- package/dist/tests/decimal.test.mjs +3 -3
- package/dist/tests/{docloader-DfKe9tzg.mjs → docloader--jQ3XcCi.mjs} +5 -3
- package/dist/tests/{docloader-CtYlclGl.cjs → docloader-DzwnQe1e.cjs} +5 -3
- package/dist/tests/docloader.test.cjs +50 -2
- package/dist/tests/docloader.test.mjs +50 -2
- package/dist/tests/{portable-media-m6FfvJAS.mjs → portable-media-BHBIOsiA.mjs} +2 -2
- package/dist/tests/{portable-media-BOmei2xs.cjs → portable-media-LtEUNA6B.cjs} +2 -2
- package/dist/tests/portable-media.test.cjs +1 -1
- package/dist/tests/portable-media.test.mjs +1 -1
- package/dist/tests/{request-CUfih6js.cjs → request-3qhu9psJ.cjs} +1 -1
- package/dist/tests/{request-DthSKvCz.mjs → request-BHqGsrJF.mjs} +1 -1
- package/dist/tests/request.test.cjs +1 -1
- package/dist/tests/request.test.mjs +1 -1
- package/package.json +1 -1
- package/src/docloader.test.ts +90 -0
- package/src/docloader.ts +5 -1
package/deno.json
CHANGED
package/dist/mod.cjs
CHANGED
|
@@ -16,7 +16,7 @@ let _multiformats_base_x = require("@multiformats/base-x");
|
|
|
16
16
|
_multiformats_base_x = require_rolldown_runtime.__toESM(_multiformats_base_x, 1);
|
|
17
17
|
//#region deno.json
|
|
18
18
|
var name = "@fedify/vocab-runtime";
|
|
19
|
-
var version = "2.5.0-dev.
|
|
19
|
+
var version = "2.5.0-dev.2424+97214632";
|
|
20
20
|
//#endregion
|
|
21
21
|
//#region src/request.ts
|
|
22
22
|
/**
|
|
@@ -772,7 +772,9 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
772
772
|
const maximumRedirection = maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
773
773
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
774
774
|
options?.signal?.throwIfAborted();
|
|
775
|
-
const
|
|
775
|
+
const parsedUrl = new URL(url);
|
|
776
|
+
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") throw new require_url.UrlError(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
777
|
+
const currentUrl = parsedUrl.href;
|
|
776
778
|
if (!skipPreloadedContexts && currentUrl in require_contexts.preloadedContexts) {
|
|
777
779
|
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|
|
778
780
|
return {
|
package/dist/mod.js
CHANGED
|
@@ -12,7 +12,7 @@ import { PublicKeyInfo } from "pkijs";
|
|
|
12
12
|
import baseX from "@multiformats/base-x";
|
|
13
13
|
//#region deno.json
|
|
14
14
|
var name = "@fedify/vocab-runtime";
|
|
15
|
-
var version = "2.5.0-dev.
|
|
15
|
+
var version = "2.5.0-dev.2424+97214632";
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/request.ts
|
|
18
18
|
/**
|
|
@@ -768,7 +768,9 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
768
768
|
const maximumRedirection = maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
769
769
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
770
770
|
options?.signal?.throwIfAborted();
|
|
771
|
-
const
|
|
771
|
+
const parsedUrl = new URL(url);
|
|
772
|
+
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") throw new UrlError(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
773
|
+
const currentUrl = parsedUrl.href;
|
|
772
774
|
if (!skipPreloadedContexts && currentUrl in preloadedContexts) {
|
|
773
775
|
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|
|
774
776
|
return {
|
package/dist/tests/body.test.cjs
CHANGED
package/dist/tests/body.test.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as readBoundedText, t as BodyTooLargeError } from "./body-
|
|
1
|
+
import { i as readBoundedText, t as BodyTooLargeError } from "./body-Djuimvjd.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,12 +1,12 @@
|
|
|
1
|
-
require("./request-
|
|
1
|
+
require("./request-3qhu9psJ.cjs");
|
|
2
2
|
require("./url-BNakuZ8k.cjs");
|
|
3
|
-
require("./docloader-
|
|
3
|
+
require("./docloader-DzwnQe1e.cjs");
|
|
4
4
|
require("./key-C-AYkdJJ.cjs");
|
|
5
5
|
require("./multibase-B5Mea7Ip.cjs");
|
|
6
6
|
require("./digest-3FeH2Y-Q.cjs");
|
|
7
7
|
require("./langtag-DASCPgl3.cjs");
|
|
8
8
|
require("./langstr-h89Kjekh.cjs");
|
|
9
|
-
require("./portable-media-
|
|
9
|
+
require("./portable-media-LtEUNA6B.cjs");
|
|
10
10
|
let node_test = require("node:test");
|
|
11
11
|
let node_assert = require("node:assert");
|
|
12
12
|
//#region src/decimal.ts
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import "./request-
|
|
1
|
+
import "./request-BHqGsrJF.mjs";
|
|
2
2
|
import "./url-DMxmp7ZG.mjs";
|
|
3
|
-
import "./docloader
|
|
3
|
+
import "./docloader--jQ3XcCi.mjs";
|
|
4
4
|
import "./key-C2Db_TAJ.mjs";
|
|
5
5
|
import "./multibase-BPnF_L4e.mjs";
|
|
6
6
|
import "./digest-COC7xDiQ.mjs";
|
|
7
7
|
import "./langtag-CD3zHKPN.mjs";
|
|
8
8
|
import "./langstr-Dw8IBDZl.mjs";
|
|
9
|
-
import "./portable-media-
|
|
9
|
+
import "./portable-media-BHBIOsiA.mjs";
|
|
10
10
|
import { test } from "node:test";
|
|
11
11
|
import { deepStrictEqual, throws } from "node:assert";
|
|
12
12
|
//#region src/decimal.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as logRequest, n as createActivityPubRequest, o as name, s as version, t as FetchError } from "./request-
|
|
1
|
+
import { a as logRequest, n as createActivityPubRequest, o as name, s as version, t as FetchError } from "./request-BHqGsrJF.mjs";
|
|
2
2
|
import { n as UrlError, x as validatePublicUrl } from "./url-DMxmp7ZG.mjs";
|
|
3
|
-
import { i as readBoundedText, n as MAX_BODY_SIZE, r as readBoundedBytes, t as BodyTooLargeError } from "./body-
|
|
3
|
+
import { i as readBoundedText, n as MAX_BODY_SIZE, r as readBoundedBytes, t as BodyTooLargeError } from "./body-Djuimvjd.mjs";
|
|
4
4
|
import { t as preloadedContexts } from "./contexts-duRA_dDC.mjs";
|
|
5
5
|
import { t as HttpHeaderLink } from "./link-Cevmc87v.mjs";
|
|
6
6
|
import { getLogger } from "@logtape/logtape";
|
|
@@ -291,7 +291,9 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
291
291
|
const maximumRedirection = maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
292
292
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
293
293
|
options?.signal?.throwIfAborted();
|
|
294
|
-
const
|
|
294
|
+
const parsedUrl = new URL(url);
|
|
295
|
+
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") throw new UrlError(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
296
|
+
const currentUrl = parsedUrl.href;
|
|
295
297
|
if (!skipPreloadedContexts && currentUrl in preloadedContexts) {
|
|
296
298
|
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|
|
297
299
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const require_request = require("./request-
|
|
1
|
+
const require_request = require("./request-3qhu9psJ.cjs");
|
|
2
2
|
const require_url = require("./url-BNakuZ8k.cjs");
|
|
3
|
-
const require_body = require("./body-
|
|
3
|
+
const require_body = require("./body-DVcRd85t.cjs");
|
|
4
4
|
const require_contexts = require("./contexts-C9Lj11SC.cjs");
|
|
5
5
|
const require_link = require("./link-DlKm8bEr.cjs");
|
|
6
6
|
let _logtape_logtape = require("@logtape/logtape");
|
|
@@ -291,7 +291,9 @@ function getDocumentLoader({ allowPrivateAddress, maxRedirection, skipPreloadedC
|
|
|
291
291
|
const maximumRedirection = maxRedirection ?? DEFAULT_MAX_REDIRECTION;
|
|
292
292
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
293
293
|
options?.signal?.throwIfAborted();
|
|
294
|
-
const
|
|
294
|
+
const parsedUrl = new URL(url);
|
|
295
|
+
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") throw new require_url.UrlError(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
296
|
+
const currentUrl = parsedUrl.href;
|
|
295
297
|
if (!skipPreloadedContexts && currentUrl in require_contexts.preloadedContexts) {
|
|
296
298
|
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|
|
297
299
|
return {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-emK7D4bc.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
2
|
+
const require_request = require("./request-3qhu9psJ.cjs");
|
|
3
3
|
const require_url = require("./url-BNakuZ8k.cjs");
|
|
4
4
|
const require_contexts = require("./contexts-C9Lj11SC.cjs");
|
|
5
|
-
const require_docloader = require("./docloader-
|
|
5
|
+
const require_docloader = require("./docloader-DzwnQe1e.cjs");
|
|
6
6
|
const require_jsonld = require("./jsonld-CmDhHNTx.cjs");
|
|
7
7
|
let node_zlib = require("node:zlib");
|
|
8
8
|
let _logtape_logtape = require("@logtape/logtape");
|
|
@@ -2371,4 +2371,52 @@ function isTimeoutFetchError(error, url) {
|
|
|
2371
2371
|
})(url), (e) => isTimeoutFetchError(e, url));
|
|
2372
2372
|
});
|
|
2373
2373
|
});
|
|
2374
|
+
const unsupportedUrls = [
|
|
2375
|
+
"ftp://example.com/collection",
|
|
2376
|
+
"file:///collection",
|
|
2377
|
+
`data:application/ld+json,${encodeURIComponent(JSON.stringify({ id: "https://example.com/data" }))}`
|
|
2378
|
+
];
|
|
2379
|
+
function isUnsupportedProtocolError(error, url) {
|
|
2380
|
+
return error instanceof require_url.UrlError && error.message === `Unsupported protocol: ${new URL(url).protocol}` && error.reason === "disallowed";
|
|
2381
|
+
}
|
|
2382
|
+
async function withFetchStub(respond, callback) {
|
|
2383
|
+
const fetched = [];
|
|
2384
|
+
const originalFetch = globalThis.fetch;
|
|
2385
|
+
globalThis.fetch = (input) => {
|
|
2386
|
+
const url = input instanceof Request ? input.url : String(input);
|
|
2387
|
+
fetched.push(url);
|
|
2388
|
+
return Promise.resolve(respond(url));
|
|
2389
|
+
};
|
|
2390
|
+
try {
|
|
2391
|
+
await callback(fetched);
|
|
2392
|
+
} finally {
|
|
2393
|
+
globalThis.fetch = originalFetch;
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
for (const url of unsupportedUrls) {
|
|
2397
|
+
const scheme = new URL(url).protocol;
|
|
2398
|
+
(0, _fedify_fixture.test)(`getDocumentLoader() rejects ${scheme} URLs with private addresses allowed before fetching`, async () => {
|
|
2399
|
+
await withFetchStub(() => Response.json({}), async (fetched) => {
|
|
2400
|
+
await (0, node_assert.rejects)(require_docloader.getDocumentLoader({ allowPrivateAddress: true })(url), (e) => isUnsupportedProtocolError(e, url));
|
|
2401
|
+
(0, node_assert.deepStrictEqual)(fetched, []);
|
|
2402
|
+
});
|
|
2403
|
+
});
|
|
2404
|
+
(0, _fedify_fixture.test)(`getDocumentLoader() rejects redirects to ${scheme} URLs with private addresses allowed`, async () => {
|
|
2405
|
+
const start = "https://example.com/redirect-to-unsupported";
|
|
2406
|
+
await withFetchStub(() => Response.redirect(url, 302), async (fetched) => {
|
|
2407
|
+
await (0, node_assert.rejects)(require_docloader.getDocumentLoader({ allowPrivateAddress: true })(start), (e) => isUnsupportedProtocolError(e, url));
|
|
2408
|
+
(0, node_assert.deepStrictEqual)(fetched, [start]);
|
|
2409
|
+
});
|
|
2410
|
+
});
|
|
2411
|
+
for (const html of [false, true]) (0, _fedify_fixture.test)(`getDocumentLoader() rejects ${html ? "HTML" : "Link header"} alternates to ${scheme} URLs with private addresses allowed`, async () => {
|
|
2412
|
+
const start = "https://example.com/alternate-to-unsupported";
|
|
2413
|
+
await withFetchStub(() => html ? new Response(`<link rel="alternate" type="application/activity+json" href="${url}">`, { headers: { "Content-Type": "text/html" } }) : new Response("", { headers: {
|
|
2414
|
+
"Content-Type": "text/plain",
|
|
2415
|
+
Link: `<${url}>; rel="alternate"; type="application/activity+json"`
|
|
2416
|
+
} }), async (fetched) => {
|
|
2417
|
+
await (0, node_assert.rejects)(require_docloader.getDocumentLoader({ allowPrivateAddress: true })(start), (e) => isUnsupportedProtocolError(e, url));
|
|
2418
|
+
(0, node_assert.deepStrictEqual)(fetched, [start]);
|
|
2419
|
+
});
|
|
2420
|
+
});
|
|
2421
|
+
}
|
|
2374
2422
|
//#endregion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as FetchError } from "./request-
|
|
1
|
+
import { t as FetchError } from "./request-BHqGsrJF.mjs";
|
|
2
2
|
import { n as UrlError } from "./url-DMxmp7ZG.mjs";
|
|
3
3
|
import { n as cid_v1_default, t as preloadedContexts } from "./contexts-duRA_dDC.mjs";
|
|
4
|
-
import { i as withDocumentLoaderTimeout, n as getRemoteDocument, r as resolveDocumentLoaderTimeout, t as getDocumentLoader } from "./docloader
|
|
4
|
+
import { i as withDocumentLoaderTimeout, n as getRemoteDocument, r as resolveDocumentLoaderTimeout, t as getDocumentLoader } from "./docloader--jQ3XcCi.mjs";
|
|
5
5
|
import { t as jsonld_default } from "./jsonld-DweIJ07b.mjs";
|
|
6
6
|
import { gzipSync } from "node:zlib";
|
|
7
7
|
import { configure, reset } from "@logtape/logtape";
|
|
@@ -2389,5 +2389,53 @@ test("getDocumentLoader() times out a stalled body of such a status", async () =
|
|
|
2389
2389
|
})(url), (e) => isTimeoutFetchError(e, url));
|
|
2390
2390
|
});
|
|
2391
2391
|
});
|
|
2392
|
+
const unsupportedUrls = [
|
|
2393
|
+
"ftp://example.com/collection",
|
|
2394
|
+
"file:///collection",
|
|
2395
|
+
`data:application/ld+json,${encodeURIComponent(JSON.stringify({ id: "https://example.com/data" }))}`
|
|
2396
|
+
];
|
|
2397
|
+
function isUnsupportedProtocolError(error, url) {
|
|
2398
|
+
return error instanceof UrlError && error.message === `Unsupported protocol: ${new URL(url).protocol}` && error.reason === "disallowed";
|
|
2399
|
+
}
|
|
2400
|
+
async function withFetchStub(respond, callback) {
|
|
2401
|
+
const fetched = [];
|
|
2402
|
+
const originalFetch = globalThis.fetch;
|
|
2403
|
+
globalThis.fetch = (input) => {
|
|
2404
|
+
const url = input instanceof Request ? input.url : String(input);
|
|
2405
|
+
fetched.push(url);
|
|
2406
|
+
return Promise.resolve(respond(url));
|
|
2407
|
+
};
|
|
2408
|
+
try {
|
|
2409
|
+
await callback(fetched);
|
|
2410
|
+
} finally {
|
|
2411
|
+
globalThis.fetch = originalFetch;
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
for (const url of unsupportedUrls) {
|
|
2415
|
+
const scheme = new URL(url).protocol;
|
|
2416
|
+
test(`getDocumentLoader() rejects ${scheme} URLs with private addresses allowed before fetching`, async () => {
|
|
2417
|
+
await withFetchStub(() => Response.json({}), async (fetched) => {
|
|
2418
|
+
await rejects(getDocumentLoader({ allowPrivateAddress: true })(url), (e) => isUnsupportedProtocolError(e, url));
|
|
2419
|
+
deepStrictEqual(fetched, []);
|
|
2420
|
+
});
|
|
2421
|
+
});
|
|
2422
|
+
test(`getDocumentLoader() rejects redirects to ${scheme} URLs with private addresses allowed`, async () => {
|
|
2423
|
+
const start = "https://example.com/redirect-to-unsupported";
|
|
2424
|
+
await withFetchStub(() => Response.redirect(url, 302), async (fetched) => {
|
|
2425
|
+
await rejects(getDocumentLoader({ allowPrivateAddress: true })(start), (e) => isUnsupportedProtocolError(e, url));
|
|
2426
|
+
deepStrictEqual(fetched, [start]);
|
|
2427
|
+
});
|
|
2428
|
+
});
|
|
2429
|
+
for (const html of [false, true]) test(`getDocumentLoader() rejects ${html ? "HTML" : "Link header"} alternates to ${scheme} URLs with private addresses allowed`, async () => {
|
|
2430
|
+
const start = "https://example.com/alternate-to-unsupported";
|
|
2431
|
+
await withFetchStub(() => html ? new Response(`<link rel="alternate" type="application/activity+json" href="${url}">`, { headers: { "Content-Type": "text/html" } }) : new Response("", { headers: {
|
|
2432
|
+
"Content-Type": "text/plain",
|
|
2433
|
+
Link: `<${url}>; rel="alternate"; type="application/activity+json"`
|
|
2434
|
+
} }), async (fetched) => {
|
|
2435
|
+
await rejects(getDocumentLoader({ allowPrivateAddress: true })(start), (e) => isUnsupportedProtocolError(e, url));
|
|
2436
|
+
deepStrictEqual(fetched, [start]);
|
|
2437
|
+
});
|
|
2438
|
+
});
|
|
2439
|
+
}
|
|
2392
2440
|
//#endregion
|
|
2393
2441
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { r as getUserAgent } from "./request-
|
|
1
|
+
import { r as getUserAgent } from "./request-BHqGsrJF.mjs";
|
|
2
2
|
import { g as parseGatewayUrl, x as validatePublicUrl } from "./url-DMxmp7ZG.mjs";
|
|
3
|
-
import { r as readBoundedBytes } from "./body-
|
|
3
|
+
import { r as readBoundedBytes } from "./body-Djuimvjd.mjs";
|
|
4
4
|
import { a as verifyDigestMultibase, i as parseHashlink, r as parseDigestMultibase } from "./digest-COC7xDiQ.mjs";
|
|
5
5
|
//#region src/portable-media.ts
|
|
6
6
|
function resolveTimeout(value, fallback) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const require_request = require("./request-
|
|
1
|
+
const require_request = require("./request-3qhu9psJ.cjs");
|
|
2
2
|
const require_url = require("./url-BNakuZ8k.cjs");
|
|
3
|
-
const require_body = require("./body-
|
|
3
|
+
const require_body = require("./body-DVcRd85t.cjs");
|
|
4
4
|
const require_digest = require("./digest-3FeH2Y-Q.cjs");
|
|
5
5
|
//#region src/portable-media.ts
|
|
6
6
|
function resolveTimeout(value, fallback) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_digest = require("./digest-3FeH2Y-Q.cjs");
|
|
2
|
-
const require_portable_media = require("./portable-media-
|
|
2
|
+
const require_portable_media = require("./portable-media-LtEUNA6B.cjs");
|
|
3
3
|
let node_assert_strict = require("node:assert/strict");
|
|
4
4
|
let node_test = require("node:test");
|
|
5
5
|
let node_http = require("node:http");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as createHashlink, t as computeDigestMultibase } from "./digest-COC7xDiQ.mjs";
|
|
2
|
-
import { t as fetchPortableMedia } from "./portable-media-
|
|
2
|
+
import { t as fetchPortableMedia } from "./portable-media-BHBIOsiA.mjs";
|
|
3
3
|
import { deepStrictEqual, equal, rejects } from "node:assert/strict";
|
|
4
4
|
import { test } from "node:test";
|
|
5
5
|
import { createServer } from "node:http";
|
|
@@ -4,7 +4,7 @@ let node_process = require("node:process");
|
|
|
4
4
|
node_process = require_rolldown_runtime.__toESM(node_process, 1);
|
|
5
5
|
//#region deno.json
|
|
6
6
|
var name = "@fedify/vocab-runtime";
|
|
7
|
-
var version = "2.5.0-dev.
|
|
7
|
+
var version = "2.5.0-dev.2424+97214632";
|
|
8
8
|
//#endregion
|
|
9
9
|
//#region src/request.ts
|
|
10
10
|
/**
|
|
@@ -2,7 +2,7 @@ import { n as UrlError } from "./url-DMxmp7ZG.mjs";
|
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
//#region deno.json
|
|
4
4
|
var name = "@fedify/vocab-runtime";
|
|
5
|
-
var version = "2.5.0-dev.
|
|
5
|
+
var version = "2.5.0-dev.2424+97214632";
|
|
6
6
|
//#endregion
|
|
7
7
|
//#region src/request.ts
|
|
8
8
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-emK7D4bc.cjs");
|
|
2
|
-
const require_request = require("./request-
|
|
2
|
+
const require_request = require("./request-3qhu9psJ.cjs");
|
|
3
3
|
const require_url = require("./url-BNakuZ8k.cjs");
|
|
4
4
|
let node_test = require("node:test");
|
|
5
5
|
let node_process = require("node:process");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as isTransientFetchError, n as createActivityPubRequest, r as getUserAgent, s as version, t as FetchError } from "./request-
|
|
1
|
+
import { i as isTransientFetchError, n as createActivityPubRequest, r as getUserAgent, s as version, t as FetchError } from "./request-BHqGsrJF.mjs";
|
|
2
2
|
import { n as UrlError } from "./url-DMxmp7ZG.mjs";
|
|
3
3
|
import { test } from "node:test";
|
|
4
4
|
import process from "node:process";
|
package/package.json
CHANGED
package/src/docloader.test.ts
CHANGED
|
@@ -1612,3 +1612,93 @@ test("getDocumentLoader() times out a stalled body of such a status", async () =
|
|
|
1612
1612
|
await rejects(loader(url), (e) => isTimeoutFetchError(e, url));
|
|
1613
1613
|
});
|
|
1614
1614
|
});
|
|
1615
|
+
|
|
1616
|
+
const unsupportedUrls = [
|
|
1617
|
+
"ftp://example.com/collection",
|
|
1618
|
+
"file:///collection",
|
|
1619
|
+
`data:application/ld+json,${
|
|
1620
|
+
encodeURIComponent(JSON.stringify({ id: "https://example.com/data" }))
|
|
1621
|
+
}`,
|
|
1622
|
+
];
|
|
1623
|
+
|
|
1624
|
+
function isUnsupportedProtocolError(error: unknown, url: string): boolean {
|
|
1625
|
+
return error instanceof UrlError &&
|
|
1626
|
+
error.message === `Unsupported protocol: ${new URL(url).protocol}` &&
|
|
1627
|
+
error.reason === "disallowed";
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
async function withFetchStub(
|
|
1631
|
+
respond: (url: string) => Response,
|
|
1632
|
+
callback: (fetched: string[]) => Promise<void>,
|
|
1633
|
+
): Promise<void> {
|
|
1634
|
+
const fetched: string[] = [];
|
|
1635
|
+
const originalFetch = globalThis.fetch;
|
|
1636
|
+
globalThis.fetch = (input: RequestInfo | URL) => {
|
|
1637
|
+
const url = input instanceof Request ? input.url : String(input);
|
|
1638
|
+
fetched.push(url);
|
|
1639
|
+
return Promise.resolve(respond(url));
|
|
1640
|
+
};
|
|
1641
|
+
try {
|
|
1642
|
+
await callback(fetched);
|
|
1643
|
+
} finally {
|
|
1644
|
+
globalThis.fetch = originalFetch;
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
for (const url of unsupportedUrls) {
|
|
1649
|
+
const scheme = new URL(url).protocol;
|
|
1650
|
+
|
|
1651
|
+
test(`getDocumentLoader() rejects ${scheme} URLs with private addresses allowed before fetching`, async () => {
|
|
1652
|
+
await withFetchStub(() => Response.json({}), async (fetched) => {
|
|
1653
|
+
await rejects(
|
|
1654
|
+
getDocumentLoader({ allowPrivateAddress: true })(url),
|
|
1655
|
+
(e) => isUnsupportedProtocolError(e, url),
|
|
1656
|
+
);
|
|
1657
|
+
deepStrictEqual(fetched, []);
|
|
1658
|
+
});
|
|
1659
|
+
});
|
|
1660
|
+
|
|
1661
|
+
test(`getDocumentLoader() rejects redirects to ${scheme} URLs with private addresses allowed`, async () => {
|
|
1662
|
+
const start = "https://example.com/redirect-to-unsupported";
|
|
1663
|
+
await withFetchStub(() => Response.redirect(url, 302), async (fetched) => {
|
|
1664
|
+
await rejects(
|
|
1665
|
+
getDocumentLoader({ allowPrivateAddress: true })(start),
|
|
1666
|
+
(e) => isUnsupportedProtocolError(e, url),
|
|
1667
|
+
);
|
|
1668
|
+
deepStrictEqual(fetched, [start]);
|
|
1669
|
+
});
|
|
1670
|
+
});
|
|
1671
|
+
|
|
1672
|
+
for (const html of [false, true]) {
|
|
1673
|
+
test(
|
|
1674
|
+
`getDocumentLoader() rejects ${
|
|
1675
|
+
html ? "HTML" : "Link header"
|
|
1676
|
+
} alternates to ${scheme} URLs with private addresses allowed`,
|
|
1677
|
+
async () => {
|
|
1678
|
+
const start = "https://example.com/alternate-to-unsupported";
|
|
1679
|
+
await withFetchStub(
|
|
1680
|
+
() =>
|
|
1681
|
+
html
|
|
1682
|
+
? new Response(
|
|
1683
|
+
`<link rel="alternate" type="application/activity+json" href="${url}">`,
|
|
1684
|
+
{ headers: { "Content-Type": "text/html" } },
|
|
1685
|
+
)
|
|
1686
|
+
: new Response("", {
|
|
1687
|
+
headers: {
|
|
1688
|
+
"Content-Type": "text/plain",
|
|
1689
|
+
Link:
|
|
1690
|
+
`<${url}>; rel="alternate"; type="application/activity+json"`,
|
|
1691
|
+
},
|
|
1692
|
+
}),
|
|
1693
|
+
async (fetched) => {
|
|
1694
|
+
await rejects(
|
|
1695
|
+
getDocumentLoader({ allowPrivateAddress: true })(start),
|
|
1696
|
+
(e) => isUnsupportedProtocolError(e, url),
|
|
1697
|
+
);
|
|
1698
|
+
deepStrictEqual(fetched, [start]);
|
|
1699
|
+
},
|
|
1700
|
+
);
|
|
1701
|
+
},
|
|
1702
|
+
);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
package/src/docloader.ts
CHANGED
|
@@ -557,7 +557,11 @@ export function getDocumentLoader(
|
|
|
557
557
|
visited = new Set<string>(),
|
|
558
558
|
): Promise<RemoteDocument> {
|
|
559
559
|
options?.signal?.throwIfAborted();
|
|
560
|
-
const
|
|
560
|
+
const parsedUrl = new URL(url);
|
|
561
|
+
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
|
|
562
|
+
throw new UrlError(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
563
|
+
}
|
|
564
|
+
const currentUrl = parsedUrl.href;
|
|
561
565
|
if (!skipPreloadedContexts && currentUrl in preloadedContexts) {
|
|
562
566
|
logger.debug("Using preloaded context: {url}.", { url: currentUrl });
|
|
563
567
|
return {
|