@fedify/fedify 2.3.15-dev.2482 → 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/dist/{builder-CocMrVkL.mjs → builder-B6vSXYxn.mjs} +2 -2
- package/dist/{client-CAM_bQXx.d.cts → client-BIBzqEIp.d.cts} +0 -1
- package/dist/{client-1He2YuBF.mjs → client-DpUNYKla.mjs} +113 -64
- package/dist/{client-CSddvgWN.d.ts → client-jE7oGvRh.d.ts} +0 -1
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{context-MOrCC7yl.d.cts → context-CE_Tj_Oc.d.cts} +28 -2
- package/dist/{context-BWbdE_MZ.d.ts → context-H_5tZXg-.d.ts} +28 -2
- package/dist/{deno-po8iekMB.mjs → deno-BCuL3mid.mjs} +1 -1
- package/dist/docloader-D2dr1_6B.mjs +125 -0
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/handler.test.mjs +5 -5
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/inbox.test.mjs +1 -1
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +390 -29
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +1 -1
- package/dist/federation/send.test.mjs +498 -88
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +1 -1
- package/dist/{http-Cdu8BGtv.js → http-BkjxY3U0.js} +172 -103
- package/dist/{http-BNCLeQJ-.mjs → http-CSDcThvz.mjs} +196 -98
- package/dist/{http-DQmNpfym.d.ts → http-CZPYFK3b.d.cts} +1 -2
- package/dist/{http-DiWQB8Mr.d.cts → http-DmP0sr2l.d.ts} +1 -2
- package/dist/{http-WcSdFbt1.cjs → http-gOkAiIe1.cjs} +173 -104
- package/dist/{inbox-g1sd_Vjn.mjs → inbox-BHxez4d5.mjs} +2 -2
- package/dist/{key-BR2TRTXR.mjs → key-D8IMQ72M.mjs} +2 -2
- package/dist/{kv-cache-Bw_gduSm.cjs → kv-cache-Alm5UmJa.cjs} +59 -17
- package/dist/{kv-cache-8SigUtvX.mjs → kv-cache-Blr9nDDp.mjs} +1 -1
- package/dist/{kv-cache-C0AqpjoS.js → kv-cache-CkXgU-ak.js} +60 -18
- package/dist/{ld-CSNsWdYE.mjs → ld-CVxxE1Pp.mjs} +3 -3
- package/dist/{metrics-BS7YzLVA.mjs → metrics-SYIZHFf_.mjs} +1 -1
- package/dist/{middleware-D-SL8Bkj.cjs → middleware-4yPyyoF5.cjs} +236 -98
- package/dist/{middleware-B1RRLN7m.mjs → middleware-CfskJGfV.mjs} +80 -40
- package/dist/{middleware-Dlo7NnZl.mjs → middleware-D3JWfiCu.mjs} +1 -1
- package/dist/{middleware-WL-JfDiK.js → middleware-DhN7c65B.js} +237 -99
- package/dist/{mod-LmD03uRA.d.ts → mod-CDFFESfL.d.ts} +1 -1
- package/dist/{mod-Bid79LFU.d.cts → mod-C_gFmeNq.d.cts} +1 -1
- package/dist/{mod-Co1M3Ux0.d.cts → mod-DDVkmZ_h.d.cts} +2 -8
- package/dist/{mod-B6PwkUMU.d.cts → mod-DDjtbkZO.d.cts} +1 -1
- package/dist/{mod-Br8yJNcE.d.ts → mod-DMjhnFbg.d.ts} +2 -8
- package/dist/{mod-TLEvgT1i.d.ts → mod-HQXFvOHs.d.ts} +1 -1
- package/dist/mod.cjs +5 -5
- package/dist/mod.d.cts +6 -6
- package/dist/mod.d.ts +6 -6
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/client.test.mjs +337 -19
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/nodeinfo/mod.cjs +1 -1
- package/dist/nodeinfo/mod.d.cts +1 -1
- package/dist/nodeinfo/mod.d.ts +1 -1
- package/dist/nodeinfo/mod.js +1 -1
- package/dist/otel/exporter.test.mjs +292 -30
- package/dist/otel/mod.cjs +36 -30
- package/dist/otel/mod.d.cts +13 -0
- package/dist/otel/mod.d.ts +13 -0
- package/dist/otel/mod.js +36 -30
- package/dist/{owner-DeggvxcG.mjs → owner-BluLVPf0.mjs} +2 -2
- package/dist/{proof-teNNYmFh.cjs → proof-CR-HwI0l.cjs} +1 -1
- package/dist/{proof-DMcUrrp8.mjs → proof-Co6nQBVR.mjs} +3 -3
- package/dist/{proof-v-IzWx7x.js → proof-Dg0d9QBo.js} +1 -1
- package/dist/{send-BsthcvPG.mjs → send-D_DnqOFA.mjs} +171 -73
- package/dist/sig/http.test.mjs +528 -2
- package/dist/sig/key.test.mjs +2 -2
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.d.cts +2 -2
- package/dist/sig/mod.d.ts +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/proof.test.mjs +1 -1
- package/dist/{temporal-Cji8Y8eQ.mjs → temporal-B8FUNkXB.mjs} +1 -1
- package/dist/testing/mod.d.mts +26 -0
- package/dist/{types-miAYfiGO.js → types-B1_pRFE_.js} +112 -63
- package/dist/{types-DRPjmHVV.cjs → types-DOvyymM4.cjs} +111 -62
- package/dist/utils/docloader.test.mjs +318 -34
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.d.cts +1 -1
- package/dist/utils/mod.d.ts +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +8 -8
- package/dist/docloader-BVj35vgR.mjs +0 -83
|
@@ -2,10 +2,10 @@ const { Temporal } = require("@js-temporal/polyfill");
|
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
const require_chunk = require("./chunk-DDcVe30Y.cjs");
|
|
4
4
|
const require_transformers = require("./transformers-NeAONrAq.cjs");
|
|
5
|
-
const require_http = require("./http-
|
|
6
|
-
const require_types = require("./types-
|
|
7
|
-
const require_proof = require("./proof-
|
|
8
|
-
const require_kv_cache = require("./kv-cache-
|
|
5
|
+
const require_http = require("./http-gOkAiIe1.cjs");
|
|
6
|
+
const require_types = require("./types-DOvyymM4.cjs");
|
|
7
|
+
const require_proof = require("./proof-CR-HwI0l.cjs");
|
|
8
|
+
const require_kv_cache = require("./kv-cache-Alm5UmJa.cjs");
|
|
9
9
|
let _logtape_logtape = require("@logtape/logtape");
|
|
10
10
|
let _fedify_uri_template = require("@fedify/uri-template");
|
|
11
11
|
let _fedify_vocab = require("@fedify/vocab");
|
|
@@ -17,6 +17,7 @@ let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conve
|
|
|
17
17
|
let _fedify_vocab_runtime_jsonld = require("@fedify/vocab-runtime/jsonld");
|
|
18
18
|
_fedify_vocab_runtime_jsonld = require_chunk.__toESM(_fedify_vocab_runtime_jsonld, 1);
|
|
19
19
|
let _fedify_webfinger = require("@fedify/webfinger");
|
|
20
|
+
let _fedify_vocab_runtime_internal = require("@fedify/vocab-runtime/internal");
|
|
20
21
|
let _opentelemetry_sdk_metrics = require("@opentelemetry/sdk-metrics");
|
|
21
22
|
let node_url = require("node:url");
|
|
22
23
|
//#region src/federation/activity-listener.ts
|
|
@@ -3423,9 +3424,10 @@ function extractInboxes({ recipients, preferSharedInbox, excludeBaseUris }) {
|
|
|
3423
3424
|
*
|
|
3424
3425
|
* @param parameters The parameters for sending the activity.
|
|
3425
3426
|
* See also {@link SendActivityParameters}.
|
|
3427
|
+
* @param deps The dependencies, for tests.
|
|
3426
3428
|
* @throws {Error} If the activity fails to send.
|
|
3427
3429
|
*/
|
|
3428
|
-
function sendActivity(options) {
|
|
3430
|
+
function sendActivity(options, deps = {}) {
|
|
3429
3431
|
const tracerProvider = options.tracerProvider ?? _opentelemetry_api.trace.getTracerProvider();
|
|
3430
3432
|
return tracerProvider.getTracer(require_http.name, require_http.version).startActiveSpan("activitypub.send_activity", {
|
|
3431
3433
|
kind: _opentelemetry_api.SpanKind.CLIENT,
|
|
@@ -3437,7 +3439,7 @@ function sendActivity(options) {
|
|
|
3437
3439
|
await sendActivityInternal({
|
|
3438
3440
|
...options,
|
|
3439
3441
|
tracerProvider
|
|
3440
|
-
}, span);
|
|
3442
|
+
}, span, deps);
|
|
3441
3443
|
} catch (e) {
|
|
3442
3444
|
span.setStatus({
|
|
3443
3445
|
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
@@ -3490,13 +3492,14 @@ async function readLimitedResponseBody(response, maxBytes) {
|
|
|
3490
3492
|
totalBytes += value.length;
|
|
3491
3493
|
}
|
|
3492
3494
|
} finally {
|
|
3495
|
+
if (truncated) reader.cancel().catch(() => {});
|
|
3493
3496
|
reader.releaseLock();
|
|
3494
3497
|
}
|
|
3495
3498
|
let result = chunks.join("");
|
|
3496
3499
|
if (truncated) result += "… (truncated)";
|
|
3497
3500
|
return result;
|
|
3498
3501
|
}
|
|
3499
|
-
async function sendActivityInternal({ activity, activityId, activityType, keys, inbox, allowPrivateAddress, headers, specDeterminer, meterProvider, tracerProvider }, span) {
|
|
3502
|
+
async function sendActivityInternal({ activity, activityId, activityType, keys, inbox, allowPrivateAddress, headers, specDeterminer, meterProvider, tracerProvider }, span, deps) {
|
|
3500
3503
|
const logger = (0, _logtape_logtape.getLogger)([
|
|
3501
3504
|
"fedify",
|
|
3502
3505
|
"federation",
|
|
@@ -3505,9 +3508,11 @@ async function sendActivityInternal({ activity, activityId, activityType, keys,
|
|
|
3505
3508
|
const federationMetrics = require_http.getFederationMetrics(meterProvider);
|
|
3506
3509
|
const started = performance.now();
|
|
3507
3510
|
let deliverySuccess = false;
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
+
const openUnvalidatedHop = deps.openHop ?? (allowPrivateAddress ? _fedify_vocab_runtime_internal.openDirectFetch : (url) => (0, _fedify_vocab_runtime_internal.openPublicFetch)(url));
|
|
3512
|
+
async function openHop(url) {
|
|
3513
|
+
let session;
|
|
3514
|
+
try {
|
|
3515
|
+
session = await openUnvalidatedHop(url);
|
|
3511
3516
|
} catch (error) {
|
|
3512
3517
|
if (error instanceof _fedify_vocab_runtime.UrlError && error.reason === "dns") {
|
|
3513
3518
|
logger.error("DNS resolution failed for URL: {url}", {
|
|
@@ -3524,78 +3529,86 @@ async function sendActivityInternal({ activity, activityId, activityType, keys,
|
|
|
3524
3529
|
});
|
|
3525
3530
|
throw error;
|
|
3526
3531
|
}
|
|
3532
|
+
return session;
|
|
3527
3533
|
}
|
|
3534
|
+
let initialSession;
|
|
3528
3535
|
try {
|
|
3529
|
-
await
|
|
3536
|
+
initialSession = await openHop(inbox.href);
|
|
3530
3537
|
} catch (error) {
|
|
3531
3538
|
if (error instanceof _fedify_vocab_runtime.FetchError) federationMetrics.recordDelivery(inbox, require_http.getDurationMs(started), false, activityType);
|
|
3532
3539
|
throw error;
|
|
3533
3540
|
}
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
}
|
|
3542
|
-
let rsaKey = null;
|
|
3543
|
-
for (const key of keys) if (key.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5") {
|
|
3544
|
-
rsaKey = key;
|
|
3545
|
-
break;
|
|
3546
|
-
}
|
|
3547
|
-
if (rsaKey == null) logger.warn("No supported key found to sign the request to {inbox}. The request will be sent without a signature. In order to sign the request, at least one RSASSA-PKCS1-v1_5 key must be provided.", {
|
|
3548
|
-
inbox: inbox.href,
|
|
3549
|
-
keys: keys.map((pair) => ({
|
|
3550
|
-
keyId: pair.keyId.href,
|
|
3551
|
-
privateKey: pair.privateKey
|
|
3552
|
-
}))
|
|
3553
|
-
});
|
|
3554
|
-
let response;
|
|
3541
|
+
let initialPending = true;
|
|
3542
|
+
const openDeliveryHop = (url) => {
|
|
3543
|
+
if (initialPending) {
|
|
3544
|
+
initialPending = false;
|
|
3545
|
+
return Promise.resolve(initialSession);
|
|
3546
|
+
}
|
|
3547
|
+
return openHop(url);
|
|
3548
|
+
};
|
|
3555
3549
|
try {
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3550
|
+
headers = new Headers(headers);
|
|
3551
|
+
headers.set("Content-Type", "application/activity+json");
|
|
3552
|
+
const request = new Request(inbox, {
|
|
3553
|
+
method: "POST",
|
|
3554
|
+
headers,
|
|
3555
|
+
body: JSON.stringify(activity),
|
|
3556
|
+
redirect: "manual"
|
|
3560
3557
|
});
|
|
3561
|
-
|
|
3562
|
-
const
|
|
3563
|
-
|
|
3564
|
-
|
|
3558
|
+
let rsaKey = null;
|
|
3559
|
+
for (const key of keys) if (key.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5") {
|
|
3560
|
+
rsaKey = key;
|
|
3561
|
+
break;
|
|
3562
|
+
}
|
|
3563
|
+
if (rsaKey == null) logger.warn("No supported key found to sign the request to {inbox}. The request will be sent without a signature. In order to sign the request, at least one RSASSA-PKCS1-v1_5 key must be provided.", {
|
|
3565
3564
|
inbox: inbox.href,
|
|
3566
|
-
|
|
3565
|
+
keys: keys.map((pair) => ({
|
|
3566
|
+
keyId: pair.keyId.href,
|
|
3567
|
+
privateKey: pair.privateKey
|
|
3568
|
+
}))
|
|
3567
3569
|
});
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
}
|
|
3577
|
-
error = "";
|
|
3578
|
-
}
|
|
3579
|
-
logger.error("Failed to send activity {activityId} to {inbox} ({status} {statusText}):\n{error}", {
|
|
3570
|
+
let outcome;
|
|
3571
|
+
try {
|
|
3572
|
+
outcome = rsaKey == null ? await fetchWithValidatedRedirects(request, openDeliveryHop, (response) => consumeSendActivityResponse(response, inbox)) : await require_http.doubleKnockScoped(request, rsaKey, {
|
|
3573
|
+
tracerProvider,
|
|
3574
|
+
specDeterminer
|
|
3575
|
+
}, openDeliveryHop, (response) => consumeSendActivityResponse(response, inbox));
|
|
3576
|
+
} catch (error) {
|
|
3577
|
+
const failure = error instanceof _fedify_vocab_runtime.FetchError || error instanceof _fedify_vocab_runtime.UrlError ? error : createFetchError(inbox.href, error);
|
|
3578
|
+
logger.error("Failed to send activity {activityId} to {inbox}:\n{error}", {
|
|
3580
3579
|
activityId,
|
|
3581
3580
|
inbox: inbox.href,
|
|
3582
|
-
|
|
3583
|
-
statusText: response.statusText,
|
|
3584
|
-
error
|
|
3581
|
+
error: failure
|
|
3585
3582
|
});
|
|
3586
|
-
|
|
3583
|
+
federationMetrics.recordDelivery(inbox, require_http.getDurationMs(started), false, activityType);
|
|
3584
|
+
throw failure;
|
|
3585
|
+
}
|
|
3586
|
+
try {
|
|
3587
|
+
if (!outcome.ok) {
|
|
3588
|
+
const { status, statusText, error, responseHeaders } = outcome;
|
|
3589
|
+
logger.error("Failed to send activity {activityId} to {inbox} ({status} {statusText}):\n{error}", {
|
|
3590
|
+
activityId,
|
|
3591
|
+
inbox: inbox.href,
|
|
3592
|
+
status,
|
|
3593
|
+
statusText,
|
|
3594
|
+
error
|
|
3595
|
+
});
|
|
3596
|
+
throw new SendActivityError(inbox, status, `Failed to send activity ${activityId} to ${inbox.href} (${status} ${statusText}):\n${error}`, error, responseHeaders);
|
|
3597
|
+
}
|
|
3598
|
+
deliverySuccess = true;
|
|
3599
|
+
const eventAttributes = {
|
|
3600
|
+
"activitypub.inbox.url": inbox.href,
|
|
3601
|
+
"activitypub.activity.id": activityId ?? ""
|
|
3602
|
+
};
|
|
3603
|
+
if (activityType != null) eventAttributes["activitypub.activity.type"] = activityType;
|
|
3604
|
+
const actorId = getActivityActorId(activity);
|
|
3605
|
+
if (actorId != null) eventAttributes["activitypub.actor.id"] = actorId;
|
|
3606
|
+
span.addEvent("activitypub.activity.sent", eventAttributes);
|
|
3607
|
+
} finally {
|
|
3608
|
+
federationMetrics.recordDelivery(inbox, require_http.getDurationMs(started), deliverySuccess, activityType);
|
|
3587
3609
|
}
|
|
3588
|
-
deliverySuccess = true;
|
|
3589
|
-
const eventAttributes = {
|
|
3590
|
-
"activitypub.inbox.url": inbox.href,
|
|
3591
|
-
"activitypub.activity.id": activityId ?? ""
|
|
3592
|
-
};
|
|
3593
|
-
if (activityType != null) eventAttributes["activitypub.activity.type"] = activityType;
|
|
3594
|
-
const actorId = getActivityActorId(activity);
|
|
3595
|
-
if (actorId != null) eventAttributes["activitypub.actor.id"] = actorId;
|
|
3596
|
-
span.addEvent("activitypub.activity.sent", eventAttributes);
|
|
3597
3610
|
} finally {
|
|
3598
|
-
|
|
3611
|
+
if (initialPending) await initialSession.close();
|
|
3599
3612
|
}
|
|
3600
3613
|
}
|
|
3601
3614
|
function createFetchError(url, cause) {
|
|
@@ -3603,10 +3616,75 @@ function createFetchError(url, cause) {
|
|
|
3603
3616
|
error.cause = cause;
|
|
3604
3617
|
return error;
|
|
3605
3618
|
}
|
|
3606
|
-
|
|
3619
|
+
/**
|
|
3620
|
+
* Starts cancelling the body of a response without waiting for it to settle.
|
|
3621
|
+
* The cancellation of a branch of a tee (e.g., a body cloned by a fetch mock)
|
|
3622
|
+
* settles only after the other branch is cancelled too, per the Streams
|
|
3623
|
+
* standard, so awaiting it could block forever. Failures are only logged.
|
|
3624
|
+
*/
|
|
3625
|
+
function cancelResponseBody(response, url) {
|
|
3626
|
+
response.body?.cancel().catch((error) => {
|
|
3627
|
+
(0, _logtape_logtape.getLogger)([
|
|
3628
|
+
"fedify",
|
|
3629
|
+
"federation",
|
|
3630
|
+
"outbox"
|
|
3631
|
+
]).debug("Failed to cancel the response body from {url}: {error}", {
|
|
3632
|
+
url,
|
|
3633
|
+
error
|
|
3634
|
+
});
|
|
3635
|
+
});
|
|
3636
|
+
}
|
|
3637
|
+
/**
|
|
3638
|
+
* Reads what is needed from the final response of a delivery while its
|
|
3639
|
+
* session is open: the body of a successful response is cancelled, and at
|
|
3640
|
+
* most 1 KiB of an error response body is read.
|
|
3641
|
+
*/
|
|
3642
|
+
async function consumeSendActivityResponse(response, inbox) {
|
|
3643
|
+
if (response.ok) {
|
|
3644
|
+
cancelResponseBody(response, response.url || inbox.href);
|
|
3645
|
+
return { ok: true };
|
|
3646
|
+
}
|
|
3647
|
+
let error;
|
|
3648
|
+
try {
|
|
3649
|
+
error = await readLimitedResponseBody(response, MAX_ERROR_RESPONSE_BODY_BYTES);
|
|
3650
|
+
} catch (_) {
|
|
3651
|
+
error = "";
|
|
3652
|
+
}
|
|
3653
|
+
return {
|
|
3654
|
+
ok: false,
|
|
3655
|
+
status: response.status,
|
|
3656
|
+
statusText: response.statusText,
|
|
3657
|
+
error,
|
|
3658
|
+
responseHeaders: new Headers(response.headers)
|
|
3659
|
+
};
|
|
3660
|
+
}
|
|
3661
|
+
/**
|
|
3662
|
+
* Sends a request without signing it, following redirects manually like the
|
|
3663
|
+
* Fetch standard does. Every hop is opened with `openHop()`, which validates
|
|
3664
|
+
* the destination, after the previous hop is closed. The final response is
|
|
3665
|
+
* passed to `consume()`, and its session is closed after that.
|
|
3666
|
+
* This is exported only for tests; it is not exported from any entry point.
|
|
3667
|
+
* @param request The request to send.
|
|
3668
|
+
* @param openHop The function to open a session for each hop.
|
|
3669
|
+
* @param consume The function to consume the final response.
|
|
3670
|
+
* @returns The value returned by `consume`.
|
|
3671
|
+
*/
|
|
3672
|
+
async function fetchWithValidatedRedirects(request, openHop, consume) {
|
|
3673
|
+
const logger = (0, _logtape_logtape.getLogger)([
|
|
3674
|
+
"fedify",
|
|
3675
|
+
"federation",
|
|
3676
|
+
"outbox"
|
|
3677
|
+
]);
|
|
3607
3678
|
let body = await request.clone().text();
|
|
3608
3679
|
for (let redirects = 0;; redirects++) {
|
|
3609
|
-
const
|
|
3680
|
+
const session = await openHop(request.url);
|
|
3681
|
+
let response;
|
|
3682
|
+
try {
|
|
3683
|
+
response = await session.fetch(request, { redirect: "manual" });
|
|
3684
|
+
} catch (error) {
|
|
3685
|
+
await closeAfterError(session, logger);
|
|
3686
|
+
throw error;
|
|
3687
|
+
}
|
|
3610
3688
|
const location = response.headers.get("Location");
|
|
3611
3689
|
if (![
|
|
3612
3690
|
301,
|
|
@@ -3614,11 +3692,21 @@ async function fetchWithValidatedRedirects(request, validateUrl) {
|
|
|
3614
3692
|
303,
|
|
3615
3693
|
307,
|
|
3616
3694
|
308
|
|
3617
|
-
].includes(response.status) || location == null)
|
|
3618
|
-
|
|
3695
|
+
].includes(response.status) || location == null) try {
|
|
3696
|
+
return await consume(response);
|
|
3697
|
+
} catch (error) {
|
|
3698
|
+
logger.debug("Failed to consume the response from {url}; closing the session: {error}", {
|
|
3699
|
+
url: request.url,
|
|
3700
|
+
error
|
|
3701
|
+
});
|
|
3702
|
+
throw error;
|
|
3703
|
+
} finally {
|
|
3704
|
+
await session.close();
|
|
3705
|
+
}
|
|
3706
|
+
cancelResponseBody(response, request.url);
|
|
3707
|
+
await session.close();
|
|
3619
3708
|
if (redirects >= 20) throw new TypeError("Too many redirects");
|
|
3620
3709
|
const url = new URL(location, request.url);
|
|
3621
|
-
await validateUrl(url.href);
|
|
3622
3710
|
const headers = new Headers(request.headers);
|
|
3623
3711
|
if (url.origin !== new URL(request.url).origin) {
|
|
3624
3712
|
headers.delete("Authorization");
|
|
@@ -3646,6 +3734,16 @@ async function fetchWithValidatedRedirects(request, validateUrl) {
|
|
|
3646
3734
|
});
|
|
3647
3735
|
}
|
|
3648
3736
|
}
|
|
3737
|
+
async function closeAfterError(session, logger) {
|
|
3738
|
+
try {
|
|
3739
|
+
await session.close();
|
|
3740
|
+
} catch (error) {
|
|
3741
|
+
logger.debug("Failed to close the session for {url}: {error}", {
|
|
3742
|
+
url: session.url.href,
|
|
3743
|
+
error
|
|
3744
|
+
});
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3649
3747
|
/**
|
|
3650
3748
|
* An error that is thrown when an activity fails to send to a remote inbox.
|
|
3651
3749
|
* It contains structured information about the failure, including the HTTP
|
|
@@ -6497,44 +6595,84 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
6497
6595
|
}
|
|
6498
6596
|
}), values);
|
|
6499
6597
|
}
|
|
6500
|
-
#signedKey =
|
|
6598
|
+
#signedKey = null;
|
|
6599
|
+
#signedKeyOwner = null;
|
|
6600
|
+
#signatureChecks = /* @__PURE__ */ new WeakMap();
|
|
6601
|
+
#getSignatureCheck(documentLoader, contextLoader) {
|
|
6602
|
+
let checks = this.#signatureChecks.get(documentLoader);
|
|
6603
|
+
if (checks == null) {
|
|
6604
|
+
checks = /* @__PURE__ */ new WeakMap();
|
|
6605
|
+
this.#signatureChecks.set(documentLoader, checks);
|
|
6606
|
+
}
|
|
6607
|
+
let check = checks.get(contextLoader);
|
|
6608
|
+
if (check == null) {
|
|
6609
|
+
check = {};
|
|
6610
|
+
checks.set(contextLoader, check);
|
|
6611
|
+
}
|
|
6612
|
+
return check;
|
|
6613
|
+
}
|
|
6501
6614
|
async getSignedKey(options = {}) {
|
|
6502
6615
|
if (this.#signedKey != null) return this.#signedKey;
|
|
6503
|
-
|
|
6616
|
+
const documentLoader = options.documentLoader ?? this.documentLoader;
|
|
6617
|
+
const contextLoader = options.contextLoader ?? this.contextLoader;
|
|
6618
|
+
const check = this.#getSignatureCheck(documentLoader, contextLoader);
|
|
6619
|
+
if (check.key != null) return check.key;
|
|
6620
|
+
const promise = require_http.verifyRequest(this.request, {
|
|
6504
6621
|
...this,
|
|
6505
|
-
contextLoader
|
|
6506
|
-
documentLoader
|
|
6622
|
+
contextLoader,
|
|
6623
|
+
documentLoader,
|
|
6507
6624
|
timeWindow: this.federation.signatureTimeWindow,
|
|
6508
6625
|
meterProvider: this.meterProvider,
|
|
6509
6626
|
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
6627
|
+
}).then((key) => {
|
|
6628
|
+
if (key != null) this.#signedKey ??= key;
|
|
6629
|
+
return key;
|
|
6630
|
+
}).catch((error) => {
|
|
6631
|
+
if (check.key === promise) check.key = void 0;
|
|
6632
|
+
throw error;
|
|
6510
6633
|
});
|
|
6634
|
+
check.key = promise;
|
|
6635
|
+
return await promise;
|
|
6511
6636
|
}
|
|
6512
|
-
#signedKeyOwner = void 0;
|
|
6513
6637
|
async getSignedKeyOwner(options = {}) {
|
|
6514
6638
|
if (this.#signedKeyOwner != null) return this.#signedKeyOwner;
|
|
6515
|
-
const
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
"fedify",
|
|
6527
|
-
"federation",
|
|
6528
|
-
"actor"
|
|
6529
|
-
]).warn("Failed to fetch the key owner {keyOwner} of {keyId} while verifying the request signature; treating the request as unauthenticated: {error}", {
|
|
6530
|
-
keyId: key.id?.href,
|
|
6531
|
-
keyOwner: error.url.href,
|
|
6532
|
-
error
|
|
6533
|
-
});
|
|
6534
|
-
return this.#signedKeyOwner = null;
|
|
6639
|
+
const normalizedOptions = {
|
|
6640
|
+
documentLoader: options.documentLoader ?? this.documentLoader,
|
|
6641
|
+
contextLoader: options.contextLoader ?? this.contextLoader,
|
|
6642
|
+
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
6643
|
+
};
|
|
6644
|
+
const check = this.#getSignatureCheck(normalizedOptions.documentLoader, normalizedOptions.contextLoader);
|
|
6645
|
+
if (check.owner != null) return check.owner;
|
|
6646
|
+
const promise = this.getSignedKey(normalizedOptions).then(async (key) => {
|
|
6647
|
+
if (key == null) {
|
|
6648
|
+
if (check.owner === promise) check.owner = void 0;
|
|
6649
|
+
return null;
|
|
6535
6650
|
}
|
|
6651
|
+
try {
|
|
6652
|
+
const owner = await require_proof.getKeyOwner(key, normalizedOptions);
|
|
6653
|
+
if (owner != null) this.#signedKeyOwner ??= owner;
|
|
6654
|
+
return owner;
|
|
6655
|
+
} catch (error) {
|
|
6656
|
+
if (error instanceof _fedify_vocab_runtime.FetchError) {
|
|
6657
|
+
(0, _logtape_logtape.getLogger)([
|
|
6658
|
+
"fedify",
|
|
6659
|
+
"federation",
|
|
6660
|
+
"actor"
|
|
6661
|
+
]).warn("Failed to fetch the key owner {keyOwner} of {keyId} while verifying the request signature; treating the request as unauthenticated: {error}", {
|
|
6662
|
+
keyId: key.id?.href,
|
|
6663
|
+
keyOwner: error.url.href,
|
|
6664
|
+
error
|
|
6665
|
+
});
|
|
6666
|
+
return null;
|
|
6667
|
+
}
|
|
6668
|
+
throw error;
|
|
6669
|
+
}
|
|
6670
|
+
}).catch((error) => {
|
|
6671
|
+
if (check.owner === promise) check.owner = void 0;
|
|
6536
6672
|
throw error;
|
|
6537
|
-
}
|
|
6673
|
+
});
|
|
6674
|
+
check.owner = promise;
|
|
6675
|
+
return await promise;
|
|
6538
6676
|
}
|
|
6539
6677
|
};
|
|
6540
6678
|
function forwardActivity(ctx, loggerCategory, forwarder, recipients, options) {
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics-
|
|
4
|
+
import { n as version, t as name } from "./deno-BCuL3mid.mjs";
|
|
5
|
+
import { a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics-SYIZHFf_.mjs";
|
|
6
6
|
import { t as formatAcceptSignature } from "./accept-Dd__NiUL.mjs";
|
|
7
|
-
import { o as importJwk, s as validateCryptoKey, t as exportJwk } from "./key-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { n as kvCache } from "./kv-cache-
|
|
7
|
+
import { o as importJwk, s as validateCryptoKey, t as exportJwk } from "./key-D8IMQ72M.mjs";
|
|
8
|
+
import { d as verifyRequestDetailed, s as parseRfc9421SignatureInput, u as verifyRequest } from "./http-CSDcThvz.mjs";
|
|
9
|
+
import { n as getAuthenticatedDocumentLoader } from "./docloader-D2dr1_6B.mjs";
|
|
10
|
+
import { n as kvCache } from "./kv-cache-Blr9nDDp.mjs";
|
|
11
11
|
import { t as KvKeyCache } from "./keycache-BimEQucx.mjs";
|
|
12
|
-
import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-
|
|
13
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-
|
|
12
|
+
import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-CVxxE1Pp.mjs";
|
|
13
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-BluLVPf0.mjs";
|
|
14
14
|
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-D4iTv7uM.mjs";
|
|
15
|
-
import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-
|
|
16
|
-
import { d as
|
|
15
|
+
import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-Co6nQBVR.mjs";
|
|
16
|
+
import { d as MAX_BODY_SIZE, f as readBoundedText, t as getNodeInfo, u as BodyTooLargeError } from "./client-DpUNYKla.mjs";
|
|
17
17
|
import { t as nodeInfoToJson } from "./types-J53Kw7so.mjs";
|
|
18
|
-
import {
|
|
19
|
-
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-
|
|
18
|
+
import { i as sendActivity, n as extractInboxes, t as SendActivityError } from "./send-D_DnqOFA.mjs";
|
|
19
|
+
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-B6vSXYxn.mjs";
|
|
20
20
|
import { t as CircuitBreaker } from "./circuit-breaker-D1fxthDI.mjs";
|
|
21
21
|
import { t as buildCollectionSynchronizationHeader } from "./collection-Cc3DVAhE.mjs";
|
|
22
|
-
import { n as routeActivity, t as actorsHaveSameOrigin } from "./inbox-
|
|
22
|
+
import { n as routeActivity, t as actorsHaveSameOrigin } from "./inbox-BHxez4d5.mjs";
|
|
23
23
|
import { t as acceptsJsonLd } from "./negotiation-DDstyBvc.mjs";
|
|
24
|
-
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-
|
|
24
|
+
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-B8FUNkXB.mjs";
|
|
25
25
|
import { t as createExponentialBackoffPolicy } from "./retry-CXg_MBI-.mjs";
|
|
26
26
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
27
27
|
import { RouterError } from "@fedify/uri-template";
|
|
@@ -4547,44 +4547,84 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
4547
4547
|
}
|
|
4548
4548
|
}), values);
|
|
4549
4549
|
}
|
|
4550
|
-
#signedKey =
|
|
4550
|
+
#signedKey = null;
|
|
4551
|
+
#signedKeyOwner = null;
|
|
4552
|
+
#signatureChecks = /* @__PURE__ */ new WeakMap();
|
|
4553
|
+
#getSignatureCheck(documentLoader, contextLoader) {
|
|
4554
|
+
let checks = this.#signatureChecks.get(documentLoader);
|
|
4555
|
+
if (checks == null) {
|
|
4556
|
+
checks = /* @__PURE__ */ new WeakMap();
|
|
4557
|
+
this.#signatureChecks.set(documentLoader, checks);
|
|
4558
|
+
}
|
|
4559
|
+
let check = checks.get(contextLoader);
|
|
4560
|
+
if (check == null) {
|
|
4561
|
+
check = {};
|
|
4562
|
+
checks.set(contextLoader, check);
|
|
4563
|
+
}
|
|
4564
|
+
return check;
|
|
4565
|
+
}
|
|
4551
4566
|
async getSignedKey(options = {}) {
|
|
4552
4567
|
if (this.#signedKey != null) return this.#signedKey;
|
|
4553
|
-
|
|
4568
|
+
const documentLoader = options.documentLoader ?? this.documentLoader;
|
|
4569
|
+
const contextLoader = options.contextLoader ?? this.contextLoader;
|
|
4570
|
+
const check = this.#getSignatureCheck(documentLoader, contextLoader);
|
|
4571
|
+
if (check.key != null) return check.key;
|
|
4572
|
+
const promise = verifyRequest(this.request, {
|
|
4554
4573
|
...this,
|
|
4555
|
-
contextLoader
|
|
4556
|
-
documentLoader
|
|
4574
|
+
contextLoader,
|
|
4575
|
+
documentLoader,
|
|
4557
4576
|
timeWindow: this.federation.signatureTimeWindow,
|
|
4558
4577
|
meterProvider: this.meterProvider,
|
|
4559
4578
|
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
4579
|
+
}).then((key) => {
|
|
4580
|
+
if (key != null) this.#signedKey ??= key;
|
|
4581
|
+
return key;
|
|
4582
|
+
}).catch((error) => {
|
|
4583
|
+
if (check.key === promise) check.key = void 0;
|
|
4584
|
+
throw error;
|
|
4560
4585
|
});
|
|
4586
|
+
check.key = promise;
|
|
4587
|
+
return await promise;
|
|
4561
4588
|
}
|
|
4562
|
-
#signedKeyOwner = void 0;
|
|
4563
4589
|
async getSignedKeyOwner(options = {}) {
|
|
4564
4590
|
if (this.#signedKeyOwner != null) return this.#signedKeyOwner;
|
|
4565
|
-
const
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
"fedify",
|
|
4577
|
-
"federation",
|
|
4578
|
-
"actor"
|
|
4579
|
-
]).warn("Failed to fetch the key owner {keyOwner} of {keyId} while verifying the request signature; treating the request as unauthenticated: {error}", {
|
|
4580
|
-
keyId: key.id?.href,
|
|
4581
|
-
keyOwner: error.url.href,
|
|
4582
|
-
error
|
|
4583
|
-
});
|
|
4584
|
-
return this.#signedKeyOwner = null;
|
|
4591
|
+
const normalizedOptions = {
|
|
4592
|
+
documentLoader: options.documentLoader ?? this.documentLoader,
|
|
4593
|
+
contextLoader: options.contextLoader ?? this.contextLoader,
|
|
4594
|
+
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
4595
|
+
};
|
|
4596
|
+
const check = this.#getSignatureCheck(normalizedOptions.documentLoader, normalizedOptions.contextLoader);
|
|
4597
|
+
if (check.owner != null) return check.owner;
|
|
4598
|
+
const promise = this.getSignedKey(normalizedOptions).then(async (key) => {
|
|
4599
|
+
if (key == null) {
|
|
4600
|
+
if (check.owner === promise) check.owner = void 0;
|
|
4601
|
+
return null;
|
|
4585
4602
|
}
|
|
4603
|
+
try {
|
|
4604
|
+
const owner = await getKeyOwner(key, normalizedOptions);
|
|
4605
|
+
if (owner != null) this.#signedKeyOwner ??= owner;
|
|
4606
|
+
return owner;
|
|
4607
|
+
} catch (error) {
|
|
4608
|
+
if (error instanceof FetchError) {
|
|
4609
|
+
getLogger([
|
|
4610
|
+
"fedify",
|
|
4611
|
+
"federation",
|
|
4612
|
+
"actor"
|
|
4613
|
+
]).warn("Failed to fetch the key owner {keyOwner} of {keyId} while verifying the request signature; treating the request as unauthenticated: {error}", {
|
|
4614
|
+
keyId: key.id?.href,
|
|
4615
|
+
keyOwner: error.url.href,
|
|
4616
|
+
error
|
|
4617
|
+
});
|
|
4618
|
+
return null;
|
|
4619
|
+
}
|
|
4620
|
+
throw error;
|
|
4621
|
+
}
|
|
4622
|
+
}).catch((error) => {
|
|
4623
|
+
if (check.owner === promise) check.owner = void 0;
|
|
4586
4624
|
throw error;
|
|
4587
|
-
}
|
|
4625
|
+
});
|
|
4626
|
+
check.owner = promise;
|
|
4627
|
+
return await promise;
|
|
4588
4628
|
}
|
|
4589
4629
|
};
|
|
4590
4630
|
function forwardActivity(ctx, loggerCategory, forwarder, recipients, options) {
|