@fedify/fedify 1.9.6 → 1.9.8
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/{actor-CEGEmRll.js → actor-BTA45fXF.js} +1205 -2768
- package/dist/{actor-Ydzhc8dj.d.cts → actor-Be-68iJP.d.cts} +3 -3
- package/dist/{actor-C1Euqngb.d.ts → actor-C5AY0Tno.d.ts} +3 -3
- package/dist/{actor-DbpZ6pzg.js → actor-DGa1EWaV.mjs} +8 -15
- package/dist/{actor-DlS-Q8hE.cjs → actor-DxfJk4lY.cjs} +3112 -4674
- package/dist/{assert-MZs1qjMx.js → assert-DikXweDx.mjs} +5 -9
- package/dist/{assert_equals-DSbWqCm3.js → assert_equals-Ew3jOFa3.mjs} +55 -69
- package/dist/{assert_instance_of-DHz7EHNU.js → assert_instance_of-C4Ri6VuN.mjs} +5 -9
- package/dist/{assert_is_error-BPGph1Jx.js → assert_is_error-C50x8tnw.mjs} +5 -9
- package/dist/{assert_not_equals-f3m3epl3.js → assert_not_equals--wG9hV7u.mjs} +6 -13
- package/dist/{assert_rejects-DiIiJbZn.js → assert_rejects-CJC9ThS-.mjs} +6 -11
- package/dist/{assert_throws-BOO88avQ.js → assert_throws-BIL7gChy.mjs} +6 -10
- package/dist/{authdocloader-DUQcOTRS.js → authdocloader-BC2rYCy1.mjs} +9 -14
- package/dist/{authdocloader-CT_V4Z7G.cjs → authdocloader-BrhFB421.cjs} +14 -22
- package/dist/{authdocloader-BLqMyboS.js → authdocloader-CqtNsX_N.js} +8 -15
- package/dist/{builder-BO61xeXE.js → builder-CIkAhIGC.mjs} +31 -40
- package/dist/{client-DF8anIB5.d.ts → client-D8OSiPBT.d.ts} +2 -2
- package/dist/{client-UG5wpNhG.js → client-MXqit6c-.mjs} +11 -15
- package/dist/{client-DjT_tegg.d.cts → client-T0VFOdMw.d.cts} +2 -2
- package/dist/{collection-CSzG2j1P.js → collection-BD6-SZ6O.mjs} +7 -12
- package/dist/compat/mod.cjs +5 -8
- package/dist/compat/mod.d.cts +78 -12
- package/dist/compat/mod.d.ts +78 -12
- package/dist/compat/mod.js +4 -8
- package/dist/compat/transformers.test.mjs +62 -0
- package/dist/{context-CwUAkopp.d.cts → context-CACMqDzl.d.cts} +33 -26
- package/dist/{context-CXUibY4L.d.ts → context-K4cCphQj.d.ts} +33 -26
- package/dist/{denokv-Bv33Xxea.js → denokv-CoSB_Eps.mjs} +22 -11
- package/dist/{docloader-BIFI3OS7.cjs → docloader-BVuUhBLI.cjs} +112 -212
- package/dist/{docloader-fJgJeqiX.js → docloader-BoXhusJ1.js} +17 -151
- package/dist/{docloader-CxWcuWqQ.d.ts → docloader-DSaLRXEA.d.ts} +2 -7
- package/dist/{docloader-D-MrRyHl.d.cts → docloader-DpGRDZrn.d.cts} +2 -7
- package/dist/{esm-C1EfGjSS.js → esm-BHJ7sdNg.mjs} +49 -85
- package/dist/federation/{builder.test.js → builder.test.mjs} +22 -41
- package/dist/federation/collection.test.d.mts +2 -0
- package/dist/federation/collection.test.mjs +21 -0
- package/dist/federation/handler.test.d.mts +2 -0
- package/dist/federation/{handler.test.js → handler.test.mjs} +22 -49
- package/dist/federation/idempotency.test.d.mts +2 -0
- package/dist/federation/{idempotency.test.js → idempotency.test.mjs} +29 -59
- package/dist/federation/inbox.test.d.mts +2 -0
- package/dist/federation/{inbox.test.js → inbox.test.mjs} +10 -15
- package/dist/federation/keycache.test.d.mts +2 -0
- package/dist/federation/{keycache.test.js → keycache.test.mjs} +13 -18
- package/dist/federation/kv.test.d.mts +2 -0
- package/dist/federation/{kv.test.js → kv.test.mjs} +9 -20
- package/dist/federation/middleware.test.d.mts +2 -0
- package/dist/federation/{middleware.test.js → middleware.test.mjs} +182 -197
- package/dist/federation/mod.cjs +223 -21
- package/dist/federation/mod.d.cts +4 -13
- package/dist/federation/mod.d.ts +4 -13
- package/dist/federation/mod.js +218 -18
- package/dist/federation/mq.test.d.mts +2 -0
- package/dist/federation/{mq.test.js → mq.test.mjs} +23 -38
- package/dist/federation/retry.test.d.mts +2 -0
- package/dist/federation/{retry.test.js → retry.test.mjs} +9 -14
- package/dist/federation/router.test.d.mts +2 -0
- package/dist/federation/{router.test.js → router.test.mjs} +12 -19
- package/dist/federation/send.test.d.mts +2 -0
- package/dist/federation/{send.test.js → send.test.mjs} +17 -26
- package/dist/{http-wsGR6KkT.d.ts → http-BZpls--H.d.ts} +5 -9
- package/dist/{http-CR-Eg1Uq.js → http-Bu5ZNlhZ.mjs} +16 -32
- package/dist/{http-B1_DzfAU.d.cts → http-C7WoprmE.d.cts} +5 -9
- package/dist/{http-BgopPF-8.cjs → http-DKw-O_VY.cjs} +51 -68
- package/dist/{http-05HxN-lp.js → http-VJbz6sKD.js} +17 -33
- package/dist/{inbox-DcJN1cxM.js → inbox-DkbTULXE.mjs} +17 -25
- package/dist/key-4fu6v0Jf.mjs +5 -0
- package/dist/{key-DjS1X9TG.cjs → key-B-wFdaPB.cjs} +42 -50
- package/dist/{key-ibMO03_0.js → key-BNMK_IVr.mjs} +12 -18
- package/dist/key-CancShOo.cjs +4 -0
- package/dist/{key-CPJcJjp-.js → key-DK3o0FEH.js} +19 -19
- package/dist/{keycache-CMUfqYqr.js → keycache-D-Vj8z88.mjs} +6 -10
- package/dist/{keys-IZ5050fT.js → keys-B27nVeIs.mjs} +6 -10
- package/dist/{kv-C7sopW2E.d.ts → kv-Bq9QLKm5.d.ts} +1 -1
- package/dist/{kv-CRZrzyXm.js → kv-DM1zFCtL.mjs} +6 -10
- package/dist/{kv-63Cil1MD.d.cts → kv-GIrOktyG.d.cts} +1 -1
- package/dist/{ld-DHNA2RSQ.js → ld-6jAVu3jV.mjs} +17 -31
- package/dist/{lookup-CKZfuyxA.js → lookup-BaU75j-d.js} +5 -11
- package/dist/{lookup-C4_dVYz7.cjs → lookup-BiIPmTwB.cjs} +16 -23
- package/dist/{lookup-BMAWLsP2.js → lookup-DmeJ8WUw.mjs} +8 -17
- package/dist/middleware-9ByEpBvV.cjs +4 -0
- package/dist/{middleware-CGbvIGvy.cjs → middleware-C188G4Go.cjs} +494 -547
- package/dist/{middleware-DrhEvfTo.js → middleware-Db1yZQaT.mjs} +276 -321
- package/dist/{middleware-ODfDRN3q.js → middleware-Do06X21v.js} +349 -393
- package/dist/middleware-DrfZEjyc.mjs +5 -0
- package/dist/{mod-CDObsV1d.d.ts → mod-BSwc3_rD.d.ts} +3 -3
- package/dist/{mod-DBzN0aCM.d.ts → mod-BTNpXcPj.d.ts} +2 -2
- package/dist/{mod-fjqfsrty.d.cts → mod-Chb_NKPp.d.cts} +4 -4
- package/dist/{mod-DgcYoyZK.d.ts → mod-DHoc3toL.d.ts} +4 -4
- package/dist/{mod-jQ4OODsl.d.cts → mod-DIMx6YjJ.d.cts} +2 -2
- package/dist/{mod-BUbqxBev.d.cts → mod-HElaq2UB.d.cts} +3 -3
- package/dist/mod.cjs +31 -33
- package/dist/mod.d.cts +15 -17
- package/dist/mod.d.ts +15 -17
- package/dist/mod.js +20 -23
- package/dist/{mq-B7R1Q-M5.d.cts → mq-CrItclRD.d.cts} +1 -1
- package/dist/{mq-CRGm1e_F.d.ts → mq-D_ZZRdby.d.ts} +1 -1
- package/dist/nodeinfo/client.test.d.mts +2 -0
- package/dist/nodeinfo/{client.test.js → client.test.mjs} +23 -45
- package/dist/nodeinfo/handler.test.d.mts +2 -0
- package/dist/nodeinfo/{handler.test.js → handler.test.mjs} +14 -43
- package/dist/nodeinfo/mod.cjs +5 -9
- package/dist/nodeinfo/mod.d.cts +2 -5
- package/dist/nodeinfo/mod.d.ts +2 -5
- package/dist/nodeinfo/mod.js +4 -9
- package/dist/nodeinfo/semver.test.d.mts +2 -0
- package/dist/nodeinfo/{semver.test.js → semver.test.mjs} +28 -51
- package/dist/nodeinfo/types.test.d.mts +2 -0
- package/dist/nodeinfo/{types.test.js → types.test.mjs} +10 -21
- package/dist/{owner-DDHsHYQO.js → owner-CKuGt_T9.mjs} +10 -13
- package/dist/{owner-BbeUDvOu.d.ts → owner-DPAPnB0R.d.ts} +4 -4
- package/dist/{owner-6KSEp9eV.d.cts → owner-_rFs0ik_.d.cts} +4 -4
- package/dist/{proof-V1uQaB2y.js → proof-CmTtG_t-.js} +33 -57
- package/dist/{proof-CX7ujFFX.cjs → proof-DLOy7HYU.cjs} +112 -135
- package/dist/{proof-exgGRW88.js → proof-mJLL2gSA.mjs} +20 -32
- package/dist/{retry-D4GJ670a.js → retry-Ddbq3AcK.mjs} +4 -7
- package/dist/rolldown-runtime-C7fyD9f2.js +15 -0
- package/dist/runtime/authdocloader.test.d.mts +2 -0
- package/dist/runtime/{authdocloader.test.js → authdocloader.test.mjs} +16 -28
- package/dist/runtime/docloader.test.d.mts +2 -0
- package/dist/runtime/{docloader.test.js → docloader.test.mjs} +52 -72
- package/dist/runtime/key.test.d.mts +2 -0
- package/dist/runtime/{key.test.js → key.test.mjs} +27 -57
- package/dist/runtime/langstr.test.d.mts +2 -0
- package/dist/runtime/{langstr.test.js → langstr.test.mjs} +9 -19
- package/dist/runtime/link.test.d.mts +2 -0
- package/dist/runtime/{link.test.js → link.test.mjs} +7 -11
- package/dist/runtime/mod.cjs +7 -13
- package/dist/runtime/mod.d.cts +103 -6
- package/dist/runtime/mod.d.ts +103 -6
- package/dist/runtime/mod.js +6 -13
- package/dist/runtime/multibase/multibase.test.d.mts +2 -0
- package/dist/runtime/multibase/{multibase.test.js → multibase.test.mjs} +16 -33
- package/dist/runtime/url.test.d.mts +2 -0
- package/dist/runtime/{url.test.js → url.test.mjs} +10 -15
- package/dist/{semver-dArNLkR9.js → semver-CgD82xxg.mjs} +13 -28
- package/dist/{send-BfMYakUE.js → send-BsQbGuw4.mjs} +7 -12
- package/dist/sig/http.test.d.mts +2 -0
- package/dist/sig/{http.test.js → http.test.mjs} +119 -203
- package/dist/sig/key.test.d.mts +2 -0
- package/dist/sig/{key.test.js → key.test.mjs} +13 -22
- package/dist/sig/ld.test.d.mts +2 -0
- package/dist/sig/{ld.test.js → ld.test.mjs} +24 -39
- package/dist/sig/mod.cjs +7 -13
- package/dist/sig/mod.d.cts +3 -7
- package/dist/sig/mod.d.ts +3 -7
- package/dist/sig/mod.js +6 -13
- package/dist/sig/owner.test.d.mts +2 -0
- package/dist/sig/owner.test.mjs +39 -0
- package/dist/sig/proof.test.d.mts +2 -0
- package/dist/sig/{proof.test.js → proof.test.mjs} +18 -31
- package/dist/{std__assert-X-_kMxKM.js → std__assert-2v7gYiZp.mjs} +13 -24
- package/dist/testing/docloader.test.d.mts +2 -0
- package/dist/testing/docloader.test.mjs +12 -0
- package/dist/testing/{mod.d.ts → mod.d.mts} +371 -541
- package/dist/testing/mod.mjs +5 -0
- package/dist/{testing-RPOc_gVG.js → testing-DS3gcq8V.mjs} +27 -35
- package/dist/{transformers-CoBS-oFG.cjs → transformers-BM0M8hnW.cjs} +20 -25
- package/dist/{transformers-BFT6d7J5.js → transformers-BV4OeK9o.js} +3 -7
- package/dist/{types-Cptev2nt.js → types-BXfL-dsX.js} +18 -36
- package/dist/{types-BIgY6c-l.js → types-CAnkAQGM.mjs} +5 -9
- package/dist/{types-CGnM1vft.cjs → types-DpM4FhjW.cjs} +45 -64
- package/dist/vocab/actor.test.d.mts +2 -0
- package/dist/vocab/{actor.test.js → actor.test.mjs} +308 -550
- package/dist/vocab/cjs.test.d.mts +2 -0
- package/dist/vocab/cjs.test.mjs +14 -0
- package/dist/vocab/lookup.test.d.mts +2 -0
- package/dist/vocab/{lookup.test.js → lookup.test.mjs} +29 -45
- package/dist/vocab/mod.cjs +251 -16
- package/dist/vocab/mod.d.cts +3 -5
- package/dist/vocab/mod.d.ts +3 -5
- package/dist/vocab/mod.js +244 -10
- package/dist/vocab/type.test.d.mts +2 -0
- package/dist/vocab/type.test.mjs +16 -0
- package/dist/vocab/vocab.test.d.mts +2 -0
- package/dist/vocab/{vocab.test.js → vocab.test.mjs} +178 -311
- package/dist/{vocab-CDHNj5zp.d.ts → vocab-BLvSEtuz.d.cts} +2 -4
- package/dist/{type-COPv6pMi.js → vocab-DuW9rL1h.mjs} +1177 -2871
- package/dist/{vocab-Cfs0937i.d.cts → vocab-lhCS9lzq.d.ts} +4 -2
- package/dist/webfinger/handler.test.d.mts +2 -0
- package/dist/webfinger/{handler.test.js → handler.test.mjs} +23 -56
- package/dist/webfinger/lookup.test.d.mts +2 -0
- package/dist/webfinger/{lookup.test.js → lookup.test.mjs} +13 -27
- package/dist/webfinger/mod.cjs +5 -9
- package/dist/webfinger/mod.d.cts +1 -3
- package/dist/webfinger/mod.d.ts +1 -3
- package/dist/webfinger/mod.js +4 -9
- package/dist/x/cfworkers.cjs +25 -14
- package/dist/x/cfworkers.d.cts +33 -6
- package/dist/x/cfworkers.d.ts +33 -6
- package/dist/x/cfworkers.js +22 -12
- package/dist/x/cfworkers.test.d.mts +2 -0
- package/dist/x/{cfworkers.test.js → cfworkers.test.mjs} +28 -26
- package/dist/x/hono.cjs +25 -14
- package/dist/x/hono.d.cts +1 -11
- package/dist/x/hono.d.ts +1 -11
- package/dist/x/hono.js +22 -12
- package/dist/x/sveltekit.cjs +23 -12
- package/dist/x/sveltekit.d.cts +1 -11
- package/dist/x/sveltekit.d.ts +1 -11
- package/dist/x/sveltekit.js +20 -10
- package/package.json +2 -2
- package/dist/chunk-DqRYRqnO.cjs +0 -34
- package/dist/compat/transformers.test.d.ts +0 -3
- package/dist/compat/transformers.test.js +0 -86
- package/dist/compat-DmDDELst.cjs +0 -4
- package/dist/compat-nxUqe4Z-.js +0 -4
- package/dist/federation/builder.test.d.ts +0 -3
- package/dist/federation/collection.test.d.ts +0 -3
- package/dist/federation/collection.test.js +0 -35
- package/dist/federation/handler.test.d.ts +0 -3
- package/dist/federation/idempotency.test.d.ts +0 -3
- package/dist/federation/inbox.test.d.ts +0 -3
- package/dist/federation/keycache.test.d.ts +0 -3
- package/dist/federation/kv.test.d.ts +0 -3
- package/dist/federation/middleware.test.d.ts +0 -3
- package/dist/federation/mq.test.d.ts +0 -3
- package/dist/federation/retry.test.d.ts +0 -3
- package/dist/federation/router.test.d.ts +0 -3
- package/dist/federation/send.test.d.ts +0 -3
- package/dist/federation-D1U8YY9t.js +0 -226
- package/dist/federation-H2_En3j5.cjs +0 -244
- package/dist/key-BCUd8FWp.js +0 -10
- package/dist/key-BUardnTH.cjs +0 -10
- package/dist/key-Dr6H_e3K.js +0 -10
- package/dist/middleware-BJ83veqi.js +0 -26
- package/dist/middleware-CJ4W2ir5.cjs +0 -17
- package/dist/middleware-Ve2mHJgo.js +0 -17
- package/dist/mod-BcObK1Lz.d.ts +0 -82
- package/dist/mod-C2tOeRkN.d.cts +0 -1
- package/dist/mod-CIbqfZW0.d.ts +0 -104
- package/dist/mod-Dt-G9ZOS.d.cts +0 -102
- package/dist/mod-FZd39qVq.d.cts +0 -1
- package/dist/mod-mXx9V0q5.d.cts +0 -80
- package/dist/nodeinfo/client.test.d.ts +0 -3
- package/dist/nodeinfo/handler.test.d.ts +0 -3
- package/dist/nodeinfo/semver.test.d.ts +0 -3
- package/dist/nodeinfo/types.test.d.ts +0 -3
- package/dist/nodeinfo-Co9lJrWl.cjs +0 -4
- package/dist/nodeinfo-DfycQ8Wf.js +0 -4
- package/dist/runtime/authdocloader.test.d.ts +0 -3
- package/dist/runtime/docloader.test.d.ts +0 -3
- package/dist/runtime/key.test.d.ts +0 -3
- package/dist/runtime/langstr.test.d.ts +0 -3
- package/dist/runtime/link.test.d.ts +0 -3
- package/dist/runtime/multibase/multibase.test.d.ts +0 -3
- package/dist/runtime/url.test.d.ts +0 -3
- package/dist/runtime-C58AJWSv.cjs +0 -4
- package/dist/runtime-DPYEDf-o.js +0 -4
- package/dist/sig/http.test.d.ts +0 -3
- package/dist/sig/key.test.d.ts +0 -3
- package/dist/sig/ld.test.d.ts +0 -3
- package/dist/sig/owner.test.d.ts +0 -3
- package/dist/sig/owner.test.js +0 -52
- package/dist/sig/proof.test.d.ts +0 -3
- package/dist/sig-ByHXzqUi.cjs +0 -4
- package/dist/sig-Cj3tk-ig.js +0 -4
- package/dist/testing/docloader.test.d.ts +0 -3
- package/dist/testing/docloader.test.js +0 -24
- package/dist/testing/mod.js +0 -10
- package/dist/vocab/actor.test.d.ts +0 -3
- package/dist/vocab/lookup.test.d.ts +0 -3
- package/dist/vocab/type.test.d.ts +0 -3
- package/dist/vocab/type.test.js +0 -25
- package/dist/vocab/vocab.test.d.ts +0 -3
- package/dist/vocab-BFy1CS5L.cjs +0 -289
- package/dist/vocab-BPFiQ650.js +0 -253
- package/dist/webfinger/handler.test.d.ts +0 -3
- package/dist/webfinger/lookup.test.d.ts +0 -3
- package/dist/webfinger-BjOEdFPs.cjs +0 -4
- package/dist/webfinger-De_bU0iE.js +0 -4
- package/dist/x/cfworkers.test.d.ts +0 -3
- /package/dist/{mod-1pDWKvUL.d.ts → compat/transformers.test.d.mts} +0 -0
- /package/dist/{mod-g0xFzAP9.d.ts → federation/builder.test.d.mts} +0 -0
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { lookupObject, traverseCollection } from "./vocab-BPFiQ650.js";
|
|
1
|
+
import { Temporal } from "@js-temporal/polyfill";
|
|
2
|
+
import "urlpattern-polyfill";
|
|
3
|
+
import { t as __exportAll } from "./rolldown-runtime-C7fyD9f2.js";
|
|
4
|
+
import { r as getDefaultActivityTransformers } from "./transformers-BV4OeK9o.js";
|
|
5
|
+
import { d as name, f as version, i as getDocumentLoader, s as kvCache } from "./docloader-BoXhusJ1.js";
|
|
6
|
+
import { G as Multikey, Tt as getTypeId, V as Link, X as OrderedCollectionPage, Y as OrderedCollection, _ as CollectionPage, g as Collection, q as Object$1, s as Activity, y as CryptographicKey } from "./actor-BTA45fXF.js";
|
|
7
|
+
import { t as lookupWebFinger } from "./lookup-BaU75j-d.js";
|
|
8
|
+
import { i as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-DK3o0FEH.js";
|
|
9
|
+
import { r as verifyRequest, t as doubleKnock } from "./http-VJbz6sKD.js";
|
|
10
|
+
import { a as doesActorOwnKey, d as signJsonLd, f as verifyJsonLd, l as detachSignature, n as signObject, o as getKeyOwner, r as verifyObject, u as hasSignature } from "./proof-CmTtG_t-.js";
|
|
11
|
+
import { n as getNodeInfo, t as nodeInfoToJson } from "./types-BXfL-dsX.js";
|
|
12
|
+
import { t as getAuthenticatedDocumentLoader } from "./authdocloader-CqtNsX_N.js";
|
|
13
|
+
import { lookupObject, traverseCollection } from "./vocab/mod.js";
|
|
15
14
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
16
15
|
import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
|
|
17
16
|
import { encodeHex } from "byte-encodings/hex";
|
|
@@ -20,7 +19,6 @@ import { Router } from "uri-template-router";
|
|
|
20
19
|
import { parseTemplate } from "url-template";
|
|
21
20
|
import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
|
|
22
21
|
import { domainToASCII } from "node:url";
|
|
23
|
-
|
|
24
22
|
//#region src/federation/inbox.ts
|
|
25
23
|
var InboxListenerSet = class InboxListenerSet {
|
|
26
24
|
#listeners;
|
|
@@ -57,7 +55,7 @@ var InboxListenerSet = class InboxListenerSet {
|
|
|
57
55
|
};
|
|
58
56
|
let warnedAboutDefaultIdempotency = false;
|
|
59
57
|
async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
|
|
60
|
-
const logger
|
|
58
|
+
const logger = getLogger([
|
|
61
59
|
"fedify",
|
|
62
60
|
"federation",
|
|
63
61
|
"inbox"
|
|
@@ -67,14 +65,12 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
67
65
|
const inboxContext = inboxContextFactory(recipient, json, activity.id?.href, getTypeId(activity).href);
|
|
68
66
|
const strategy = idempotencyStrategy ?? "per-origin";
|
|
69
67
|
if (idempotencyStrategy === void 0 && !warnedAboutDefaultIdempotency) {
|
|
70
|
-
logger
|
|
68
|
+
logger.warn("Using default idempotency strategy 'per-origin'. This default will change to 'per-inbox' in Fedify 2.0. Please explicitly set the idempotency strategy using .withIdempotency().");
|
|
71
69
|
warnedAboutDefaultIdempotency = true;
|
|
72
70
|
}
|
|
73
71
|
let keyString;
|
|
74
|
-
if (typeof strategy === "function")
|
|
75
|
-
|
|
76
|
-
keyString = result;
|
|
77
|
-
} else switch (strategy) {
|
|
72
|
+
if (typeof strategy === "function") keyString = await strategy(inboxContext, activity);
|
|
73
|
+
else switch (strategy) {
|
|
78
74
|
case "global":
|
|
79
75
|
keyString = activity.id.href;
|
|
80
76
|
break;
|
|
@@ -89,9 +85,8 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
89
85
|
if (keyString != null) cacheKey = [...kvPrefixes.activityIdempotence, keyString];
|
|
90
86
|
}
|
|
91
87
|
if (cacheKey != null) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
logger$1.debug("Activity {activityId} has already been processed.", {
|
|
88
|
+
if (await kv.get(cacheKey) === true) {
|
|
89
|
+
logger.debug("Activity {activityId} has already been processed.", {
|
|
95
90
|
activityId: activity.id?.href,
|
|
96
91
|
activity: json,
|
|
97
92
|
recipient
|
|
@@ -104,7 +99,7 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
104
99
|
}
|
|
105
100
|
}
|
|
106
101
|
if (activity.actorId == null) {
|
|
107
|
-
logger
|
|
102
|
+
logger.error("Missing actor.", { activity: json });
|
|
108
103
|
span.setStatus({
|
|
109
104
|
code: SpanStatusCode.ERROR,
|
|
110
105
|
message: "Missing actor."
|
|
@@ -127,7 +122,7 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
127
122
|
traceContext: carrier
|
|
128
123
|
});
|
|
129
124
|
} catch (error) {
|
|
130
|
-
logger
|
|
125
|
+
logger.error("Failed to enqueue the incoming activity {activityId}:\n{error}", {
|
|
131
126
|
error,
|
|
132
127
|
activityId: activity.id?.href,
|
|
133
128
|
activity: json,
|
|
@@ -139,7 +134,7 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
139
134
|
});
|
|
140
135
|
throw error;
|
|
141
136
|
}
|
|
142
|
-
logger
|
|
137
|
+
logger.info("Activity {activityId} is enqueued.", {
|
|
143
138
|
activityId: activity.id?.href,
|
|
144
139
|
activity: json,
|
|
145
140
|
recipient
|
|
@@ -147,60 +142,58 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
|
|
|
147
142
|
return "enqueued";
|
|
148
143
|
}
|
|
149
144
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
150
|
-
|
|
151
|
-
return await tracer.startActiveSpan("activitypub.dispatch_inbox_listener", { kind: SpanKind.INTERNAL }, async (span$1) => {
|
|
145
|
+
return await tracerProvider.getTracer(name, version).startActiveSpan("activitypub.dispatch_inbox_listener", { kind: SpanKind.INTERNAL }, async (span) => {
|
|
152
146
|
const dispatched = inboxListeners?.dispatchWithClass(activity);
|
|
153
147
|
if (dispatched == null) {
|
|
154
|
-
logger
|
|
148
|
+
logger.error("Unsupported activity type:\n{activity}", {
|
|
155
149
|
activity: json,
|
|
156
150
|
recipient
|
|
157
151
|
});
|
|
158
|
-
span
|
|
152
|
+
span.setStatus({
|
|
159
153
|
code: SpanStatusCode.UNSET,
|
|
160
154
|
message: `Unsupported activity type: ${getTypeId(activity).href}`
|
|
161
155
|
});
|
|
162
|
-
span
|
|
156
|
+
span.end();
|
|
163
157
|
return "unsupportedActivity";
|
|
164
158
|
}
|
|
165
159
|
const { class: cls, listener } = dispatched;
|
|
166
|
-
span
|
|
160
|
+
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
167
161
|
try {
|
|
168
162
|
await listener(inboxContextFactory(recipient, json, activity?.id?.href, getTypeId(activity).href), activity);
|
|
169
163
|
} catch (error) {
|
|
170
164
|
try {
|
|
171
165
|
await inboxErrorHandler?.(ctx, error);
|
|
172
|
-
} catch (error
|
|
173
|
-
logger
|
|
174
|
-
error
|
|
166
|
+
} catch (error) {
|
|
167
|
+
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
168
|
+
error,
|
|
175
169
|
activityId: activity.id?.href,
|
|
176
170
|
activity: json,
|
|
177
171
|
recipient
|
|
178
172
|
});
|
|
179
173
|
}
|
|
180
|
-
logger
|
|
174
|
+
logger.error("Failed to process the incoming activity {activityId}:\n{error}", {
|
|
181
175
|
error,
|
|
182
176
|
activityId: activity.id?.href,
|
|
183
177
|
activity: json,
|
|
184
178
|
recipient
|
|
185
179
|
});
|
|
186
|
-
span
|
|
180
|
+
span.setStatus({
|
|
187
181
|
code: SpanStatusCode.ERROR,
|
|
188
182
|
message: String(error)
|
|
189
183
|
});
|
|
190
|
-
span
|
|
184
|
+
span.end();
|
|
191
185
|
return "error";
|
|
192
186
|
}
|
|
193
187
|
if (cacheKey != null) await kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
194
|
-
logger
|
|
188
|
+
logger.info("Activity {activityId} has been processed.", {
|
|
195
189
|
activityId: activity.id?.href,
|
|
196
190
|
activity: json,
|
|
197
191
|
recipient
|
|
198
192
|
});
|
|
199
|
-
span
|
|
193
|
+
span.end();
|
|
200
194
|
return "success";
|
|
201
195
|
});
|
|
202
196
|
}
|
|
203
|
-
|
|
204
197
|
//#endregion
|
|
205
198
|
//#region src/federation/router.ts
|
|
206
199
|
function cloneInnerRouter(router) {
|
|
@@ -308,7 +301,6 @@ var RouterError = class extends Error {
|
|
|
308
301
|
this.name = "RouterError";
|
|
309
302
|
}
|
|
310
303
|
};
|
|
311
|
-
|
|
312
304
|
//#endregion
|
|
313
305
|
//#region src/federation/builder.ts
|
|
314
306
|
var FederationBuilderImpl = class {
|
|
@@ -344,8 +336,8 @@ var FederationBuilderImpl = class {
|
|
|
344
336
|
this.collectionTypeIds = {};
|
|
345
337
|
}
|
|
346
338
|
async build(options) {
|
|
347
|
-
const { FederationImpl
|
|
348
|
-
const f = new FederationImpl
|
|
339
|
+
const { FederationImpl } = await Promise.resolve().then(() => middleware_exports);
|
|
340
|
+
const f = new FederationImpl(options);
|
|
349
341
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
350
342
|
f.router = this.router.clone();
|
|
351
343
|
f.router.trailingSlashInsensitive = trailingSlashInsensitiveValue;
|
|
@@ -370,7 +362,7 @@ var FederationBuilderImpl = class {
|
|
|
370
362
|
return f;
|
|
371
363
|
}
|
|
372
364
|
_getTracer() {
|
|
373
|
-
return trace.getTracer(
|
|
365
|
+
return trace.getTracer(name, version);
|
|
374
366
|
}
|
|
375
367
|
setActorDispatcher(path, dispatcher) {
|
|
376
368
|
if (this.router.has("actor")) throw new RouterError("Actor dispatcher already set.");
|
|
@@ -381,17 +373,17 @@ var FederationBuilderImpl = class {
|
|
|
381
373
|
"federation",
|
|
382
374
|
"actor"
|
|
383
375
|
]).warn("The {{handle}} variable in the actor dispatcher path is deprecated. Use {{identifier}} instead.");
|
|
384
|
-
const callbacks = { dispatcher: async (context
|
|
376
|
+
const callbacks = { dispatcher: async (context, identifier) => {
|
|
385
377
|
const actor = await this._getTracer().startActiveSpan("activitypub.dispatch_actor", {
|
|
386
378
|
kind: SpanKind.SERVER,
|
|
387
379
|
attributes: { "fedify.actor.identifier": identifier }
|
|
388
380
|
}, async (span) => {
|
|
389
381
|
try {
|
|
390
|
-
const actor
|
|
391
|
-
span.setAttribute("activitypub.actor.id", (actor
|
|
392
|
-
if (actor
|
|
393
|
-
else span.setAttribute("activitypub.actor.type", getTypeId(actor
|
|
394
|
-
return actor
|
|
382
|
+
const actor = await dispatcher(context, identifier);
|
|
383
|
+
span.setAttribute("activitypub.actor.id", (actor?.id ?? context.getActorUri(identifier)).href);
|
|
384
|
+
if (actor == null) span.setStatus({ code: SpanStatusCode.ERROR });
|
|
385
|
+
else span.setAttribute("activitypub.actor.type", getTypeId(actor).href);
|
|
386
|
+
return actor;
|
|
395
387
|
} catch (error) {
|
|
396
388
|
span.setStatus({
|
|
397
389
|
code: SpanStatusCode.ERROR,
|
|
@@ -403,52 +395,52 @@ var FederationBuilderImpl = class {
|
|
|
403
395
|
}
|
|
404
396
|
});
|
|
405
397
|
if (actor == null) return null;
|
|
406
|
-
const logger
|
|
398
|
+
const logger = getLogger([
|
|
407
399
|
"fedify",
|
|
408
400
|
"federation",
|
|
409
401
|
"actor"
|
|
410
402
|
]);
|
|
411
|
-
if (actor.id == null) logger
|
|
412
|
-
else if (actor.id.href != context
|
|
403
|
+
if (actor.id == null) logger.warn("Actor dispatcher returned an actor without an id property. Set the property with Context.getActorUri(identifier).");
|
|
404
|
+
else if (actor.id.href != context.getActorUri(identifier).href) logger.warn("Actor dispatcher returned an actor with an id property that does not match the actor URI. Set the property with Context.getActorUri(identifier).");
|
|
413
405
|
if (this.followingCallbacks != null && this.followingCallbacks.dispatcher != null) {
|
|
414
|
-
if (actor.followingId == null) logger
|
|
415
|
-
else if (actor.followingId.href != context
|
|
406
|
+
if (actor.followingId == null) logger.warn("You configured a following collection dispatcher, but the actor does not have a following property. Set the property with Context.getFollowingUri(identifier).");
|
|
407
|
+
else if (actor.followingId.href != context.getFollowingUri(identifier).href) logger.warn("You configured a following collection dispatcher, but the actor's following property does not match the following collection URI. Set the property with Context.getFollowingUri(identifier).");
|
|
416
408
|
}
|
|
417
409
|
if (this.followersCallbacks != null && this.followersCallbacks.dispatcher != null) {
|
|
418
|
-
if (actor.followersId == null) logger
|
|
419
|
-
else if (actor.followersId.href != context
|
|
410
|
+
if (actor.followersId == null) logger.warn("You configured a followers collection dispatcher, but the actor does not have a followers property. Set the property with Context.getFollowersUri(identifier).");
|
|
411
|
+
else if (actor.followersId.href != context.getFollowersUri(identifier).href) logger.warn("You configured a followers collection dispatcher, but the actor's followers property does not match the followers collection URI. Set the property with Context.getFollowersUri(identifier).");
|
|
420
412
|
}
|
|
421
413
|
if (this.outboxCallbacks != null && this.outboxCallbacks.dispatcher != null) {
|
|
422
|
-
if (actor?.outboxId == null) logger
|
|
423
|
-
else if (actor.outboxId.href != context
|
|
414
|
+
if (actor?.outboxId == null) logger.warn("You configured an outbox collection dispatcher, but the actor does not have an outbox property. Set the property with Context.getOutboxUri(identifier).");
|
|
415
|
+
else if (actor.outboxId.href != context.getOutboxUri(identifier).href) logger.warn("You configured an outbox collection dispatcher, but the actor's outbox property does not match the outbox collection URI. Set the property with Context.getOutboxUri(identifier).");
|
|
424
416
|
}
|
|
425
417
|
if (this.likedCallbacks != null && this.likedCallbacks.dispatcher != null) {
|
|
426
|
-
if (actor?.likedId == null) logger
|
|
427
|
-
else if (actor.likedId.href != context
|
|
418
|
+
if (actor?.likedId == null) logger.warn("You configured a liked collection dispatcher, but the actor does not have a liked property. Set the property with Context.getLikedUri(identifier).");
|
|
419
|
+
else if (actor.likedId.href != context.getLikedUri(identifier).href) logger.warn("You configured a liked collection dispatcher, but the actor's liked property does not match the liked collection URI. Set the property with Context.getLikedUri(identifier).");
|
|
428
420
|
}
|
|
429
421
|
if (this.featuredCallbacks != null && this.featuredCallbacks.dispatcher != null) {
|
|
430
|
-
if (actor?.featuredId == null) logger
|
|
431
|
-
else if (actor.featuredId.href != context
|
|
422
|
+
if (actor?.featuredId == null) logger.warn("You configured a featured collection dispatcher, but the actor does not have a featured property. Set the property with Context.getFeaturedUri(identifier).");
|
|
423
|
+
else if (actor.featuredId.href != context.getFeaturedUri(identifier).href) logger.warn("You configured a featured collection dispatcher, but the actor's featured property does not match the featured collection URI. Set the property with Context.getFeaturedUri(identifier).");
|
|
432
424
|
}
|
|
433
425
|
if (this.featuredTagsCallbacks != null && this.featuredTagsCallbacks.dispatcher != null) {
|
|
434
|
-
if (actor?.featuredTagsId == null) logger
|
|
435
|
-
else if (actor.featuredTagsId.href != context
|
|
426
|
+
if (actor?.featuredTagsId == null) logger.warn("You configured a featured tags collection dispatcher, but the actor does not have a featuredTags property. Set the property with Context.getFeaturedTagsUri(identifier).");
|
|
427
|
+
else if (actor.featuredTagsId.href != context.getFeaturedTagsUri(identifier).href) logger.warn("You configured a featured tags collection dispatcher, but the actor's featuredTags property does not match the featured tags collection URI. Set the property with Context.getFeaturedTagsUri(identifier).");
|
|
436
428
|
}
|
|
437
429
|
if (this.router.has("inbox")) {
|
|
438
|
-
if (actor.inboxId == null) logger
|
|
439
|
-
else if (actor.inboxId.href != context
|
|
440
|
-
if (actor.endpoints == null || actor.endpoints.sharedInbox == null) logger
|
|
441
|
-
else if (actor.endpoints.sharedInbox.href != context
|
|
430
|
+
if (actor.inboxId == null) logger.warn("You configured inbox listeners, but the actor does not have an inbox property. Set the property with Context.getInboxUri(identifier).");
|
|
431
|
+
else if (actor.inboxId.href != context.getInboxUri(identifier).href) logger.warn("You configured inbox listeners, but the actor's inbox property does not match the inbox URI. Set the property with Context.getInboxUri(identifier).");
|
|
432
|
+
if (actor.endpoints == null || actor.endpoints.sharedInbox == null) logger.warn("You configured inbox listeners, but the actor does not have a endpoints.sharedInbox property. Set the property with Context.getInboxUri().");
|
|
433
|
+
else if (actor.endpoints.sharedInbox.href != context.getInboxUri().href) logger.warn("You configured inbox listeners, but the actor's endpoints.sharedInbox property does not match the shared inbox URI. Set the property with Context.getInboxUri().");
|
|
442
434
|
}
|
|
443
435
|
if (callbacks.keyPairsDispatcher != null) {
|
|
444
|
-
if (actor.publicKeyId == null) logger
|
|
445
|
-
if (actor.assertionMethodId == null) logger
|
|
436
|
+
if (actor.publicKeyId == null) logger.warn("You configured a key pairs dispatcher, but the actor does not have a publicKey property. Set the property with Context.getActorKeyPairs(identifier).");
|
|
437
|
+
if (actor.assertionMethodId == null) logger.warn("You configured a key pairs dispatcher, but the actor does not have an assertionMethod property. Set the property with Context.getActorKeyPairs(identifier).");
|
|
446
438
|
}
|
|
447
439
|
return actor;
|
|
448
440
|
} };
|
|
449
441
|
this.actorCallbacks = callbacks;
|
|
450
442
|
const setters = {
|
|
451
|
-
setKeyPairsDispatcher: (dispatcher
|
|
443
|
+
setKeyPairsDispatcher: (dispatcher) => {
|
|
452
444
|
callbacks.keyPairsDispatcher = (ctx, identifier) => this._getTracer().startActiveSpan("activitypub.dispatch_actor_key_pairs", {
|
|
453
445
|
kind: SpanKind.SERVER,
|
|
454
446
|
attributes: {
|
|
@@ -457,7 +449,7 @@ var FederationBuilderImpl = class {
|
|
|
457
449
|
}
|
|
458
450
|
}, async (span) => {
|
|
459
451
|
try {
|
|
460
|
-
return await dispatcher
|
|
452
|
+
return await dispatcher(ctx, identifier);
|
|
461
453
|
} catch (e) {
|
|
462
454
|
span.setStatus({
|
|
463
455
|
code: SpanStatusCode.ERROR,
|
|
@@ -487,8 +479,7 @@ var FederationBuilderImpl = class {
|
|
|
487
479
|
}
|
|
488
480
|
setNodeInfoDispatcher(path, dispatcher) {
|
|
489
481
|
if (this.router.has("nodeInfo")) throw new RouterError("NodeInfo dispatcher already set.");
|
|
490
|
-
|
|
491
|
-
if (variables.size !== 0) throw new RouterError("Path for NodeInfo dispatcher must have no variables.");
|
|
482
|
+
if (this.router.add(path, "nodeInfo").size !== 0) throw new RouterError("Path for NodeInfo dispatcher must have no variables.");
|
|
492
483
|
this.nodeInfoDispatcher = dispatcher;
|
|
493
484
|
}
|
|
494
485
|
setWebFingerLinksDispatcher(dispatcher) {
|
|
@@ -501,8 +492,7 @@ var FederationBuilderImpl = class {
|
|
|
501
492
|
if (variables.size < 1) throw new RouterError("Path for object dispatcher must have at least one variable.");
|
|
502
493
|
const callbacks = {
|
|
503
494
|
dispatcher: (ctx, values) => {
|
|
504
|
-
|
|
505
|
-
return tracer.startActiveSpan("activitypub.dispatch_object", {
|
|
495
|
+
return this._getTracer().startActiveSpan("activitypub.dispatch_object", {
|
|
506
496
|
kind: SpanKind.SERVER,
|
|
507
497
|
attributes: {
|
|
508
498
|
"fedify.object.type": cls.typeId.href,
|
|
@@ -773,8 +763,7 @@ var FederationBuilderImpl = class {
|
|
|
773
763
|
]).warn("The {{handle}} variable in the inbox path is deprecated. Use {{identifier}} instead.");
|
|
774
764
|
}
|
|
775
765
|
if (sharedInboxPath != null) {
|
|
776
|
-
|
|
777
|
-
if (siVars.size !== 0) throw new RouterError("Path for shared inbox must have no variables.");
|
|
766
|
+
if (this.router.add(sharedInboxPath, "sharedInbox").size !== 0) throw new RouterError("Path for shared inbox must have no variables.");
|
|
778
767
|
}
|
|
779
768
|
const listeners = this.inboxListeners = new InboxListenerSet();
|
|
780
769
|
const setters = {
|
|
@@ -808,8 +797,7 @@ var FederationBuilderImpl = class {
|
|
|
808
797
|
const routeName = `${collectionType}:${this.#uniqueCollectionId(name)}`;
|
|
809
798
|
if (this.router.has(routeName)) throw new RouterError(`Collection dispatcher for ${strName} already set.`);
|
|
810
799
|
if (this.collectionCallbacks[name] != null) throw new RouterError(`Collection dispatcher for ${strName} already set.`);
|
|
811
|
-
|
|
812
|
-
if (variables.size < 1) throw new RouterError("Path for collection dispatcher must have at least one variable.");
|
|
800
|
+
if (this.router.add(path, routeName).size < 1) throw new RouterError("Path for collection dispatcher must have at least one variable.");
|
|
813
801
|
const callbacks = { dispatcher };
|
|
814
802
|
this.collectionCallbacks[name] = callbacks;
|
|
815
803
|
this.collectionTypeIds[name] = itemType;
|
|
@@ -844,8 +832,7 @@ var FederationBuilderImpl = class {
|
|
|
844
832
|
getCollectionPath(name, values) {
|
|
845
833
|
if (!(name in this.collectionCallbacks)) return null;
|
|
846
834
|
const routeName = this.#uniqueCollectionId(name);
|
|
847
|
-
|
|
848
|
-
return path;
|
|
835
|
+
return this.router.build(`collection:${routeName}`, values) ?? this.router.build(`orderedCollection:${routeName}`, values);
|
|
849
836
|
}
|
|
850
837
|
/**
|
|
851
838
|
* Converts a name (string or symbol) to a unique string identifier.
|
|
@@ -868,7 +855,6 @@ var FederationBuilderImpl = class {
|
|
|
868
855
|
function createFederationBuilder() {
|
|
869
856
|
return new FederationBuilderImpl();
|
|
870
857
|
}
|
|
871
|
-
|
|
872
858
|
//#endregion
|
|
873
859
|
//#region src/federation/collection.ts
|
|
874
860
|
/**
|
|
@@ -887,8 +873,8 @@ async function digest(uris) {
|
|
|
887
873
|
if (processed.has(u)) continue;
|
|
888
874
|
processed.add(u);
|
|
889
875
|
const encoded = encoder.encode(u);
|
|
890
|
-
const digest
|
|
891
|
-
for (let i = 0; i < 32; i++) result[i] ^= digest
|
|
876
|
+
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", encoded));
|
|
877
|
+
for (let i = 0; i < 32; i++) result[i] ^= digest[i];
|
|
892
878
|
}
|
|
893
879
|
return result;
|
|
894
880
|
}
|
|
@@ -906,10 +892,8 @@ async function buildCollectionSynchronizationHeader(collectionId, actorIds) {
|
|
|
906
892
|
const baseUrl = new URL(anyActorId);
|
|
907
893
|
const url = new URL(collectionId);
|
|
908
894
|
url.searchParams.set("base-url", `${baseUrl.origin}/`);
|
|
909
|
-
|
|
910
|
-
return `collectionId="${collectionId}", url="${url}", digest="${hash}"`;
|
|
895
|
+
return `collectionId="${collectionId}", url="${url}", digest="${encodeHex(await digest(actorIds))}"`;
|
|
911
896
|
}
|
|
912
|
-
|
|
913
897
|
//#endregion
|
|
914
898
|
//#region src/federation/keycache.ts
|
|
915
899
|
const NULL_KEY_CACHE_VALUE = { _fedify: "key-unavailable" };
|
|
@@ -943,7 +927,7 @@ var KvKeyCache = class {
|
|
|
943
927
|
return await Multikey.fromJsonLd(serialized, this.options);
|
|
944
928
|
} catch {
|
|
945
929
|
await this.kv.delete([...this.prefix, keyId.href]);
|
|
946
|
-
return
|
|
930
|
+
return;
|
|
947
931
|
}
|
|
948
932
|
}
|
|
949
933
|
}
|
|
@@ -958,7 +942,6 @@ var KvKeyCache = class {
|
|
|
958
942
|
await this.kv.set([...this.prefix, keyId.href], serialized);
|
|
959
943
|
}
|
|
960
944
|
};
|
|
961
|
-
|
|
962
945
|
//#endregion
|
|
963
946
|
//#region src/federation/negotiation.ts
|
|
964
947
|
function compareSpecs(a, b) {
|
|
@@ -1003,8 +986,8 @@ function parseMediaType(str, i) {
|
|
|
1003
986
|
function parseAccept(accept) {
|
|
1004
987
|
const accepts = accept.split(",").map((p) => p.trim());
|
|
1005
988
|
const mediaTypes = [];
|
|
1006
|
-
for (const [index, accept
|
|
1007
|
-
const mediaType = parseMediaType(accept
|
|
989
|
+
for (const [index, accept] of accepts.entries()) {
|
|
990
|
+
const mediaType = parseMediaType(accept.trim(), index);
|
|
1008
991
|
if (mediaType) mediaTypes.push(mediaType);
|
|
1009
992
|
}
|
|
1010
993
|
return mediaTypes;
|
|
@@ -1013,10 +996,8 @@ function getFullType(spec) {
|
|
|
1013
996
|
return `${spec.type}/${spec.subtype}`;
|
|
1014
997
|
}
|
|
1015
998
|
function preferredMediaTypes(accept) {
|
|
1016
|
-
|
|
1017
|
-
return accepts.filter(isQuality).sort(compareSpecs).map(getFullType);
|
|
999
|
+
return parseAccept(accept === void 0 ? "*/*" : accept ?? "").filter(isQuality).sort(compareSpecs).map(getFullType);
|
|
1018
1000
|
}
|
|
1019
|
-
|
|
1020
1001
|
//#endregion
|
|
1021
1002
|
//#region src/federation/handler.ts
|
|
1022
1003
|
function acceptsJsonLd(request) {
|
|
@@ -1033,24 +1014,24 @@ function acceptsJsonLd(request) {
|
|
|
1033
1014
|
* @param parameters The parameters for handling the actor.
|
|
1034
1015
|
* @returns A promise that resolves to an HTTP response.
|
|
1035
1016
|
*/
|
|
1036
|
-
async function handleActor(request, { identifier, context
|
|
1037
|
-
const logger
|
|
1017
|
+
async function handleActor(request, { identifier, context, actorDispatcher, authorizePredicate, onNotFound, onNotAcceptable, onUnauthorized }) {
|
|
1018
|
+
const logger = getLogger([
|
|
1038
1019
|
"fedify",
|
|
1039
1020
|
"federation",
|
|
1040
1021
|
"actor"
|
|
1041
1022
|
]);
|
|
1042
1023
|
if (actorDispatcher == null) {
|
|
1043
|
-
logger
|
|
1024
|
+
logger.debug("Actor dispatcher is not set.", { identifier });
|
|
1044
1025
|
return await onNotFound(request);
|
|
1045
1026
|
}
|
|
1046
|
-
const actor = await actorDispatcher(context
|
|
1027
|
+
const actor = await actorDispatcher(context, identifier);
|
|
1047
1028
|
if (actor == null) {
|
|
1048
|
-
logger
|
|
1029
|
+
logger.debug("Actor {identifier} not found.", { identifier });
|
|
1049
1030
|
return await onNotFound(request);
|
|
1050
1031
|
}
|
|
1051
1032
|
if (!acceptsJsonLd(request)) return await onNotAcceptable(request);
|
|
1052
1033
|
if (authorizePredicate != null) {
|
|
1053
|
-
let key = await context
|
|
1034
|
+
let key = await context.getSignedKey();
|
|
1054
1035
|
key = key?.clone({}, { $warning: {
|
|
1055
1036
|
category: [
|
|
1056
1037
|
"fedify",
|
|
@@ -1059,7 +1040,7 @@ async function handleActor(request, { identifier, context: context$1, actorDispa
|
|
|
1059
1040
|
],
|
|
1060
1041
|
message: "The third parameter of AuthorizePredicate is deprecated in favor of RequestContext.getSignedKey() method. The third parameter will be removed in a future release."
|
|
1061
1042
|
} }) ?? null;
|
|
1062
|
-
let keyOwner = await context
|
|
1043
|
+
let keyOwner = await context.getSignedKeyOwner();
|
|
1063
1044
|
keyOwner = keyOwner?.clone({}, { $warning: {
|
|
1064
1045
|
category: [
|
|
1065
1046
|
"fedify",
|
|
@@ -1068,9 +1049,9 @@ async function handleActor(request, { identifier, context: context$1, actorDispa
|
|
|
1068
1049
|
],
|
|
1069
1050
|
message: "The fourth parameter of AuthorizePredicate is deprecated in favor of RequestContext.getSignedKeyOwner() method. The fourth parameter will be removed in a future release."
|
|
1070
1051
|
} }) ?? null;
|
|
1071
|
-
if (!await authorizePredicate(context
|
|
1052
|
+
if (!await authorizePredicate(context, identifier, key, keyOwner)) return await onUnauthorized(request);
|
|
1072
1053
|
}
|
|
1073
|
-
const jsonLd = await actor.toJsonLd(context
|
|
1054
|
+
const jsonLd = await actor.toJsonLd(context);
|
|
1074
1055
|
return new Response(JSON.stringify(jsonLd), { headers: {
|
|
1075
1056
|
"Content-Type": "application/activity+json",
|
|
1076
1057
|
Vary: "Accept"
|
|
@@ -1083,13 +1064,13 @@ async function handleActor(request, { identifier, context: context$1, actorDispa
|
|
|
1083
1064
|
* @param parameters The parameters for handling the object.
|
|
1084
1065
|
* @returns A promise that resolves to an HTTP response.
|
|
1085
1066
|
*/
|
|
1086
|
-
async function handleObject(request, { values, context
|
|
1067
|
+
async function handleObject(request, { values, context, objectDispatcher, authorizePredicate, onNotFound, onNotAcceptable, onUnauthorized }) {
|
|
1087
1068
|
if (objectDispatcher == null) return await onNotFound(request);
|
|
1088
|
-
const object = await objectDispatcher(context
|
|
1069
|
+
const object = await objectDispatcher(context, values);
|
|
1089
1070
|
if (object == null) return await onNotFound(request);
|
|
1090
1071
|
if (!acceptsJsonLd(request)) return await onNotAcceptable(request);
|
|
1091
1072
|
if (authorizePredicate != null) {
|
|
1092
|
-
let key = await context
|
|
1073
|
+
let key = await context.getSignedKey();
|
|
1093
1074
|
key = key?.clone({}, { $warning: {
|
|
1094
1075
|
category: [
|
|
1095
1076
|
"fedify",
|
|
@@ -1098,7 +1079,7 @@ async function handleObject(request, { values, context: context$1, objectDispatc
|
|
|
1098
1079
|
],
|
|
1099
1080
|
message: "The third parameter of ObjectAuthorizePredicate is deprecated in favor of RequestContext.getSignedKey() method. The third parameter will be removed in a future release."
|
|
1100
1081
|
} }) ?? null;
|
|
1101
|
-
let keyOwner = await context
|
|
1082
|
+
let keyOwner = await context.getSignedKeyOwner();
|
|
1102
1083
|
keyOwner = keyOwner?.clone({}, { $warning: {
|
|
1103
1084
|
category: [
|
|
1104
1085
|
"fedify",
|
|
@@ -1107,9 +1088,9 @@ async function handleObject(request, { values, context: context$1, objectDispatc
|
|
|
1107
1088
|
],
|
|
1108
1089
|
message: "The fourth parameter of ObjectAuthorizePredicate is deprecated in favor of RequestContext.getSignedKeyOwner() method. The fourth parameter will be removed in a future release."
|
|
1109
1090
|
} }) ?? null;
|
|
1110
|
-
if (!await authorizePredicate(context
|
|
1091
|
+
if (!await authorizePredicate(context, values, key, keyOwner)) return await onUnauthorized(request);
|
|
1111
1092
|
}
|
|
1112
|
-
const jsonLd = await object.toJsonLd(context
|
|
1093
|
+
const jsonLd = await object.toJsonLd(context);
|
|
1113
1094
|
return new Response(JSON.stringify(jsonLd), { headers: {
|
|
1114
1095
|
"Content-Type": "application/activity+json",
|
|
1115
1096
|
Vary: "Accept"
|
|
@@ -1125,18 +1106,17 @@ async function handleObject(request, { values, context: context$1, objectDispatc
|
|
|
1125
1106
|
* @param parameters The parameters for handling the collection.
|
|
1126
1107
|
* @returns A promise that resolves to an HTTP response.
|
|
1127
1108
|
*/
|
|
1128
|
-
async function handleCollection(request, { name, identifier, uriGetter, filter, filterPredicate, context
|
|
1129
|
-
const spanName = name.trim().replace(/\s+/g, "_");
|
|
1109
|
+
async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound, onNotAcceptable }) {
|
|
1110
|
+
const spanName = name$2.trim().replace(/\s+/g, "_");
|
|
1130
1111
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
1131
|
-
const tracer = tracerProvider.getTracer(
|
|
1132
|
-
const
|
|
1133
|
-
const cursor = url.searchParams.get("cursor");
|
|
1112
|
+
const tracer = tracerProvider.getTracer(name, version);
|
|
1113
|
+
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
1134
1114
|
if (collectionCallbacks == null) return await onNotFound(request);
|
|
1135
1115
|
let collection;
|
|
1136
1116
|
const baseUri = uriGetter(identifier);
|
|
1137
1117
|
if (cursor == null) {
|
|
1138
|
-
const firstCursor = await collectionCallbacks.firstCursor?.(context
|
|
1139
|
-
const totalItems = filter == null ? await collectionCallbacks.counter?.(context
|
|
1118
|
+
const firstCursor = await collectionCallbacks.firstCursor?.(context, identifier);
|
|
1119
|
+
const totalItems = filter == null ? await collectionCallbacks.counter?.(context, identifier) : void 0;
|
|
1140
1120
|
if (firstCursor == null) {
|
|
1141
1121
|
const itemsOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection ${spanName}`, {
|
|
1142
1122
|
kind: SpanKind.SERVER,
|
|
@@ -1147,7 +1127,7 @@ async function handleCollection(request, { name, identifier, uriGetter, filter,
|
|
|
1147
1127
|
}, async (span) => {
|
|
1148
1128
|
if (totalItems != null) span.setAttribute("activitypub.collection.total_items", Number(totalItems));
|
|
1149
1129
|
try {
|
|
1150
|
-
const page = await collectionCallbacks.dispatcher(context
|
|
1130
|
+
const page = await collectionCallbacks.dispatcher(context, identifier, null, filter);
|
|
1151
1131
|
if (page == null) {
|
|
1152
1132
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1153
1133
|
return await onNotFound(request);
|
|
@@ -1169,15 +1149,15 @@ async function handleCollection(request, { name, identifier, uriGetter, filter,
|
|
|
1169
1149
|
collection = new OrderedCollection({
|
|
1170
1150
|
id: baseUri,
|
|
1171
1151
|
totalItems: totalItems == null ? null : Number(totalItems),
|
|
1172
|
-
items: filterCollectionItems(itemsOrResponse, name, filterPredicate)
|
|
1152
|
+
items: filterCollectionItems(itemsOrResponse, name$2, filterPredicate)
|
|
1173
1153
|
});
|
|
1174
1154
|
} else {
|
|
1175
|
-
const lastCursor = await collectionCallbacks.lastCursor?.(context
|
|
1176
|
-
const first = new URL(context
|
|
1155
|
+
const lastCursor = await collectionCallbacks.lastCursor?.(context, identifier);
|
|
1156
|
+
const first = new URL(context.url);
|
|
1177
1157
|
first.searchParams.set("cursor", firstCursor);
|
|
1178
1158
|
let last = null;
|
|
1179
1159
|
if (lastCursor != null) {
|
|
1180
|
-
last = new URL(context
|
|
1160
|
+
last = new URL(context.url);
|
|
1181
1161
|
last.searchParams.set("cursor", lastCursor);
|
|
1182
1162
|
}
|
|
1183
1163
|
collection = new OrderedCollection({
|
|
@@ -1190,7 +1170,7 @@ async function handleCollection(request, { name, identifier, uriGetter, filter,
|
|
|
1190
1170
|
} else {
|
|
1191
1171
|
const uri = new URL(baseUri);
|
|
1192
1172
|
uri.searchParams.set("cursor", cursor);
|
|
1193
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name}`, {
|
|
1173
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
|
|
1194
1174
|
kind: SpanKind.SERVER,
|
|
1195
1175
|
attributes: {
|
|
1196
1176
|
"activitypub.collection.id": uri.href,
|
|
@@ -1199,7 +1179,7 @@ async function handleCollection(request, { name, identifier, uriGetter, filter,
|
|
|
1199
1179
|
}
|
|
1200
1180
|
}, async (span) => {
|
|
1201
1181
|
try {
|
|
1202
|
-
const page = await collectionCallbacks.dispatcher(context
|
|
1182
|
+
const page = await collectionCallbacks.dispatcher(context, identifier, cursor, filter);
|
|
1203
1183
|
if (page == null) {
|
|
1204
1184
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1205
1185
|
return await onNotFound(request);
|
|
@@ -1220,27 +1200,27 @@ async function handleCollection(request, { name, identifier, uriGetter, filter,
|
|
|
1220
1200
|
const { items, prevCursor, nextCursor } = pageOrResponse;
|
|
1221
1201
|
let prev = null;
|
|
1222
1202
|
if (prevCursor != null) {
|
|
1223
|
-
prev = new URL(context
|
|
1203
|
+
prev = new URL(context.url);
|
|
1224
1204
|
prev.searchParams.set("cursor", prevCursor);
|
|
1225
1205
|
}
|
|
1226
1206
|
let next = null;
|
|
1227
1207
|
if (nextCursor != null) {
|
|
1228
|
-
next = new URL(context
|
|
1208
|
+
next = new URL(context.url);
|
|
1229
1209
|
next.searchParams.set("cursor", nextCursor);
|
|
1230
1210
|
}
|
|
1231
|
-
const partOf = new URL(context
|
|
1211
|
+
const partOf = new URL(context.url);
|
|
1232
1212
|
partOf.searchParams.delete("cursor");
|
|
1233
1213
|
collection = new OrderedCollectionPage({
|
|
1234
1214
|
id: uri,
|
|
1235
1215
|
prev,
|
|
1236
1216
|
next,
|
|
1237
|
-
items: filterCollectionItems(items, name, filterPredicate),
|
|
1217
|
+
items: filterCollectionItems(items, name$2, filterPredicate),
|
|
1238
1218
|
partOf
|
|
1239
1219
|
});
|
|
1240
1220
|
}
|
|
1241
1221
|
if (!acceptsJsonLd(request)) return await onNotAcceptable(request);
|
|
1242
1222
|
if (collectionCallbacks.authorizePredicate != null) {
|
|
1243
|
-
let key = await context
|
|
1223
|
+
let key = await context.getSignedKey();
|
|
1244
1224
|
key = key?.clone({}, { $warning: {
|
|
1245
1225
|
category: [
|
|
1246
1226
|
"fedify",
|
|
@@ -1249,7 +1229,7 @@ async function handleCollection(request, { name, identifier, uriGetter, filter,
|
|
|
1249
1229
|
],
|
|
1250
1230
|
message: "The third parameter of AuthorizePredicate is deprecated in favor of RequestContext.getSignedKey() method. The third parameter will be removed in a future release."
|
|
1251
1231
|
} }) ?? null;
|
|
1252
|
-
let keyOwner = await context
|
|
1232
|
+
let keyOwner = await context.getSignedKeyOwner();
|
|
1253
1233
|
keyOwner = keyOwner?.clone({}, { $warning: {
|
|
1254
1234
|
category: [
|
|
1255
1235
|
"fedify",
|
|
@@ -1258,9 +1238,9 @@ async function handleCollection(request, { name, identifier, uriGetter, filter,
|
|
|
1258
1238
|
],
|
|
1259
1239
|
message: "The fourth parameter of AuthorizePredicate is deprecated in favor of RequestContext.getSignedKeyOwner() method. The fourth parameter will be removed in a future release."
|
|
1260
1240
|
} }) ?? null;
|
|
1261
|
-
if (!await collectionCallbacks.authorizePredicate(context
|
|
1241
|
+
if (!await collectionCallbacks.authorizePredicate(context, identifier, key, keyOwner)) return await onUnauthorized(request);
|
|
1262
1242
|
}
|
|
1263
|
-
const jsonLd = await collection.toJsonLd(context
|
|
1243
|
+
const jsonLd = await collection.toJsonLd(context);
|
|
1264
1244
|
return new Response(JSON.stringify(jsonLd), { headers: {
|
|
1265
1245
|
"Content-Type": "application/activity+json",
|
|
1266
1246
|
Vary: "Accept"
|
|
@@ -1305,9 +1285,7 @@ function filterCollectionItems(items, collectionName, filterPredicate) {
|
|
|
1305
1285
|
* @returns A promise that resolves to an HTTP response.
|
|
1306
1286
|
*/
|
|
1307
1287
|
async function handleInbox(request, options) {
|
|
1308
|
-
|
|
1309
|
-
const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
|
|
1310
|
-
return await tracer.startActiveSpan("activitypub.inbox", {
|
|
1288
|
+
return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("activitypub.inbox", {
|
|
1311
1289
|
kind: options.queue == null ? SpanKind.SERVER : SpanKind.PRODUCER,
|
|
1312
1290
|
attributes: { "activitypub.shared_inbox": options.recipient == null }
|
|
1313
1291
|
}, async (span) => {
|
|
@@ -1335,22 +1313,21 @@ async function handleInbox(request, options) {
|
|
|
1335
1313
|
*/
|
|
1336
1314
|
async function handleInboxInternal(request, parameters, span) {
|
|
1337
1315
|
const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, tracerProvider } = parameters;
|
|
1338
|
-
const logger
|
|
1316
|
+
const logger = getLogger([
|
|
1339
1317
|
"fedify",
|
|
1340
1318
|
"federation",
|
|
1341
1319
|
"inbox"
|
|
1342
1320
|
]);
|
|
1343
1321
|
if (actorDispatcher == null) {
|
|
1344
|
-
logger
|
|
1322
|
+
logger.error("Actor dispatcher is not set.", { recipient });
|
|
1345
1323
|
span.setStatus({
|
|
1346
1324
|
code: SpanStatusCode.ERROR,
|
|
1347
1325
|
message: "Actor dispatcher is not set."
|
|
1348
1326
|
});
|
|
1349
1327
|
return await onNotFound(request);
|
|
1350
1328
|
} else if (recipient != null) {
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
logger$1.error("Actor {recipient} not found.", { recipient });
|
|
1329
|
+
if (await actorDispatcher(ctx, recipient) == null) {
|
|
1330
|
+
logger.error("Actor {recipient} not found.", { recipient });
|
|
1354
1331
|
span.setStatus({
|
|
1355
1332
|
code: SpanStatusCode.ERROR,
|
|
1356
1333
|
message: `Actor ${recipient} not found.`
|
|
@@ -1359,7 +1336,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1359
1336
|
}
|
|
1360
1337
|
}
|
|
1361
1338
|
if (request.bodyUsed) {
|
|
1362
|
-
logger
|
|
1339
|
+
logger.error("Request body has already been read.", { recipient });
|
|
1363
1340
|
span.setStatus({
|
|
1364
1341
|
code: SpanStatusCode.ERROR,
|
|
1365
1342
|
message: "Request body has already been read."
|
|
@@ -1369,7 +1346,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1369
1346
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1370
1347
|
});
|
|
1371
1348
|
} else if (request.body?.locked) {
|
|
1372
|
-
logger
|
|
1349
|
+
logger.error("Request body is locked.", { recipient });
|
|
1373
1350
|
span.setStatus({
|
|
1374
1351
|
code: SpanStatusCode.ERROR,
|
|
1375
1352
|
message: "Request body is locked."
|
|
@@ -1383,15 +1360,15 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1383
1360
|
try {
|
|
1384
1361
|
json = await request.clone().json();
|
|
1385
1362
|
} catch (error) {
|
|
1386
|
-
logger
|
|
1363
|
+
logger.error("Failed to parse JSON:\n{error}", {
|
|
1387
1364
|
recipient,
|
|
1388
1365
|
error
|
|
1389
1366
|
});
|
|
1390
1367
|
try {
|
|
1391
1368
|
await inboxErrorHandler?.(ctx, error);
|
|
1392
|
-
} catch (error
|
|
1393
|
-
logger
|
|
1394
|
-
error
|
|
1369
|
+
} catch (error) {
|
|
1370
|
+
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
1371
|
+
error,
|
|
1395
1372
|
activity: json,
|
|
1396
1373
|
recipient
|
|
1397
1374
|
});
|
|
@@ -1416,7 +1393,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1416
1393
|
});
|
|
1417
1394
|
} catch (error) {
|
|
1418
1395
|
if (error instanceof Error && error.name === "jsonld.SyntaxError") {
|
|
1419
|
-
logger
|
|
1396
|
+
logger.error("Failed to parse JSON-LD:\n{error}", {
|
|
1420
1397
|
recipient,
|
|
1421
1398
|
error
|
|
1422
1399
|
});
|
|
@@ -1430,13 +1407,13 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1430
1407
|
const jsonWithoutSig = detachSignature(json);
|
|
1431
1408
|
let activity = null;
|
|
1432
1409
|
if (ldSigVerified) {
|
|
1433
|
-
logger
|
|
1410
|
+
logger.debug("Linked Data Signatures are verified.", {
|
|
1434
1411
|
recipient,
|
|
1435
1412
|
json
|
|
1436
1413
|
});
|
|
1437
1414
|
activity = await Activity.fromJsonLd(jsonWithoutSig, ctx);
|
|
1438
1415
|
} else {
|
|
1439
|
-
logger
|
|
1416
|
+
logger.debug("Linked Data Signatures are not verified.", {
|
|
1440
1417
|
recipient,
|
|
1441
1418
|
json
|
|
1442
1419
|
});
|
|
@@ -1448,16 +1425,16 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1448
1425
|
tracerProvider
|
|
1449
1426
|
});
|
|
1450
1427
|
} catch (error) {
|
|
1451
|
-
logger
|
|
1428
|
+
logger.error("Failed to parse activity:\n{error}", {
|
|
1452
1429
|
recipient,
|
|
1453
1430
|
activity: json,
|
|
1454
1431
|
error
|
|
1455
1432
|
});
|
|
1456
1433
|
try {
|
|
1457
1434
|
await inboxErrorHandler?.(ctx, error);
|
|
1458
|
-
} catch (error
|
|
1459
|
-
logger
|
|
1460
|
-
error
|
|
1435
|
+
} catch (error) {
|
|
1436
|
+
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
1437
|
+
error,
|
|
1461
1438
|
activity: json,
|
|
1462
1439
|
recipient
|
|
1463
1440
|
});
|
|
@@ -1471,11 +1448,11 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1471
1448
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1472
1449
|
});
|
|
1473
1450
|
}
|
|
1474
|
-
if (activity == null) logger
|
|
1451
|
+
if (activity == null) logger.debug("Object Integrity Proofs are not verified.", {
|
|
1475
1452
|
recipient,
|
|
1476
1453
|
activity: json
|
|
1477
1454
|
});
|
|
1478
|
-
else logger
|
|
1455
|
+
else logger.debug("Object Integrity Proofs are verified.", {
|
|
1479
1456
|
recipient,
|
|
1480
1457
|
activity: json
|
|
1481
1458
|
});
|
|
@@ -1491,17 +1468,16 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1491
1468
|
tracerProvider
|
|
1492
1469
|
});
|
|
1493
1470
|
if (key == null) {
|
|
1494
|
-
logger
|
|
1471
|
+
logger.error("Failed to verify the request's HTTP Signatures.", { recipient });
|
|
1495
1472
|
span.setStatus({
|
|
1496
1473
|
code: SpanStatusCode.ERROR,
|
|
1497
1474
|
message: `Failed to verify the request's HTTP Signatures.`
|
|
1498
1475
|
});
|
|
1499
|
-
|
|
1476
|
+
return new Response("Failed to verify the request signature.", {
|
|
1500
1477
|
status: 401,
|
|
1501
1478
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1502
1479
|
});
|
|
1503
|
-
|
|
1504
|
-
} else logger$1.debug("HTTP Signatures are verified.", { recipient });
|
|
1480
|
+
} else logger.debug("HTTP Signatures are verified.", { recipient });
|
|
1505
1481
|
httpSigKey = key;
|
|
1506
1482
|
}
|
|
1507
1483
|
activity = await Activity.fromJsonLd(jsonWithoutSig, ctx);
|
|
@@ -1509,7 +1485,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1509
1485
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
1510
1486
|
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
1511
1487
|
if (httpSigKey != null && !await doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
1512
|
-
logger
|
|
1488
|
+
logger.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
1513
1489
|
activity: json,
|
|
1514
1490
|
recipient,
|
|
1515
1491
|
keyId: httpSigKey.id?.href,
|
|
@@ -1576,12 +1552,12 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1576
1552
|
* @since 1.8.0
|
|
1577
1553
|
*/
|
|
1578
1554
|
const handleCustomCollection = exceptWrapper(_handleCustomCollection);
|
|
1579
|
-
async function _handleCustomCollection(request, { name, values, context
|
|
1555
|
+
async function _handleCustomCollection(request, { name, values, context, tracerProvider, collectionCallbacks: callbacks, filterPredicate }) {
|
|
1580
1556
|
verifyDefined(callbacks);
|
|
1581
1557
|
verifyJsonLdRequest(request);
|
|
1582
|
-
await authIfNeeded(context
|
|
1558
|
+
await authIfNeeded(context, values, callbacks);
|
|
1583
1559
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
1584
|
-
return await new CustomCollectionHandler(name, values, context
|
|
1560
|
+
return await new CustomCollectionHandler(name, values, context, callbacks, tracerProvider, Collection, CollectionPage, filterPredicate).fetchCollection(cursor).toJsonLd().then(respondAsActivity);
|
|
1585
1561
|
}
|
|
1586
1562
|
/**
|
|
1587
1563
|
* Handles an ordered collection request.
|
|
@@ -1595,12 +1571,12 @@ async function _handleCustomCollection(request, { name, values, context: context
|
|
|
1595
1571
|
* @since 1.8.0
|
|
1596
1572
|
*/
|
|
1597
1573
|
const handleOrderedCollection = exceptWrapper(_handleOrderedCollection);
|
|
1598
|
-
async function _handleOrderedCollection(request, { name, values, context
|
|
1574
|
+
async function _handleOrderedCollection(request, { name, values, context, tracerProvider, collectionCallbacks: callbacks, filterPredicate }) {
|
|
1599
1575
|
verifyDefined(callbacks);
|
|
1600
1576
|
verifyJsonLdRequest(request);
|
|
1601
|
-
await authIfNeeded(context
|
|
1577
|
+
await authIfNeeded(context, values, callbacks);
|
|
1602
1578
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
1603
|
-
return await new CustomCollectionHandler(name, values, context
|
|
1579
|
+
return await new CustomCollectionHandler(name, values, context, callbacks, tracerProvider, OrderedCollection, OrderedCollectionPage, filterPredicate).fetchCollection(cursor).toJsonLd().then(respondAsActivity);
|
|
1604
1580
|
}
|
|
1605
1581
|
/**
|
|
1606
1582
|
* Handling custom collections with support for pagination and filtering.
|
|
@@ -1650,17 +1626,17 @@ var CustomCollectionHandler = class {
|
|
|
1650
1626
|
* @param CollectionPage The CollectionPage constructor.
|
|
1651
1627
|
* @param filterPredicate Optional filter predicate for items.
|
|
1652
1628
|
*/
|
|
1653
|
-
constructor(name, values, context
|
|
1654
|
-
this.name = name;
|
|
1629
|
+
constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), Collection, CollectionPage, filterPredicate) {
|
|
1630
|
+
this.name = name$1;
|
|
1655
1631
|
this.values = values;
|
|
1656
|
-
this.context = context
|
|
1632
|
+
this.context = context;
|
|
1657
1633
|
this.callbacks = callbacks;
|
|
1658
1634
|
this.tracerProvider = tracerProvider;
|
|
1659
|
-
this.Collection = Collection
|
|
1660
|
-
this.CollectionPage = CollectionPage
|
|
1635
|
+
this.Collection = Collection;
|
|
1636
|
+
this.CollectionPage = CollectionPage;
|
|
1661
1637
|
this.filterPredicate = filterPredicate;
|
|
1662
1638
|
this.name = this.name.trim().replace(/\s+/g, "_");
|
|
1663
|
-
this.#tracer = this.tracerProvider.getTracer(
|
|
1639
|
+
this.#tracer = this.tracerProvider.getTracer(name, version);
|
|
1664
1640
|
this.#id = new URL(this.context.url);
|
|
1665
1641
|
this.#dispatcher = callbacks.dispatcher.bind(callbacks);
|
|
1666
1642
|
}
|
|
@@ -1689,8 +1665,8 @@ var CustomCollectionHandler = class {
|
|
|
1689
1665
|
*/
|
|
1690
1666
|
async getCollection(cursor = null) {
|
|
1691
1667
|
if (cursor !== null) {
|
|
1692
|
-
const props
|
|
1693
|
-
return new this.CollectionPage(props
|
|
1668
|
+
const props = await this.getPageProps(cursor);
|
|
1669
|
+
return new this.CollectionPage(props);
|
|
1694
1670
|
}
|
|
1695
1671
|
const firstCursor = await this.firstCursor;
|
|
1696
1672
|
const props = typeof firstCursor === "string" ? await this.getProps(firstCursor) : await this.getPropsWithoutCursor();
|
|
@@ -1838,7 +1814,7 @@ var CustomCollectionHandler = class {
|
|
|
1838
1814
|
* @param value The total items count or a promise that resolves to it.
|
|
1839
1815
|
*/
|
|
1840
1816
|
set totalItems(value) {
|
|
1841
|
-
const toNumber = (value
|
|
1817
|
+
const toNumber = (value) => value == null ? null : Number(value);
|
|
1842
1818
|
this.#totalItems = value instanceof Promise ? value.then(toNumber) : Promise.resolve(toNumber(value));
|
|
1843
1819
|
}
|
|
1844
1820
|
/**
|
|
@@ -1912,11 +1888,9 @@ const verifyJsonLdRequest = (request) => {
|
|
|
1912
1888
|
* @throws {UnauthorizedError} If authorization fails.
|
|
1913
1889
|
* @since 1.8.0
|
|
1914
1890
|
*/
|
|
1915
|
-
const authIfNeeded = async (context
|
|
1891
|
+
const authIfNeeded = async (context, values, { authorizePredicate: authorize = void 0 }) => {
|
|
1916
1892
|
if (authorize === void 0) return;
|
|
1917
|
-
|
|
1918
|
-
const keyOwner = (await context$1.getSignedKeyOwner())?.clone({}, warning.keyOwner) ?? null;
|
|
1919
|
-
if (!await authorize(context$1, values, key, keyOwner)) throw new UnauthorizedError();
|
|
1893
|
+
if (!await authorize(context, values, (await context.getSignedKey())?.clone({}, warning.key) ?? null, (await context.getSignedKeyOwner())?.clone({}, warning.keyOwner) ?? null)) throw new UnauthorizedError();
|
|
1920
1894
|
};
|
|
1921
1895
|
/** Warning messages for `authIfNeeded`. */
|
|
1922
1896
|
const warning = {
|
|
@@ -2030,7 +2004,6 @@ async function respondWithObjectIfAcceptable(object, request, options) {
|
|
|
2030
2004
|
response.headers.set("Vary", "Accept");
|
|
2031
2005
|
return response;
|
|
2032
2006
|
}
|
|
2033
|
-
|
|
2034
2007
|
//#endregion
|
|
2035
2008
|
//#region src/nodeinfo/handler.ts
|
|
2036
2009
|
/**
|
|
@@ -2040,10 +2013,9 @@ async function respondWithObjectIfAcceptable(object, request, options) {
|
|
|
2040
2013
|
* @param parameters The parameters for handling the request.
|
|
2041
2014
|
* @returns The response to the request.
|
|
2042
2015
|
*/
|
|
2043
|
-
async function handleNodeInfo(_request, { context
|
|
2044
|
-
const promise = nodeInfoDispatcher(context
|
|
2045
|
-
const
|
|
2046
|
-
const json = nodeInfoToJson(nodeInfo);
|
|
2016
|
+
async function handleNodeInfo(_request, { context, nodeInfoDispatcher }) {
|
|
2017
|
+
const promise = nodeInfoDispatcher(context);
|
|
2018
|
+
const json = nodeInfoToJson(promise instanceof Promise ? await promise : promise);
|
|
2047
2019
|
return new Response(JSON.stringify(json), { headers: { "Content-Type": "application/json; profile=\"http://nodeinfo.diaspora.software/ns/schema/2.1#\"" } });
|
|
2048
2020
|
}
|
|
2049
2021
|
/**
|
|
@@ -2053,22 +2025,20 @@ async function handleNodeInfo(_request, { context: context$1, nodeInfoDispatcher
|
|
|
2053
2025
|
* @param context The request context.
|
|
2054
2026
|
* @returns The response to the request.
|
|
2055
2027
|
*/
|
|
2056
|
-
function handleNodeInfoJrd(_request, context
|
|
2028
|
+
function handleNodeInfoJrd(_request, context) {
|
|
2057
2029
|
const links = [];
|
|
2058
2030
|
try {
|
|
2059
2031
|
links.push({
|
|
2060
2032
|
rel: "http://nodeinfo.diaspora.software/ns/schema/2.1",
|
|
2061
|
-
href: context
|
|
2033
|
+
href: context.getNodeInfoUri().href,
|
|
2062
2034
|
type: "application/json; profile=\"http://nodeinfo.diaspora.software/ns/schema/2.1#\""
|
|
2063
2035
|
});
|
|
2064
2036
|
} catch (e) {
|
|
2065
2037
|
if (!(e instanceof RouterError)) throw e;
|
|
2066
2038
|
}
|
|
2067
|
-
const
|
|
2068
|
-
const response = new Response(JSON.stringify(jrd), { headers: { "Content-Type": "application/jrd+json" } });
|
|
2039
|
+
const response = new Response(JSON.stringify({ links }), { headers: { "Content-Type": "application/jrd+json" } });
|
|
2069
2040
|
return Promise.resolve(response);
|
|
2070
2041
|
}
|
|
2071
|
-
|
|
2072
2042
|
//#endregion
|
|
2073
2043
|
//#region src/webfinger/handler.ts
|
|
2074
2044
|
const logger = getLogger([
|
|
@@ -2101,12 +2071,12 @@ async function handleWebFinger(request, options) {
|
|
|
2101
2071
|
}
|
|
2102
2072
|
});
|
|
2103
2073
|
}
|
|
2104
|
-
async function handleWebFingerInternal(request, { context
|
|
2074
|
+
async function handleWebFingerInternal(request, { context, host, actorDispatcher, actorHandleMapper, actorAliasMapper, onNotFound, span, webFingerLinksDispatcher }) {
|
|
2105
2075
|
if (actorDispatcher == null) {
|
|
2106
2076
|
logger.error("Actor dispatcher is not set.");
|
|
2107
2077
|
return await onNotFound(request);
|
|
2108
2078
|
}
|
|
2109
|
-
const resource = context
|
|
2079
|
+
const resource = context.url.searchParams.get("resource");
|
|
2110
2080
|
if (resource == null) return new Response("Missing resource parameter.", { status: 400 });
|
|
2111
2081
|
span?.setAttribute("webfinger.resource", resource);
|
|
2112
2082
|
let resourceUrl;
|
|
@@ -2122,26 +2092,26 @@ async function handleWebFingerInternal(request, { context: context$1, host, acto
|
|
|
2122
2092
|
logger.error("No actor handle mapper is set; use the WebFinger username {username} as the actor's internal identifier.", { username });
|
|
2123
2093
|
return username;
|
|
2124
2094
|
}
|
|
2125
|
-
const identifier
|
|
2126
|
-
if (identifier
|
|
2095
|
+
const identifier = await actorHandleMapper(context, username);
|
|
2096
|
+
if (identifier == null) {
|
|
2127
2097
|
logger.error("Actor {username} not found.", { username });
|
|
2128
2098
|
return null;
|
|
2129
2099
|
}
|
|
2130
|
-
return identifier
|
|
2100
|
+
return identifier;
|
|
2131
2101
|
}
|
|
2132
2102
|
let identifier = null;
|
|
2133
|
-
const uriParsed = context
|
|
2103
|
+
const uriParsed = context.parseUri(resourceUrl);
|
|
2134
2104
|
if (uriParsed?.type != "actor") {
|
|
2135
2105
|
const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
|
|
2136
2106
|
if (match == null) {
|
|
2137
|
-
const result = await actorAliasMapper?.(context
|
|
2107
|
+
const result = await actorAliasMapper?.(context, resourceUrl);
|
|
2138
2108
|
if (result == null) return await onNotFound(request);
|
|
2139
2109
|
if ("identifier" in result) identifier = result.identifier;
|
|
2140
2110
|
else identifier = await mapUsernameToIdentifier(result.username);
|
|
2141
2111
|
} else {
|
|
2142
2112
|
const portMatch = /:\d+$/.exec(match[2]);
|
|
2143
2113
|
const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
|
|
2144
|
-
if (normalizedHost != context
|
|
2114
|
+
if (normalizedHost != context.url.host && normalizedHost != host) return await onNotFound(request);
|
|
2145
2115
|
else {
|
|
2146
2116
|
identifier = await mapUsernameToIdentifier(match[1]);
|
|
2147
2117
|
resourceUrl = new URL(`acct:${match[1]}@${normalizedHost}`);
|
|
@@ -2149,14 +2119,14 @@ async function handleWebFingerInternal(request, { context: context$1, host, acto
|
|
|
2149
2119
|
}
|
|
2150
2120
|
} else identifier = uriParsed.identifier;
|
|
2151
2121
|
if (identifier == null) return await onNotFound(request);
|
|
2152
|
-
const actor = await actorDispatcher(context
|
|
2122
|
+
const actor = await actorDispatcher(context, identifier);
|
|
2153
2123
|
if (actor == null) {
|
|
2154
2124
|
logger.error("Actor {identifier} not found.", { identifier });
|
|
2155
2125
|
return await onNotFound(request);
|
|
2156
2126
|
}
|
|
2157
2127
|
const links = [{
|
|
2158
2128
|
rel: "self",
|
|
2159
|
-
href: context
|
|
2129
|
+
href: context.getActorUri(identifier).href,
|
|
2160
2130
|
type: "application/activity+json"
|
|
2161
2131
|
}];
|
|
2162
2132
|
for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
|
|
@@ -2178,16 +2148,16 @@ async function handleWebFingerInternal(request, { context: context$1, host, acto
|
|
|
2178
2148
|
links.push(link);
|
|
2179
2149
|
}
|
|
2180
2150
|
if (webFingerLinksDispatcher != null) {
|
|
2181
|
-
const customLinks = await webFingerLinksDispatcher(context
|
|
2151
|
+
const customLinks = await webFingerLinksDispatcher(context, resourceUrl);
|
|
2182
2152
|
if (customLinks != null) for (const link of customLinks) links.push(link);
|
|
2183
2153
|
}
|
|
2184
2154
|
const aliases = [];
|
|
2185
2155
|
if (resourceUrl.protocol != "acct:" && actor.preferredUsername != null) {
|
|
2186
|
-
aliases.push(`acct:${actor.preferredUsername}@${host ?? context
|
|
2187
|
-
if (host != null && host !== context
|
|
2156
|
+
aliases.push(`acct:${actor.preferredUsername}@${host ?? context.url.host}`);
|
|
2157
|
+
if (host != null && host !== context.url.host) aliases.push(`acct:${actor.preferredUsername}@${context.url.host}`);
|
|
2188
2158
|
}
|
|
2189
|
-
if (resourceUrl.href !== context
|
|
2190
|
-
if (resourceUrl.protocol === "acct:" && host != null && host !== context
|
|
2159
|
+
if (resourceUrl.href !== context.getActorUri(identifier).href) aliases.push(context.getActorUri(identifier).href);
|
|
2160
|
+
if (resourceUrl.protocol === "acct:" && host != null && host !== context.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
|
|
2191
2161
|
const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
|
|
2192
2162
|
aliases.push(`acct:${username}@${host}`);
|
|
2193
2163
|
}
|
|
@@ -2201,7 +2171,6 @@ async function handleWebFingerInternal(request, { context: context$1, host, acto
|
|
|
2201
2171
|
"Access-Control-Allow-Origin": "*"
|
|
2202
2172
|
} });
|
|
2203
2173
|
}
|
|
2204
|
-
|
|
2205
2174
|
//#endregion
|
|
2206
2175
|
//#region src/federation/retry.ts
|
|
2207
2176
|
/**
|
|
@@ -2228,11 +2197,10 @@ function createExponentialBackoffPolicy(options = {}) {
|
|
|
2228
2197
|
milliseconds *= 1 + Math.random();
|
|
2229
2198
|
milliseconds = Math.round(milliseconds);
|
|
2230
2199
|
}
|
|
2231
|
-
const delay
|
|
2232
|
-
return Temporal.Duration.compare(delay
|
|
2200
|
+
const delay = Temporal.Duration.from({ milliseconds });
|
|
2201
|
+
return Temporal.Duration.compare(delay, maxDelay) > 0 ? maxDelay : delay;
|
|
2233
2202
|
};
|
|
2234
2203
|
}
|
|
2235
|
-
|
|
2236
2204
|
//#endregion
|
|
2237
2205
|
//#region src/federation/send.ts
|
|
2238
2206
|
/**
|
|
@@ -2270,8 +2238,7 @@ function extractInboxes({ recipients, preferSharedInbox, excludeBaseUris }) {
|
|
|
2270
2238
|
*/
|
|
2271
2239
|
function sendActivity(options) {
|
|
2272
2240
|
const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
|
|
2273
|
-
|
|
2274
|
-
return tracer.startActiveSpan("activitypub.send_activity", {
|
|
2241
|
+
return tracerProvider.getTracer(name, version).startActiveSpan("activitypub.send_activity", {
|
|
2275
2242
|
kind: SpanKind.CLIENT,
|
|
2276
2243
|
attributes: { "activitypub.shared_inbox": options.sharedInbox ?? false }
|
|
2277
2244
|
}, async (span) => {
|
|
@@ -2294,7 +2261,7 @@ function sendActivity(options) {
|
|
|
2294
2261
|
});
|
|
2295
2262
|
}
|
|
2296
2263
|
async function sendActivityInternal({ activity, activityId, keys, inbox, headers, specDeterminer, tracerProvider }) {
|
|
2297
|
-
const logger
|
|
2264
|
+
const logger = getLogger([
|
|
2298
2265
|
"fedify",
|
|
2299
2266
|
"federation",
|
|
2300
2267
|
"outbox"
|
|
@@ -2311,7 +2278,7 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
|
|
|
2311
2278
|
rsaKey = key;
|
|
2312
2279
|
break;
|
|
2313
2280
|
}
|
|
2314
|
-
if (rsaKey == null) logger
|
|
2281
|
+
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.", {
|
|
2315
2282
|
inbox: inbox.href,
|
|
2316
2283
|
keys: keys.map((pair) => ({
|
|
2317
2284
|
keyId: pair.keyId.href,
|
|
@@ -2325,7 +2292,7 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
|
|
|
2325
2292
|
specDeterminer
|
|
2326
2293
|
});
|
|
2327
2294
|
} catch (error) {
|
|
2328
|
-
logger
|
|
2295
|
+
logger.error("Failed to send activity {activityId} to {inbox}:\n{error}", {
|
|
2329
2296
|
activityId,
|
|
2330
2297
|
inbox: inbox.href,
|
|
2331
2298
|
error
|
|
@@ -2339,7 +2306,7 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
|
|
|
2339
2306
|
} catch (_) {
|
|
2340
2307
|
error = "";
|
|
2341
2308
|
}
|
|
2342
|
-
logger
|
|
2309
|
+
logger.error("Failed to send activity {activityId} to {inbox} ({status} {statusText}):\n{error}", {
|
|
2343
2310
|
activityId,
|
|
2344
2311
|
inbox: inbox.href,
|
|
2345
2312
|
status: response.status,
|
|
@@ -2349,9 +2316,15 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
|
|
|
2349
2316
|
throw new Error(`Failed to send activity ${activityId} to ${inbox.href} (${response.status} ${response.statusText}):\n${error}`);
|
|
2350
2317
|
}
|
|
2351
2318
|
}
|
|
2352
|
-
|
|
2353
2319
|
//#endregion
|
|
2354
2320
|
//#region src/federation/middleware.ts
|
|
2321
|
+
var middleware_exports = /* @__PURE__ */ __exportAll({
|
|
2322
|
+
ContextImpl: () => ContextImpl,
|
|
2323
|
+
FederationImpl: () => FederationImpl,
|
|
2324
|
+
InboxContextImpl: () => InboxContextImpl,
|
|
2325
|
+
KvSpecDeterminer: () => KvSpecDeterminer,
|
|
2326
|
+
createFederation: () => createFederation
|
|
2327
|
+
});
|
|
2355
2328
|
/**
|
|
2356
2329
|
* Create a new {@link Federation} instance.
|
|
2357
2330
|
* @param parameters Parameters for initializing the instance.
|
|
@@ -2387,7 +2360,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2387
2360
|
firstKnock;
|
|
2388
2361
|
constructor(options) {
|
|
2389
2362
|
super();
|
|
2390
|
-
const logger
|
|
2363
|
+
const logger = getLogger(["fedify", "federation"]);
|
|
2391
2364
|
this.kv = options.kv;
|
|
2392
2365
|
this.kvPrefixes = {
|
|
2393
2366
|
activityIdempotence: ["_fedify", "activityIdempotence"],
|
|
@@ -2444,7 +2417,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2444
2417
|
if (options.documentLoader != null) {
|
|
2445
2418
|
if (options.documentLoaderFactory != null) throw new TypeError("Cannot set both documentLoader and documentLoaderFactory options at a time; use documentLoaderFactory only.");
|
|
2446
2419
|
this.documentLoaderFactory = () => options.documentLoader;
|
|
2447
|
-
logger
|
|
2420
|
+
logger.warn("The documentLoader option is deprecated; use documentLoaderFactory option instead.");
|
|
2448
2421
|
} else this.documentLoaderFactory = options.documentLoaderFactory ?? ((opts) => {
|
|
2449
2422
|
return kvCache({
|
|
2450
2423
|
loader: getDocumentLoader({
|
|
@@ -2458,7 +2431,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2458
2431
|
if (options.contextLoader != null) {
|
|
2459
2432
|
if (options.contextLoaderFactory != null) throw new TypeError("Cannot set both contextLoader and contextLoaderFactory options at a time; use contextLoaderFactory only.");
|
|
2460
2433
|
this.contextLoaderFactory = () => options.contextLoader;
|
|
2461
|
-
logger
|
|
2434
|
+
logger.warn("The contextLoader option is deprecated; use contextLoaderFactory option instead.");
|
|
2462
2435
|
} else this.contextLoaderFactory = options.contextLoaderFactory ?? this.documentLoaderFactory;
|
|
2463
2436
|
this.authenticatedDocumentLoaderFactory = options.authenticatedDocumentLoaderFactory ?? ((identity) => getAuthenticatedDocumentLoader(identity, {
|
|
2464
2437
|
allowPrivateAddress,
|
|
@@ -2481,28 +2454,28 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2481
2454
|
this.router.add("/.well-known/nodeinfo", "nodeInfoJrd");
|
|
2482
2455
|
}
|
|
2483
2456
|
_getTracer() {
|
|
2484
|
-
return this.tracerProvider.getTracer(
|
|
2457
|
+
return this.tracerProvider.getTracer(name, version);
|
|
2485
2458
|
}
|
|
2486
2459
|
async _startQueueInternal(ctxData, signal, queue) {
|
|
2487
2460
|
if (this.inboxQueue == null && this.outboxQueue == null) return;
|
|
2488
|
-
const logger
|
|
2461
|
+
const logger = getLogger([
|
|
2489
2462
|
"fedify",
|
|
2490
2463
|
"federation",
|
|
2491
2464
|
"queue"
|
|
2492
2465
|
]);
|
|
2493
2466
|
const promises = [];
|
|
2494
2467
|
if (this.inboxQueue != null && (queue == null || queue === "inbox") && !this.inboxQueueStarted) {
|
|
2495
|
-
logger
|
|
2468
|
+
logger.debug("Starting an inbox task worker.");
|
|
2496
2469
|
this.inboxQueueStarted = true;
|
|
2497
2470
|
promises.push(this.inboxQueue.listen((msg) => this.processQueuedTask(ctxData, msg), { signal }));
|
|
2498
2471
|
}
|
|
2499
2472
|
if (this.outboxQueue != null && this.outboxQueue !== this.inboxQueue && (queue == null || queue === "outbox") && !this.outboxQueueStarted) {
|
|
2500
|
-
logger
|
|
2473
|
+
logger.debug("Starting an outbox task worker.");
|
|
2501
2474
|
this.outboxQueueStarted = true;
|
|
2502
2475
|
promises.push(this.outboxQueue.listen((msg) => this.processQueuedTask(ctxData, msg), { signal }));
|
|
2503
2476
|
}
|
|
2504
2477
|
if (this.fanoutQueue != null && this.fanoutQueue !== this.inboxQueue && this.fanoutQueue !== this.outboxQueue && (queue == null || queue === "fanout") && !this.fanoutQueueStarted) {
|
|
2505
|
-
logger
|
|
2478
|
+
logger.debug("Starting a fanout task worker.");
|
|
2506
2479
|
this.fanoutQueueStarted = true;
|
|
2507
2480
|
promises.push(this.fanoutQueue.listen((msg) => this.processQueuedTask(ctxData, msg), { signal }));
|
|
2508
2481
|
}
|
|
@@ -2568,12 +2541,11 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2568
2541
|
});
|
|
2569
2542
|
}
|
|
2570
2543
|
async #listenFanoutMessage(data, message) {
|
|
2571
|
-
|
|
2544
|
+
getLogger([
|
|
2572
2545
|
"fedify",
|
|
2573
2546
|
"federation",
|
|
2574
2547
|
"fanout"
|
|
2575
|
-
])
|
|
2576
|
-
logger$1.debug("Fanning out activity {activityId} to {inboxes} inbox(es)...", {
|
|
2548
|
+
]).debug("Fanning out activity {activityId} to {inboxes} inbox(es)...", {
|
|
2577
2549
|
activityId: message.activityId,
|
|
2578
2550
|
inboxes: globalThis.Object.keys(message.inboxes).length
|
|
2579
2551
|
});
|
|
@@ -2592,17 +2564,17 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2592
2564
|
}),
|
|
2593
2565
|
tracerProvider: this.tracerProvider
|
|
2594
2566
|
});
|
|
2595
|
-
const context
|
|
2567
|
+
const context = this.#createContext(new URL(message.baseUrl), data, { documentLoader: this.documentLoaderFactory({
|
|
2596
2568
|
allowPrivateAddress: this.allowPrivateAddress,
|
|
2597
2569
|
userAgent: this.userAgent
|
|
2598
2570
|
}) });
|
|
2599
2571
|
await this.sendActivity(keys, message.inboxes, activity, {
|
|
2600
2572
|
collectionSync: message.collectionSync,
|
|
2601
|
-
context
|
|
2573
|
+
context
|
|
2602
2574
|
});
|
|
2603
2575
|
}
|
|
2604
2576
|
async #listenOutboxMessage(_, message, span) {
|
|
2605
|
-
const logger
|
|
2577
|
+
const logger = getLogger([
|
|
2606
2578
|
"fedify",
|
|
2607
2579
|
"federation",
|
|
2608
2580
|
"outbox"
|
|
@@ -2650,65 +2622,64 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2650
2622
|
});
|
|
2651
2623
|
try {
|
|
2652
2624
|
this.onOutboxError?.(error, activity);
|
|
2653
|
-
} catch (error
|
|
2654
|
-
logger
|
|
2625
|
+
} catch (error) {
|
|
2626
|
+
logger.error("An unexpected error occurred in onError handler:\n{error}", {
|
|
2655
2627
|
...logData,
|
|
2656
|
-
error
|
|
2628
|
+
error
|
|
2657
2629
|
});
|
|
2658
2630
|
}
|
|
2659
2631
|
if (this.outboxQueue?.nativeRetrial) {
|
|
2660
|
-
logger
|
|
2632
|
+
logger.error("Failed to send activity {activityId} to {inbox}; backend will handle retry:\n{error}", {
|
|
2661
2633
|
...logData,
|
|
2662
2634
|
error
|
|
2663
2635
|
});
|
|
2664
2636
|
throw error;
|
|
2665
2637
|
}
|
|
2666
|
-
const delay
|
|
2638
|
+
const delay = this.outboxRetryPolicy({
|
|
2667
2639
|
elapsedTime: Temporal.Instant.from(message.started).until(Temporal.Now.instant()),
|
|
2668
2640
|
attempts: message.attempt
|
|
2669
2641
|
});
|
|
2670
|
-
if (delay
|
|
2671
|
-
logger
|
|
2642
|
+
if (delay != null) {
|
|
2643
|
+
logger.error("Failed to send activity {activityId} to {inbox} (attempt #{attempt}); retry...:\n{error}", {
|
|
2672
2644
|
...logData,
|
|
2673
2645
|
error
|
|
2674
2646
|
});
|
|
2675
2647
|
await this.outboxQueue?.enqueue({
|
|
2676
2648
|
...message,
|
|
2677
2649
|
attempt: message.attempt + 1
|
|
2678
|
-
}, { delay: Temporal.Duration.compare(delay
|
|
2679
|
-
} else logger
|
|
2650
|
+
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2651
|
+
} else logger.error("Failed to send activity {activityId} to {inbox} after {attempt} attempts; giving up:\n{error}", {
|
|
2680
2652
|
...logData,
|
|
2681
2653
|
error
|
|
2682
2654
|
});
|
|
2683
2655
|
return;
|
|
2684
2656
|
}
|
|
2685
|
-
logger
|
|
2657
|
+
logger.info("Successfully sent activity {activityId} to {inbox}.", { ...logData });
|
|
2686
2658
|
}
|
|
2687
2659
|
async #listenInboxMessage(ctxData, message, span) {
|
|
2688
|
-
const logger
|
|
2660
|
+
const logger = getLogger([
|
|
2689
2661
|
"fedify",
|
|
2690
2662
|
"federation",
|
|
2691
2663
|
"inbox"
|
|
2692
2664
|
]);
|
|
2693
2665
|
const baseUrl = new URL(message.baseUrl);
|
|
2694
|
-
let context
|
|
2695
|
-
if (message.identifier != null) context
|
|
2666
|
+
let context = this.#createContext(baseUrl, ctxData);
|
|
2667
|
+
if (message.identifier != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: await context.getDocumentLoader({ identifier: message.identifier }) });
|
|
2696
2668
|
else if (this.sharedInboxKeyDispatcher != null) {
|
|
2697
|
-
const identity = await this.sharedInboxKeyDispatcher(context
|
|
2698
|
-
if (identity != null) context
|
|
2669
|
+
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
2670
|
+
if (identity != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: "identifier" in identity || "username" in identity || "handle" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
2699
2671
|
}
|
|
2700
|
-
const activity = await Activity.fromJsonLd(message.activity, context
|
|
2672
|
+
const activity = await Activity.fromJsonLd(message.activity, context);
|
|
2701
2673
|
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
2702
2674
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
2703
2675
|
const cacheKey = activity.id == null ? null : [
|
|
2704
2676
|
...this.kvPrefixes.activityIdempotence,
|
|
2705
|
-
context
|
|
2677
|
+
context.origin,
|
|
2706
2678
|
activity.id.href
|
|
2707
2679
|
];
|
|
2708
2680
|
if (cacheKey != null) {
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
logger$1.debug("Activity {activityId} has already been processed.", {
|
|
2681
|
+
if (await this.kv.get(cacheKey) === true) {
|
|
2682
|
+
logger.debug("Activity {activityId} has already been processed.", {
|
|
2712
2683
|
activityId: activity.id?.href,
|
|
2713
2684
|
activity: message.activity,
|
|
2714
2685
|
recipient: message.identifier
|
|
@@ -2716,32 +2687,32 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2716
2687
|
return;
|
|
2717
2688
|
}
|
|
2718
2689
|
}
|
|
2719
|
-
await this._getTracer().startActiveSpan("activitypub.dispatch_inbox_listener", { kind: SpanKind.INTERNAL }, async (span
|
|
2690
|
+
await this._getTracer().startActiveSpan("activitypub.dispatch_inbox_listener", { kind: SpanKind.INTERNAL }, async (span) => {
|
|
2720
2691
|
const dispatched = this.inboxListeners?.dispatchWithClass(activity);
|
|
2721
2692
|
if (dispatched == null) {
|
|
2722
|
-
logger
|
|
2693
|
+
logger.error("Unsupported activity type:\n{activity}", {
|
|
2723
2694
|
activityId: activity.id?.href,
|
|
2724
2695
|
activity: message.activity,
|
|
2725
2696
|
recipient: message.identifier,
|
|
2726
2697
|
trial: message.attempt
|
|
2727
2698
|
});
|
|
2728
|
-
span
|
|
2699
|
+
span.setStatus({
|
|
2729
2700
|
code: SpanStatusCode.ERROR,
|
|
2730
2701
|
message: `Unsupported activity type: ${getTypeId(activity).href}`
|
|
2731
2702
|
});
|
|
2732
|
-
span
|
|
2703
|
+
span.end();
|
|
2733
2704
|
return;
|
|
2734
2705
|
}
|
|
2735
2706
|
const { class: cls, listener } = dispatched;
|
|
2736
|
-
span
|
|
2707
|
+
span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
|
|
2737
2708
|
try {
|
|
2738
|
-
await listener(context
|
|
2709
|
+
await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, getTypeId(activity).href), activity);
|
|
2739
2710
|
} catch (error) {
|
|
2740
2711
|
try {
|
|
2741
|
-
await this.inboxErrorHandler?.(context
|
|
2742
|
-
} catch (error
|
|
2743
|
-
logger
|
|
2744
|
-
error
|
|
2712
|
+
await this.inboxErrorHandler?.(context, error);
|
|
2713
|
+
} catch (error) {
|
|
2714
|
+
logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
|
|
2715
|
+
error,
|
|
2745
2716
|
trial: message.attempt,
|
|
2746
2717
|
activityId: activity.id?.href,
|
|
2747
2718
|
activity: message.activity,
|
|
@@ -2749,25 +2720,25 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2749
2720
|
});
|
|
2750
2721
|
}
|
|
2751
2722
|
if (this.inboxQueue?.nativeRetrial) {
|
|
2752
|
-
logger
|
|
2723
|
+
logger.error("Failed to process the incoming activity {activityId}; backend will handle retry:\n{error}", {
|
|
2753
2724
|
error,
|
|
2754
2725
|
activityId: activity.id?.href,
|
|
2755
2726
|
activity: message.activity,
|
|
2756
2727
|
recipient: message.identifier
|
|
2757
2728
|
});
|
|
2758
|
-
span
|
|
2729
|
+
span.setStatus({
|
|
2759
2730
|
code: SpanStatusCode.ERROR,
|
|
2760
2731
|
message: String(error)
|
|
2761
2732
|
});
|
|
2762
|
-
span
|
|
2733
|
+
span.end();
|
|
2763
2734
|
throw error;
|
|
2764
2735
|
}
|
|
2765
|
-
const delay
|
|
2736
|
+
const delay = this.inboxRetryPolicy({
|
|
2766
2737
|
elapsedTime: Temporal.Instant.from(message.started).until(Temporal.Now.instant()),
|
|
2767
2738
|
attempts: message.attempt
|
|
2768
2739
|
});
|
|
2769
|
-
if (delay
|
|
2770
|
-
logger
|
|
2740
|
+
if (delay != null) {
|
|
2741
|
+
logger.error("Failed to process the incoming activity {activityId} (attempt #{attempt}); retry...:\n{error}", {
|
|
2771
2742
|
error,
|
|
2772
2743
|
attempt: message.attempt,
|
|
2773
2744
|
activityId: activity.id?.href,
|
|
@@ -2777,27 +2748,27 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2777
2748
|
await this.inboxQueue?.enqueue({
|
|
2778
2749
|
...message,
|
|
2779
2750
|
attempt: message.attempt + 1
|
|
2780
|
-
}, { delay: Temporal.Duration.compare(delay
|
|
2781
|
-
} else logger
|
|
2751
|
+
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2752
|
+
} else logger.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
2782
2753
|
error,
|
|
2783
2754
|
activityId: activity.id?.href,
|
|
2784
2755
|
activity: message.activity,
|
|
2785
2756
|
recipient: message.identifier
|
|
2786
2757
|
});
|
|
2787
|
-
span
|
|
2758
|
+
span.setStatus({
|
|
2788
2759
|
code: SpanStatusCode.ERROR,
|
|
2789
2760
|
message: String(error)
|
|
2790
2761
|
});
|
|
2791
|
-
span
|
|
2762
|
+
span.end();
|
|
2792
2763
|
return;
|
|
2793
2764
|
}
|
|
2794
2765
|
if (cacheKey != null) await this.kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
|
|
2795
|
-
logger
|
|
2766
|
+
logger.info("Activity {activityId} has been processed.", {
|
|
2796
2767
|
activityId: activity.id?.href,
|
|
2797
2768
|
activity: message.activity,
|
|
2798
2769
|
recipient: message.identifier
|
|
2799
2770
|
});
|
|
2800
|
-
span
|
|
2771
|
+
span.end();
|
|
2801
2772
|
});
|
|
2802
2773
|
}
|
|
2803
2774
|
startQueue(contextData, options = {}) {
|
|
@@ -2841,7 +2812,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2841
2812
|
};
|
|
2842
2813
|
}
|
|
2843
2814
|
async sendActivity(keys, inboxes, activity, options) {
|
|
2844
|
-
const logger
|
|
2815
|
+
const logger = getLogger([
|
|
2845
2816
|
"fedify",
|
|
2846
2817
|
"federation",
|
|
2847
2818
|
"outbox"
|
|
@@ -2875,7 +2846,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2875
2846
|
format: "compact",
|
|
2876
2847
|
contextLoader
|
|
2877
2848
|
});
|
|
2878
|
-
if (rsaKey == null) logger
|
|
2849
|
+
if (rsaKey == null) logger.warn("No supported key found to create a Linked Data signature for the activity {activityId}. The activity will be sent without a Linked Data signature. In order to create a Linked Data signature, at least one RSASSA-PKCS1-v1_5 key must be provided.", {
|
|
2879
2850
|
activityId,
|
|
2880
2851
|
keys: keys.map((pair) => ({
|
|
2881
2852
|
keyId: pair.keyId.href,
|
|
@@ -2886,7 +2857,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2886
2857
|
contextLoader,
|
|
2887
2858
|
tracerProvider: this.tracerProvider
|
|
2888
2859
|
});
|
|
2889
|
-
if (!proofCreated) logger
|
|
2860
|
+
if (!proofCreated) logger.warn("No supported key found to create a proof for the activity {activityId}. The activity will be sent without a proof. In order to create a proof, at least one Ed25519 key must be provided.", {
|
|
2890
2861
|
activityId,
|
|
2891
2862
|
keys: keys.map((pair) => ({
|
|
2892
2863
|
keyId: pair.keyId.href,
|
|
@@ -2894,11 +2865,11 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2894
2865
|
}))
|
|
2895
2866
|
});
|
|
2896
2867
|
if (immediate || this.outboxQueue == null) {
|
|
2897
|
-
if (immediate) logger
|
|
2868
|
+
if (immediate) logger.debug("Sending activity immediately without queue since immediate option is set.", {
|
|
2898
2869
|
activityId: activity.id.href,
|
|
2899
2870
|
activity: jsonLd
|
|
2900
2871
|
});
|
|
2901
|
-
else logger
|
|
2872
|
+
else logger.debug("Sending activity immediately without queue since queue is not set.", {
|
|
2902
2873
|
activityId: activity.id.href,
|
|
2903
2874
|
activity: jsonLd
|
|
2904
2875
|
});
|
|
@@ -2917,7 +2888,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2917
2888
|
await Promise.all(promises);
|
|
2918
2889
|
return;
|
|
2919
2890
|
}
|
|
2920
|
-
logger
|
|
2891
|
+
logger.debug("Enqueuing activity {activityId} to send later.", {
|
|
2921
2892
|
activityId: activity.id.href,
|
|
2922
2893
|
activity: jsonLd
|
|
2923
2894
|
});
|
|
@@ -2954,10 +2925,9 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2954
2925
|
const { outboxQueue } = this;
|
|
2955
2926
|
if (outboxQueue.enqueueMany == null) {
|
|
2956
2927
|
const promises = messages.map((m) => outboxQueue.enqueue(m));
|
|
2957
|
-
const
|
|
2958
|
-
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
2928
|
+
const errors = (await Promise.allSettled(promises)).filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
2959
2929
|
if (errors.length > 0) {
|
|
2960
|
-
logger
|
|
2930
|
+
logger.error("Failed to enqueue activity {activityId} to send later: {errors}", {
|
|
2961
2931
|
activityId: activity.id.href,
|
|
2962
2932
|
errors
|
|
2963
2933
|
});
|
|
@@ -2967,7 +2937,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2967
2937
|
} else try {
|
|
2968
2938
|
await outboxQueue.enqueueMany(messages);
|
|
2969
2939
|
} catch (error) {
|
|
2970
|
-
logger
|
|
2940
|
+
logger.error("Failed to enqueue activity {activityId} to send later: {error}", {
|
|
2971
2941
|
activityId: activity.id.href,
|
|
2972
2942
|
error
|
|
2973
2943
|
});
|
|
@@ -2975,8 +2945,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2975
2945
|
}
|
|
2976
2946
|
}
|
|
2977
2947
|
fetch(request, options) {
|
|
2978
|
-
|
|
2979
|
-
return withContext({ requestId }, async () => {
|
|
2948
|
+
return withContext({ requestId: getRequestId(request) }, async () => {
|
|
2980
2949
|
const tracer = this._getTracer();
|
|
2981
2950
|
return await tracer.startActiveSpan(request.method, {
|
|
2982
2951
|
kind: SpanKind.SERVER,
|
|
@@ -2985,7 +2954,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2985
2954
|
[ATTR_URL_FULL]: request.url
|
|
2986
2955
|
}
|
|
2987
2956
|
}, async (span) => {
|
|
2988
|
-
const logger
|
|
2957
|
+
const logger = getLogger([
|
|
2989
2958
|
"fedify",
|
|
2990
2959
|
"federation",
|
|
2991
2960
|
"http"
|
|
@@ -3004,7 +2973,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3004
2973
|
message: `${error}`
|
|
3005
2974
|
});
|
|
3006
2975
|
span.end();
|
|
3007
|
-
logger
|
|
2976
|
+
logger.error("An error occurred while serving request {method} {url}: {error}", {
|
|
3008
2977
|
method: request.method,
|
|
3009
2978
|
url: request.url,
|
|
3010
2979
|
error
|
|
@@ -3028,9 +2997,9 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3028
2997
|
url: request.url,
|
|
3029
2998
|
status: response.status
|
|
3030
2999
|
};
|
|
3031
|
-
if (response.status >= 500) logger
|
|
3032
|
-
else if (response.status >= 400) logger
|
|
3033
|
-
else logger
|
|
3000
|
+
if (response.status >= 500) logger.error(logTpl, values);
|
|
3001
|
+
else if (response.status >= 400) logger.warn(logTpl, values);
|
|
3002
|
+
else logger.info(logTpl, values);
|
|
3034
3003
|
return response;
|
|
3035
3004
|
});
|
|
3036
3005
|
});
|
|
@@ -3043,11 +3012,11 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3043
3012
|
const route = this.router.route(url.pathname);
|
|
3044
3013
|
if (route == null) return await onNotFound(request);
|
|
3045
3014
|
span.updateName(`${request.method} ${route.template}`);
|
|
3046
|
-
let context
|
|
3015
|
+
let context = this.#createContext(request, contextData);
|
|
3047
3016
|
const routeName = route.name.replace(/:.*$/, "");
|
|
3048
3017
|
switch (routeName) {
|
|
3049
3018
|
case "webfinger": return await handleWebFinger(request, {
|
|
3050
|
-
context
|
|
3019
|
+
context,
|
|
3051
3020
|
host: this.origin?.handleHost,
|
|
3052
3021
|
actorDispatcher: this.actorCallbacks?.dispatcher,
|
|
3053
3022
|
actorHandleMapper: this.actorCallbacks?.handleMapper,
|
|
@@ -3056,16 +3025,16 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3056
3025
|
onNotFound,
|
|
3057
3026
|
tracer
|
|
3058
3027
|
});
|
|
3059
|
-
case "nodeInfoJrd": return await handleNodeInfoJrd(request, context
|
|
3028
|
+
case "nodeInfoJrd": return await handleNodeInfoJrd(request, context);
|
|
3060
3029
|
case "nodeInfo": return await handleNodeInfo(request, {
|
|
3061
|
-
context
|
|
3030
|
+
context,
|
|
3062
3031
|
nodeInfoDispatcher: this.nodeInfoDispatcher
|
|
3063
3032
|
});
|
|
3064
3033
|
case "actor":
|
|
3065
|
-
context
|
|
3034
|
+
context = this.#createContext(request, contextData, { invokedFromActorDispatcher: { identifier: route.values.identifier ?? route.values.handle } });
|
|
3066
3035
|
return await handleActor(request, {
|
|
3067
3036
|
identifier: route.values.identifier ?? route.values.handle,
|
|
3068
|
-
context
|
|
3037
|
+
context,
|
|
3069
3038
|
actorDispatcher: this.actorCallbacks?.dispatcher,
|
|
3070
3039
|
authorizePredicate: this.actorCallbacks?.authorizePredicate,
|
|
3071
3040
|
onUnauthorized,
|
|
@@ -3076,13 +3045,13 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3076
3045
|
const typeId = route.name.replace(/^object:/, "");
|
|
3077
3046
|
const callbacks = this.objectCallbacks[typeId];
|
|
3078
3047
|
const cls = this.objectTypeIds[typeId];
|
|
3079
|
-
context
|
|
3048
|
+
context = this.#createContext(request, contextData, { invokedFromObjectDispatcher: {
|
|
3080
3049
|
cls,
|
|
3081
3050
|
values: route.values
|
|
3082
3051
|
} });
|
|
3083
3052
|
return await handleObject(request, {
|
|
3084
3053
|
values: route.values,
|
|
3085
|
-
context
|
|
3054
|
+
context,
|
|
3086
3055
|
objectDispatcher: callbacks?.dispatcher,
|
|
3087
3056
|
authorizePredicate: callbacks?.authorizePredicate,
|
|
3088
3057
|
onUnauthorized,
|
|
@@ -3093,8 +3062,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3093
3062
|
case "outbox": return await handleCollection(request, {
|
|
3094
3063
|
name: "outbox",
|
|
3095
3064
|
identifier: route.values.identifier ?? route.values.handle,
|
|
3096
|
-
uriGetter: context
|
|
3097
|
-
context
|
|
3065
|
+
uriGetter: context.getOutboxUri.bind(context),
|
|
3066
|
+
context,
|
|
3098
3067
|
collectionCallbacks: this.outboxCallbacks,
|
|
3099
3068
|
tracerProvider: this.tracerProvider,
|
|
3100
3069
|
onUnauthorized,
|
|
@@ -3105,25 +3074,25 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3105
3074
|
if (request.method !== "POST") return await handleCollection(request, {
|
|
3106
3075
|
name: "inbox",
|
|
3107
3076
|
identifier: route.values.identifier ?? route.values.handle,
|
|
3108
|
-
uriGetter: context
|
|
3109
|
-
context
|
|
3077
|
+
uriGetter: context.getInboxUri.bind(context),
|
|
3078
|
+
context,
|
|
3110
3079
|
collectionCallbacks: this.inboxCallbacks,
|
|
3111
3080
|
tracerProvider: this.tracerProvider,
|
|
3112
3081
|
onUnauthorized,
|
|
3113
3082
|
onNotFound,
|
|
3114
3083
|
onNotAcceptable
|
|
3115
3084
|
});
|
|
3116
|
-
context
|
|
3085
|
+
context = this.#createContext(request, contextData, { documentLoader: await context.getDocumentLoader({ identifier: route.values.identifier ?? route.values.handle }) });
|
|
3117
3086
|
case "sharedInbox":
|
|
3118
3087
|
if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
|
|
3119
|
-
const identity = await this.sharedInboxKeyDispatcher(context
|
|
3120
|
-
if (identity != null) context
|
|
3088
|
+
const identity = await this.sharedInboxKeyDispatcher(context);
|
|
3089
|
+
if (identity != null) context = this.#createContext(request, contextData, { documentLoader: "identifier" in identity || "username" in identity || "handle" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
|
|
3121
3090
|
}
|
|
3122
3091
|
if (!this.manuallyStartQueue) this._startQueueInternal(contextData);
|
|
3123
3092
|
return await handleInbox(request, {
|
|
3124
3093
|
recipient: route.values.identifier ?? route.values.handle ?? null,
|
|
3125
|
-
context
|
|
3126
|
-
inboxContextFactory: context
|
|
3094
|
+
context,
|
|
3095
|
+
inboxContextFactory: context.toInboxContext.bind(context),
|
|
3127
3096
|
kv: this.kv,
|
|
3128
3097
|
kvPrefixes: this.kvPrefixes,
|
|
3129
3098
|
queue: this.inboxQueue,
|
|
@@ -3139,8 +3108,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3139
3108
|
case "following": return await handleCollection(request, {
|
|
3140
3109
|
name: "following",
|
|
3141
3110
|
identifier: route.values.identifier ?? route.values.handle,
|
|
3142
|
-
uriGetter: context
|
|
3143
|
-
context
|
|
3111
|
+
uriGetter: context.getFollowingUri.bind(context),
|
|
3112
|
+
context,
|
|
3144
3113
|
collectionCallbacks: this.followingCallbacks,
|
|
3145
3114
|
tracerProvider: this.tracerProvider,
|
|
3146
3115
|
onUnauthorized,
|
|
@@ -3157,14 +3126,14 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3157
3126
|
return await handleCollection(request, {
|
|
3158
3127
|
name: "followers",
|
|
3159
3128
|
identifier: route.values.identifier ?? route.values.handle,
|
|
3160
|
-
uriGetter: baseUrl == null ? context
|
|
3161
|
-
const uri = context
|
|
3129
|
+
uriGetter: baseUrl == null ? context.getFollowersUri.bind(context) : (identifier) => {
|
|
3130
|
+
const uri = context.getFollowersUri(identifier);
|
|
3162
3131
|
uri.searchParams.set("base-url", baseUrl);
|
|
3163
3132
|
return uri;
|
|
3164
3133
|
},
|
|
3165
|
-
context
|
|
3134
|
+
context,
|
|
3166
3135
|
filter: baseUrl != null ? new URL(baseUrl) : void 0,
|
|
3167
|
-
filterPredicate: baseUrl != null ? (i) => (i instanceof URL ? i.href : i.id?.href ?? "").startsWith(baseUrl) : void 0,
|
|
3136
|
+
filterPredicate: baseUrl != null ? ((i) => (i instanceof URL ? i.href : i.id?.href ?? "").startsWith(baseUrl)) : void 0,
|
|
3168
3137
|
collectionCallbacks: this.followersCallbacks,
|
|
3169
3138
|
tracerProvider: this.tracerProvider,
|
|
3170
3139
|
onUnauthorized,
|
|
@@ -3175,8 +3144,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3175
3144
|
case "liked": return await handleCollection(request, {
|
|
3176
3145
|
name: "liked",
|
|
3177
3146
|
identifier: route.values.identifier ?? route.values.handle,
|
|
3178
|
-
uriGetter: context
|
|
3179
|
-
context
|
|
3147
|
+
uriGetter: context.getLikedUri.bind(context),
|
|
3148
|
+
context,
|
|
3180
3149
|
collectionCallbacks: this.likedCallbacks,
|
|
3181
3150
|
tracerProvider: this.tracerProvider,
|
|
3182
3151
|
onUnauthorized,
|
|
@@ -3186,8 +3155,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3186
3155
|
case "featured": return await handleCollection(request, {
|
|
3187
3156
|
name: "featured",
|
|
3188
3157
|
identifier: route.values.identifier ?? route.values.handle,
|
|
3189
|
-
uriGetter: context
|
|
3190
|
-
context
|
|
3158
|
+
uriGetter: context.getFeaturedUri.bind(context),
|
|
3159
|
+
context,
|
|
3191
3160
|
collectionCallbacks: this.featuredCallbacks,
|
|
3192
3161
|
tracerProvider: this.tracerProvider,
|
|
3193
3162
|
onUnauthorized,
|
|
@@ -3197,8 +3166,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3197
3166
|
case "featuredTags": return await handleCollection(request, {
|
|
3198
3167
|
name: "featured tags",
|
|
3199
3168
|
identifier: route.values.identifier ?? route.values.handle,
|
|
3200
|
-
uriGetter: context
|
|
3201
|
-
context
|
|
3169
|
+
uriGetter: context.getFeaturedTagsUri.bind(context),
|
|
3170
|
+
context,
|
|
3202
3171
|
collectionCallbacks: this.featuredTagsCallbacks,
|
|
3203
3172
|
tracerProvider: this.tracerProvider,
|
|
3204
3173
|
onUnauthorized,
|
|
@@ -3210,7 +3179,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3210
3179
|
const callbacks = this.collectionCallbacks[name];
|
|
3211
3180
|
return await handleCustomCollection(request, {
|
|
3212
3181
|
name,
|
|
3213
|
-
context
|
|
3182
|
+
context,
|
|
3214
3183
|
values: route.values,
|
|
3215
3184
|
collectionCallbacks: callbacks,
|
|
3216
3185
|
tracerProvider: this.tracerProvider,
|
|
@@ -3224,7 +3193,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3224
3193
|
const callbacks = this.collectionCallbacks[name];
|
|
3225
3194
|
return await handleOrderedCollection(request, {
|
|
3226
3195
|
name,
|
|
3227
|
-
context
|
|
3196
|
+
context,
|
|
3228
3197
|
values: route.values,
|
|
3229
3198
|
collectionCallbacks: callbacks,
|
|
3230
3199
|
tracerProvider: this.tracerProvider,
|
|
@@ -3322,9 +3291,9 @@ var ContextImpl = class ContextImpl {
|
|
|
3322
3291
|
}
|
|
3323
3292
|
getInboxUri(identifier) {
|
|
3324
3293
|
if (identifier == null) {
|
|
3325
|
-
const path
|
|
3326
|
-
if (path
|
|
3327
|
-
return new URL(path
|
|
3294
|
+
const path = this.federation.router.build("sharedInbox", {});
|
|
3295
|
+
if (path == null) throw new RouterError("No shared inbox path registered.");
|
|
3296
|
+
return new URL(path, this.canonicalOrigin);
|
|
3328
3297
|
}
|
|
3329
3298
|
const path = this.federation.router.build("inbox", {
|
|
3330
3299
|
identifier,
|
|
@@ -3382,14 +3351,13 @@ var ContextImpl = class ContextImpl {
|
|
|
3382
3351
|
if (uri == null) return null;
|
|
3383
3352
|
if (uri.origin !== this.origin && uri.origin !== this.canonicalOrigin) return null;
|
|
3384
3353
|
const route = this.federation.router.route(uri.pathname);
|
|
3385
|
-
const logger
|
|
3354
|
+
const logger = getLogger(["fedify", "federation"]);
|
|
3386
3355
|
if (route == null) return null;
|
|
3387
3356
|
else if (route.name === "sharedInbox") return {
|
|
3388
3357
|
type: "inbox",
|
|
3389
3358
|
identifier: void 0,
|
|
3390
3359
|
get handle() {
|
|
3391
|
-
logger
|
|
3392
|
-
return void 0;
|
|
3360
|
+
logger.warn("The ParseUriResult.handle property is deprecated; use ParseUriResult.identifier instead.");
|
|
3393
3361
|
}
|
|
3394
3362
|
};
|
|
3395
3363
|
const identifier = "identifier" in route.values ? route.values.identifier : route.values.handle;
|
|
@@ -3397,7 +3365,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3397
3365
|
type: "actor",
|
|
3398
3366
|
identifier,
|
|
3399
3367
|
get handle() {
|
|
3400
|
-
logger
|
|
3368
|
+
logger.warn("The ParseUriResult.handle property is deprecated; use ParseUriResult.identifier instead.");
|
|
3401
3369
|
return identifier;
|
|
3402
3370
|
}
|
|
3403
3371
|
};
|
|
@@ -3413,7 +3381,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3413
3381
|
type: "inbox",
|
|
3414
3382
|
identifier,
|
|
3415
3383
|
get handle() {
|
|
3416
|
-
logger
|
|
3384
|
+
logger.warn("The ParseUriResult.handle property is deprecated; use ParseUriResult.identifier instead.");
|
|
3417
3385
|
return identifier;
|
|
3418
3386
|
}
|
|
3419
3387
|
};
|
|
@@ -3421,7 +3389,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3421
3389
|
type: "outbox",
|
|
3422
3390
|
identifier,
|
|
3423
3391
|
get handle() {
|
|
3424
|
-
logger
|
|
3392
|
+
logger.warn("The ParseUriResult.handle property is deprecated; use ParseUriResult.identifier instead.");
|
|
3425
3393
|
return identifier;
|
|
3426
3394
|
}
|
|
3427
3395
|
};
|
|
@@ -3429,7 +3397,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3429
3397
|
type: "following",
|
|
3430
3398
|
identifier,
|
|
3431
3399
|
get handle() {
|
|
3432
|
-
logger
|
|
3400
|
+
logger.warn("The ParseUriResult.handle property is deprecated; use ParseUriResult.identifier instead.");
|
|
3433
3401
|
return identifier;
|
|
3434
3402
|
}
|
|
3435
3403
|
};
|
|
@@ -3437,7 +3405,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3437
3405
|
type: "followers",
|
|
3438
3406
|
identifier,
|
|
3439
3407
|
get handle() {
|
|
3440
|
-
logger
|
|
3408
|
+
logger.warn("The ParseUriResult.handle property is deprecated; use ParseUriResult.identifier instead.");
|
|
3441
3409
|
return identifier;
|
|
3442
3410
|
}
|
|
3443
3411
|
};
|
|
@@ -3445,7 +3413,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3445
3413
|
type: "liked",
|
|
3446
3414
|
identifier,
|
|
3447
3415
|
get handle() {
|
|
3448
|
-
logger
|
|
3416
|
+
logger.warn("The ParseUriResult.handle property is deprecated; use ParseUriResult.identifier instead.");
|
|
3449
3417
|
return identifier;
|
|
3450
3418
|
}
|
|
3451
3419
|
};
|
|
@@ -3453,7 +3421,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3453
3421
|
type: "featured",
|
|
3454
3422
|
identifier,
|
|
3455
3423
|
get handle() {
|
|
3456
|
-
logger
|
|
3424
|
+
logger.warn("The ParseUriResult.handle property is deprecated; use ParseUriResult.identifier instead.");
|
|
3457
3425
|
return identifier;
|
|
3458
3426
|
}
|
|
3459
3427
|
};
|
|
@@ -3461,12 +3429,11 @@ var ContextImpl = class ContextImpl {
|
|
|
3461
3429
|
type: "featuredTags",
|
|
3462
3430
|
identifier,
|
|
3463
3431
|
get handle() {
|
|
3464
|
-
logger
|
|
3432
|
+
logger.warn("The ParseUriResult.handle property is deprecated; use ParseUriResult.identifier instead.");
|
|
3465
3433
|
return identifier;
|
|
3466
3434
|
}
|
|
3467
3435
|
};
|
|
3468
|
-
const
|
|
3469
|
-
const collectionRegex = /* @__PURE__ */ new RegExp(`^(${collectionTypes.join("|")}):(.*)$`);
|
|
3436
|
+
const collectionRegex = new RegExp(`^(${["collection", "orderedCollection"].join("|")}):(.*)$`);
|
|
3470
3437
|
const match = route.name.match(collectionRegex);
|
|
3471
3438
|
if (match !== null) {
|
|
3472
3439
|
const [, type, name] = match;
|
|
@@ -3482,12 +3449,12 @@ var ContextImpl = class ContextImpl {
|
|
|
3482
3449
|
return null;
|
|
3483
3450
|
}
|
|
3484
3451
|
async getActorKeyPairs(identifier) {
|
|
3485
|
-
const logger
|
|
3452
|
+
const logger = getLogger([
|
|
3486
3453
|
"fedify",
|
|
3487
3454
|
"federation",
|
|
3488
3455
|
"actor"
|
|
3489
3456
|
]);
|
|
3490
|
-
if (this.invokedFromActorKeyPairsDispatcher != null) logger
|
|
3457
|
+
if (this.invokedFromActorKeyPairsDispatcher != null) logger.warn("Context.getActorKeyPairs({getActorKeyPairsIdentifier}) method is invoked from the actor key pairs dispatcher ({actorKeyPairsDispatcherIdentifier}); this may cause an infinite loop.", {
|
|
3491
3458
|
getActorKeyPairsIdentifier: identifier,
|
|
3492
3459
|
actorKeyPairsDispatcherIdentifier: this.invokedFromActorKeyPairsDispatcher.identifier
|
|
3493
3460
|
});
|
|
@@ -3495,7 +3462,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3495
3462
|
try {
|
|
3496
3463
|
keyPairs = await this.getKeyPairsFromIdentifier(identifier);
|
|
3497
3464
|
} catch (_) {
|
|
3498
|
-
logger
|
|
3465
|
+
logger.warn("No actor key pairs dispatcher registered.");
|
|
3499
3466
|
return [];
|
|
3500
3467
|
}
|
|
3501
3468
|
const owner = this.getActorUri(identifier);
|
|
@@ -3519,7 +3486,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3519
3486
|
return result;
|
|
3520
3487
|
}
|
|
3521
3488
|
async getKeyPairsFromIdentifier(identifier) {
|
|
3522
|
-
const logger
|
|
3489
|
+
const logger = getLogger([
|
|
3523
3490
|
"fedify",
|
|
3524
3491
|
"federation",
|
|
3525
3492
|
"actor"
|
|
@@ -3530,7 +3497,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3530
3497
|
actorUri = this.getActorUri(identifier);
|
|
3531
3498
|
} catch (error) {
|
|
3532
3499
|
if (error instanceof RouterError) {
|
|
3533
|
-
logger
|
|
3500
|
+
logger.warn(error.message);
|
|
3534
3501
|
return [];
|
|
3535
3502
|
}
|
|
3536
3503
|
throw error;
|
|
@@ -3539,7 +3506,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3539
3506
|
...this,
|
|
3540
3507
|
invokedFromActorKeyPairsDispatcher: { identifier }
|
|
3541
3508
|
}), identifier);
|
|
3542
|
-
if (keyPairs.length < 1) logger
|
|
3509
|
+
if (keyPairs.length < 1) logger.warn("No key pairs found for actor {identifier}.", { identifier });
|
|
3543
3510
|
let i = 0;
|
|
3544
3511
|
const result = [];
|
|
3545
3512
|
for (const keyPair of keyPairs) {
|
|
@@ -3587,8 +3554,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3587
3554
|
} else identifierPromise = Promise.resolve(identity.identifier);
|
|
3588
3555
|
return identifierPromise.then((identifier) => {
|
|
3589
3556
|
if (identifier == null) return this.documentLoader;
|
|
3590
|
-
|
|
3591
|
-
return keyPair.then((pair) => pair == null ? this.documentLoader : this.federation.authenticatedDocumentLoaderFactory(pair));
|
|
3557
|
+
return this.getRsaKeyPairFromIdentifier(identifier).then((pair) => pair == null ? this.documentLoader : this.federation.authenticatedDocumentLoaderFactory(pair));
|
|
3592
3558
|
});
|
|
3593
3559
|
}
|
|
3594
3560
|
return this.federation.authenticatedDocumentLoaderFactory(identity);
|
|
@@ -3630,8 +3596,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3630
3596
|
});
|
|
3631
3597
|
}
|
|
3632
3598
|
sendActivity(sender, recipients, activity, options = {}) {
|
|
3633
|
-
|
|
3634
|
-
return tracer.startActiveSpan(this.federation.outboxQueue == null || options.immediate ? "activitypub.outbox" : "activitypub.fanout", {
|
|
3599
|
+
return this.tracerProvider.getTracer(name, version).startActiveSpan(this.federation.outboxQueue == null || options.immediate ? "activitypub.outbox" : "activitypub.fanout", {
|
|
3635
3600
|
kind: this.federation.outboxQueue == null || options.immediate ? SpanKind.CLIENT : SpanKind.PRODUCER,
|
|
3636
3601
|
attributes: {
|
|
3637
3602
|
"activitypub.activity.type": getTypeId(activity).href,
|
|
@@ -3656,7 +3621,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3656
3621
|
});
|
|
3657
3622
|
}
|
|
3658
3623
|
async sendActivityInternal(sender, recipients, activity, options, span) {
|
|
3659
|
-
const logger
|
|
3624
|
+
const logger = getLogger([
|
|
3660
3625
|
"fedify",
|
|
3661
3626
|
"federation",
|
|
3662
3627
|
"outbox"
|
|
@@ -3670,7 +3635,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3670
3635
|
if ("username" in sender) username = sender.username;
|
|
3671
3636
|
else {
|
|
3672
3637
|
username = sender.handle;
|
|
3673
|
-
logger
|
|
3638
|
+
logger.warn("The \"handle\" property for the sender parameter is deprecated; use \"identifier\" or \"username\" instead.", { sender });
|
|
3674
3639
|
}
|
|
3675
3640
|
if (this.federation.actorCallbacks?.handleMapper == null) identifier = username;
|
|
3676
3641
|
else {
|
|
@@ -3706,7 +3671,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3706
3671
|
for (const activityTransformer of this.federation.activityTransformers) activity = activityTransformer(activity, this);
|
|
3707
3672
|
span?.setAttribute("activitypub.activity.id", activity?.id?.href ?? "");
|
|
3708
3673
|
if (activity.actorId == null) {
|
|
3709
|
-
logger
|
|
3674
|
+
logger.error("Activity {activityId} to send does not have an actor.", {
|
|
3710
3675
|
activity,
|
|
3711
3676
|
activityId: activity?.id?.href
|
|
3712
3677
|
});
|
|
@@ -3717,7 +3682,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3717
3682
|
preferSharedInbox: options.preferSharedInbox,
|
|
3718
3683
|
excludeBaseUris: options.excludeBaseUris
|
|
3719
3684
|
});
|
|
3720
|
-
logger
|
|
3685
|
+
logger.debug("Sending activity {activityId} to inboxes:\n{inboxes}", {
|
|
3721
3686
|
inboxes: globalThis.Object.keys(inboxes),
|
|
3722
3687
|
activityId: activity.id?.href,
|
|
3723
3688
|
activity
|
|
@@ -3751,7 +3716,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3751
3716
|
traceContext: carrier
|
|
3752
3717
|
};
|
|
3753
3718
|
if (!this.federation.manuallyStartQueue) this.federation._startQueueInternal(this.data);
|
|
3754
|
-
this.federation.fanoutQueue.enqueue(message);
|
|
3719
|
+
await this.federation.fanoutQueue.enqueue(message);
|
|
3755
3720
|
}
|
|
3756
3721
|
async *getFollowers(identifier) {
|
|
3757
3722
|
if (this.federation.followersCallbacks == null) throw new Error("No followers collection dispatcher registered.");
|
|
@@ -3768,16 +3733,14 @@ var ContextImpl = class ContextImpl {
|
|
|
3768
3733
|
"outbox"
|
|
3769
3734
|
]).warn("Since the followers collection dispatcher returned null for no cursor (i.e., one-shot dispatcher), the pagination is used to fetch \"followers\". However, it is recommended to implement the one-shot dispatcher for better performance.", { identifier });
|
|
3770
3735
|
while (cursor != null) {
|
|
3771
|
-
const result
|
|
3772
|
-
if (result
|
|
3773
|
-
for (const recipient of result
|
|
3774
|
-
cursor = result
|
|
3736
|
+
const result = await this.federation.followersCallbacks.dispatcher(this, identifier, cursor);
|
|
3737
|
+
if (result == null) break;
|
|
3738
|
+
for (const recipient of result.items) yield recipient;
|
|
3739
|
+
cursor = result.nextCursor ?? null;
|
|
3775
3740
|
}
|
|
3776
3741
|
}
|
|
3777
3742
|
routeActivity(recipient, activity, options = {}) {
|
|
3778
|
-
|
|
3779
|
-
const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
|
|
3780
|
-
return tracer.startActiveSpan("activitypub.inbox", {
|
|
3743
|
+
return (this.tracerProvider ?? this.tracerProvider).getTracer(name, version).startActiveSpan("activitypub.inbox", {
|
|
3781
3744
|
kind: this.federation.inboxQueue == null || options.immediate ? SpanKind.INTERNAL : SpanKind.PRODUCER,
|
|
3782
3745
|
attributes: { "activitypub.activity.type": getTypeId(activity).href }
|
|
3783
3746
|
}, async (span) => {
|
|
@@ -3805,7 +3768,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3805
3768
|
});
|
|
3806
3769
|
}
|
|
3807
3770
|
async routeActivityInternal(recipient, activity, options = {}, span) {
|
|
3808
|
-
const logger
|
|
3771
|
+
const logger = getLogger([
|
|
3809
3772
|
"fedify",
|
|
3810
3773
|
"federation",
|
|
3811
3774
|
"inbox"
|
|
@@ -3813,19 +3776,18 @@ var ContextImpl = class ContextImpl {
|
|
|
3813
3776
|
const contextLoader = options.contextLoader ?? this.contextLoader;
|
|
3814
3777
|
const json = await activity.toJsonLd({ contextLoader });
|
|
3815
3778
|
const keyCache = new KvKeyCache(this.federation.kv, this.federation.kvPrefixes.publicKey, this);
|
|
3816
|
-
|
|
3779
|
+
if (await verifyObject(Activity, json, {
|
|
3817
3780
|
contextLoader,
|
|
3818
3781
|
documentLoader: options.documentLoader ?? this.documentLoader,
|
|
3819
3782
|
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
3820
3783
|
keyCache
|
|
3821
|
-
})
|
|
3822
|
-
|
|
3823
|
-
logger$1.debug("Object Integrity Proofs are not verified.", {
|
|
3784
|
+
}) == null) {
|
|
3785
|
+
logger.debug("Object Integrity Proofs are not verified.", {
|
|
3824
3786
|
recipient,
|
|
3825
3787
|
activity: json
|
|
3826
3788
|
});
|
|
3827
3789
|
if (activity.id == null) {
|
|
3828
|
-
logger
|
|
3790
|
+
logger.debug("Activity is missing an ID; unable to fetch.", {
|
|
3829
3791
|
recipient,
|
|
3830
3792
|
activity: json
|
|
3831
3793
|
});
|
|
@@ -3833,26 +3795,26 @@ var ContextImpl = class ContextImpl {
|
|
|
3833
3795
|
}
|
|
3834
3796
|
const fetched = await this.lookupObject(activity.id, options);
|
|
3835
3797
|
if (fetched == null) {
|
|
3836
|
-
logger
|
|
3798
|
+
logger.debug("Failed to fetch the remote activity object {activityId}.", {
|
|
3837
3799
|
recipient,
|
|
3838
3800
|
activity: json,
|
|
3839
3801
|
activityId: activity.id.href
|
|
3840
3802
|
});
|
|
3841
3803
|
return false;
|
|
3842
3804
|
} else if (!(fetched instanceof Activity)) {
|
|
3843
|
-
logger
|
|
3805
|
+
logger.debug("Fetched object is not an Activity.", {
|
|
3844
3806
|
recipient,
|
|
3845
3807
|
activity: await fetched.toJsonLd({ contextLoader })
|
|
3846
3808
|
});
|
|
3847
3809
|
return false;
|
|
3848
3810
|
} else if (fetched.id?.href !== activity.id.href) {
|
|
3849
|
-
logger
|
|
3811
|
+
logger.debug("Fetched activity object has a different ID; failed to verify.", {
|
|
3850
3812
|
recipient,
|
|
3851
3813
|
activity: await fetched.toJsonLd({ contextLoader })
|
|
3852
3814
|
});
|
|
3853
3815
|
return false;
|
|
3854
3816
|
} else if (fetched.actorIds.length < 1) {
|
|
3855
|
-
logger
|
|
3817
|
+
logger.debug("Fetched activity object is missing an actor; unable to verify.", {
|
|
3856
3818
|
recipient,
|
|
3857
3819
|
activity: await fetched.toJsonLd({ contextLoader })
|
|
3858
3820
|
});
|
|
@@ -3860,15 +3822,15 @@ var ContextImpl = class ContextImpl {
|
|
|
3860
3822
|
}
|
|
3861
3823
|
const activityId = fetched.id;
|
|
3862
3824
|
if (!fetched.actorIds.every((actor) => actor.origin === activityId.origin)) {
|
|
3863
|
-
logger
|
|
3825
|
+
logger.debug("Fetched activity object has actors from different origins; unable to verify.", {
|
|
3864
3826
|
recipient,
|
|
3865
3827
|
activity: await fetched.toJsonLd({ contextLoader })
|
|
3866
3828
|
});
|
|
3867
3829
|
return false;
|
|
3868
3830
|
}
|
|
3869
|
-
logger
|
|
3831
|
+
logger.debug("Successfully fetched the remote activity object {activityId}; ignore the original activity and use the fetched one, which is trustworthy.");
|
|
3870
3832
|
activity = fetched;
|
|
3871
|
-
} else logger
|
|
3833
|
+
} else logger.debug("Object Integrity Proofs are verified.", {
|
|
3872
3834
|
recipient,
|
|
3873
3835
|
activity: json
|
|
3874
3836
|
});
|
|
@@ -3994,8 +3956,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
3994
3956
|
});
|
|
3995
3957
|
}
|
|
3996
3958
|
forwardActivity(forwarder, recipients, options) {
|
|
3997
|
-
|
|
3998
|
-
return tracer.startActiveSpan("activitypub.outbox", {
|
|
3959
|
+
return this.tracerProvider.getTracer(name, version).startActiveSpan("activitypub.outbox", {
|
|
3999
3960
|
kind: this.federation.outboxQueue == null || options?.immediate ? SpanKind.CLIENT : SpanKind.PRODUCER,
|
|
4000
3961
|
attributes: { "activitypub.activity.type": this.activityType }
|
|
4001
3962
|
}, async (span) => {
|
|
@@ -4014,7 +3975,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
4014
3975
|
});
|
|
4015
3976
|
}
|
|
4016
3977
|
async forwardActivityInternal(forwarder, recipients, options) {
|
|
4017
|
-
const logger
|
|
3978
|
+
const logger = getLogger([
|
|
4018
3979
|
"fedify",
|
|
4019
3980
|
"federation",
|
|
4020
3981
|
"inbox"
|
|
@@ -4028,7 +3989,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
4028
3989
|
if ("username" in forwarder) username = forwarder.username;
|
|
4029
3990
|
else {
|
|
4030
3991
|
username = forwarder.handle;
|
|
4031
|
-
logger
|
|
3992
|
+
logger.warn("The \"handle\" property for the forwarder parameter is deprecated; use \"identifier\" or \"username\" instead.", { forwarder });
|
|
4032
3993
|
}
|
|
4033
3994
|
if (this.federation.actorCallbacks?.handleMapper == null) identifier = username;
|
|
4034
3995
|
else {
|
|
@@ -4046,14 +4007,13 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
4046
4007
|
if (!hasSignature(this.activity)) {
|
|
4047
4008
|
let hasProof;
|
|
4048
4009
|
try {
|
|
4049
|
-
|
|
4050
|
-
hasProof = await activity.getProof() != null;
|
|
4010
|
+
hasProof = await (await Activity.fromJsonLd(this.activity, this)).getProof() != null;
|
|
4051
4011
|
} catch {
|
|
4052
4012
|
hasProof = false;
|
|
4053
4013
|
}
|
|
4054
4014
|
if (!hasProof) {
|
|
4055
4015
|
if (options?.skipIfUnsigned) return;
|
|
4056
|
-
logger
|
|
4016
|
+
logger.warn("The received activity {activityId} is not signed; even if it is forwarded to other servers as is, it may not be accepted by them due to the lack of a signature/proof.");
|
|
4057
4017
|
}
|
|
4058
4018
|
}
|
|
4059
4019
|
if (recipients === "followers") {
|
|
@@ -4067,14 +4027,14 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
4067
4027
|
preferSharedInbox: options?.preferSharedInbox,
|
|
4068
4028
|
excludeBaseUris: options?.excludeBaseUris
|
|
4069
4029
|
});
|
|
4070
|
-
logger
|
|
4030
|
+
logger.debug("Forwarding activity {activityId} to inboxes:\n{inboxes}", {
|
|
4071
4031
|
inboxes: globalThis.Object.keys(inboxes),
|
|
4072
4032
|
activityId: this.activityId,
|
|
4073
4033
|
activity: this.activity
|
|
4074
4034
|
});
|
|
4075
4035
|
if (options?.immediate || this.federation.outboxQueue == null) {
|
|
4076
|
-
if (options?.immediate) logger
|
|
4077
|
-
else logger
|
|
4036
|
+
if (options?.immediate) logger.debug("Forwarding activity immediately without queue since immediate option is set.");
|
|
4037
|
+
else logger.debug("Forwarding activity immediately without queue since queue is not set.");
|
|
4078
4038
|
const promises = [];
|
|
4079
4039
|
for (const inbox in inboxes) promises.push(sendActivity({
|
|
4080
4040
|
keys,
|
|
@@ -4089,7 +4049,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
4089
4049
|
await Promise.all(promises);
|
|
4090
4050
|
return;
|
|
4091
4051
|
}
|
|
4092
|
-
logger
|
|
4052
|
+
logger.debug("Enqueuing activity {activityId} to forward later.", {
|
|
4093
4053
|
activityId: this.activityId,
|
|
4094
4054
|
activity: this.activity
|
|
4095
4055
|
});
|
|
@@ -4125,10 +4085,9 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
4125
4085
|
const { outboxQueue } = this.federation;
|
|
4126
4086
|
if (outboxQueue.enqueueMany == null) {
|
|
4127
4087
|
const promises = messages.map((m) => outboxQueue.enqueue(m));
|
|
4128
|
-
const
|
|
4129
|
-
const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
4088
|
+
const errors = (await Promise.allSettled(promises)).filter((r) => r.status === "rejected").map((r) => r.reason);
|
|
4130
4089
|
if (errors.length > 0) {
|
|
4131
|
-
logger
|
|
4090
|
+
logger.error("Failed to enqueue activity {activityId} to forward later:\n{errors}", {
|
|
4132
4091
|
activityId: this.activityId,
|
|
4133
4092
|
errors
|
|
4134
4093
|
});
|
|
@@ -4138,7 +4097,7 @@ var InboxContextImpl = class InboxContextImpl extends ContextImpl {
|
|
|
4138
4097
|
} else try {
|
|
4139
4098
|
await outboxQueue.enqueueMany(messages);
|
|
4140
4099
|
} catch (error) {
|
|
4141
|
-
logger
|
|
4100
|
+
logger.error("Failed to enqueue activity {activityId} to forward later:\n{error}", {
|
|
4142
4101
|
activityId: this.activityId,
|
|
4143
4102
|
error
|
|
4144
4103
|
});
|
|
@@ -4193,10 +4152,7 @@ function unauthorized(_request) {
|
|
|
4193
4152
|
function getRequestId(request) {
|
|
4194
4153
|
const traceId = request.headers.get("X-Request-Id") || request.headers.get("X-Correlation-Id") || request.headers.get("Traceparent")?.split("-")[1];
|
|
4195
4154
|
if (traceId != null) return traceId;
|
|
4196
|
-
|
|
4197
|
-
const random = Math.random().toString(36).slice(2, 8);
|
|
4198
|
-
return `req_${timestamp}${random}`;
|
|
4155
|
+
return `req_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
4199
4156
|
}
|
|
4200
|
-
|
|
4201
4157
|
//#endregion
|
|
4202
|
-
export {
|
|
4158
|
+
export { respondWithObjectIfAcceptable as a, createFederationBuilder as c, respondWithObject as i, Router$1 as l, middleware_exports as n, buildCollectionSynchronizationHeader as o, createExponentialBackoffPolicy as r, digest as s, createFederation as t, RouterError as u };
|