@fedify/fedify 2.0.0-dev.1593 → 2.0.0-dev.160
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/LICENSE +1 -1
- package/README.md +66 -30
- package/dist/{assert_rejects-DiIiJbZn.js → assert_rejects-Ce45JcFg.js} +1 -1
- package/dist/{assert_is_error-BPGph1Jx.js → assert_throws-BNXdRGWP.js} +31 -1
- package/dist/{builder-BgzJcrpt.js → builder-C9n2ExVv.js} +15 -8
- package/dist/chunk-DqRYRqnO.cjs +34 -0
- package/dist/client-94iWEfQa.d.cts +222 -0
- package/dist/{client-DF8anIB5.d.ts → client-BivSNrEg.d.ts} +3 -75
- package/dist/{client-CpxFv8ft.js → client-CgMTXmAD.js} +3 -22
- package/dist/compat/mod.cjs +10 -0
- package/dist/compat/mod.d.cts +7 -0
- package/dist/compat/mod.d.ts +6 -12
- package/dist/compat/mod.js +5 -5
- package/dist/compat/transformers.test.js +21 -20
- package/dist/compat-DmDDELst.cjs +4 -0
- package/dist/compat-nxUqe4Z-.js +4 -0
- package/dist/context-Bns6uTJq.js +109 -0
- package/dist/{context-9gCpIkiz.d.ts → context-CYZ2i00R.d.ts} +321 -129
- package/dist/context-D2MrtLch.d.cts +2447 -0
- package/dist/deno-B74l3pXN.js +117 -0
- package/dist/{testing-D4xRiVJV.js → dist-B5f6a8Tt.js} +90 -111
- package/dist/{authdocloader-DJtdyVPc.js → docloader-eucHnjj4.js} +17 -8
- package/dist/{esm-5nsZYnVB.js → esm-DGl7uK1r.js} +32 -17
- package/dist/federation/builder.test.js +12 -13
- package/dist/federation/collection.test.js +6 -9
- package/dist/federation/handler.test.js +115 -148
- package/dist/federation/idempotency.test.js +202 -0
- package/dist/federation/inbox.test.js +5 -6
- package/dist/federation/keycache.test.js +4 -5
- package/dist/federation/kv.test.js +61 -9
- package/dist/federation/middleware.test.js +311 -131
- package/dist/federation/mod.cjs +25 -0
- package/dist/federation/mod.d.cts +7 -0
- package/dist/federation/mod.d.ts +7 -13
- package/dist/federation/mod.js +11 -16
- package/dist/federation/mq.test.js +9 -10
- package/dist/federation/negotiation.test.js +25 -0
- package/dist/federation/retry.test.js +2 -4
- package/dist/federation/router.test.js +6 -8
- package/dist/federation/send.test.js +55 -15
- package/dist/{webfinger/handler.test.js → federation/webfinger.test.js} +27 -26
- package/dist/federation-B431K2gm.cjs +266 -0
- package/dist/{federation-CMX7WzeL.js → federation-BbZwNNWj.js} +31 -9
- package/dist/http-ClB3pLcL.d.cts +253 -0
- package/dist/{http-CQulyTuw.js → http-CrnYJYhM.js} +3 -2
- package/dist/{http-BqklewFY.js → http-DJ7KWfiN.js} +374 -14
- package/dist/{http-DqSNLFNY.d.ts → http-DLBDPal9.d.ts} +2 -2
- package/dist/http-DtRqZZgP.cjs +1222 -0
- package/dist/{inbox-B97Wrppe.js → inbox-6-2rtCJf.js} +25 -7
- package/dist/{key-D-s3dQbK.js → key-pYEsD-IB.js} +3 -2
- package/dist/{keycache-Br0-hsD5.js → keycache-DRxpZ5r9.js} +1 -1
- package/dist/{keys-DSk2aqlj.js → keys-ZbcByPg9.js} +2 -1
- package/dist/{kv-C7sopW2E.d.ts → kv-CtOmTRNc.d.ts} +30 -1
- package/dist/kv-D8q9fLkA.d.cts +110 -0
- package/dist/{kv-CRZrzyXm.js → kv-QzKcOQgP.js} +22 -0
- package/dist/kv-cache-BEeqyGER.js +107 -0
- package/dist/kv-cache-Cr66Hw1w.js +122 -0
- package/dist/kv-cache-jKJ4ZH0U.cjs +134 -0
- package/dist/{ld-CYUQO1l4.js → ld-Bmrvt1KE.js} +4 -2
- package/dist/middleware-BUywt3CE.cjs +4242 -0
- package/dist/middleware-Ba1Pxx8r.js +26 -0
- package/dist/{middleware-tfSiCl9w.js → middleware-ByNAm2-S.js} +272 -271
- package/dist/middleware-D6QDOyQU.cjs +12 -0
- package/dist/{middleware-CovCqg8w.js → middleware-D9L8QWDP.js} +230 -327
- package/dist/middleware-jJYYmbt6.js +12 -0
- package/dist/mod-BrS8tiad.d.cts +266 -0
- package/dist/mod-C81L6_lQ.d.cts +1 -0
- package/dist/mod-CJgbdSqb.d.ts +109 -0
- package/dist/mod-CNNTHyBC.d.cts +80 -0
- package/dist/mod-CS-MS7gZ.d.cts +62 -0
- package/dist/{mod-Bqxcp7eN.d.ts → mod-D_cmv2il.d.ts} +4 -4
- package/dist/mod-DcPRcifg.d.cts +107 -0
- package/dist/mod-DqFSzJA0.d.ts +64 -0
- package/dist/{mod-Drmz72EK.d.ts → mod-jOa7W503.d.ts} +3 -3
- package/dist/mod.cjs +55 -0
- package/dist/mod.d.cts +11 -0
- package/dist/mod.d.ts +11 -17
- package/dist/mod.js +15 -21
- package/dist/negotiation-5NPJL6zp.js +71 -0
- package/dist/nodeinfo/client.test.js +29 -111
- package/dist/nodeinfo/handler.test.js +26 -26
- package/dist/nodeinfo/mod.cjs +10 -0
- package/dist/nodeinfo/mod.d.cts +3 -0
- package/dist/nodeinfo/mod.d.ts +3 -5
- package/dist/nodeinfo/mod.js +6 -7
- package/dist/nodeinfo/types.test.js +7 -15
- package/dist/nodeinfo-BlLsRSiT.js +4 -0
- package/dist/nodeinfo-DuMYTpbZ.cjs +4 -0
- package/dist/otel/exporter.test.js +899 -0
- package/dist/otel/mod.cjs +262 -0
- package/dist/otel/mod.d.cts +230 -0
- package/dist/otel/mod.d.ts +232 -0
- package/dist/otel/mod.js +261 -0
- package/dist/{owner-CQPnQVtf.d.ts → owner-BgI8C-VY.d.ts} +2 -3
- package/dist/owner-C-zfmVAD.d.cts +66 -0
- package/dist/{owner-CBeUJR68.js → owner-vFiFLWHR.js} +45 -8
- package/dist/{proof-CHQnDg0z.js → proof-C-k7brtD.js} +3 -2
- package/dist/proof-CLwK-TXL.cjs +709 -0
- package/dist/{proof-D436ezTT.js → proof-Dp6V6HEi.js} +50 -14
- package/dist/router-D9eI0s4b.js +118 -0
- package/dist/{send-Bc0QdRlp.js → send-BVXXc0Cn.js} +9 -4
- package/dist/sig/http.test.js +11 -13
- package/dist/sig/key.test.js +9 -11
- package/dist/sig/ld.test.js +8 -10
- package/dist/sig/mod.cjs +26 -0
- package/dist/sig/mod.d.cts +4 -0
- package/dist/sig/mod.d.ts +3 -7
- package/dist/sig/mod.js +6 -10
- package/dist/sig/owner.test.js +33 -12
- package/dist/sig/proof.test.js +13 -14
- package/dist/sig-CwuONEzF.js +4 -0
- package/dist/sig-DeXX2xnj.cjs +4 -0
- package/dist/testing/mod.d.ts +180 -6946
- package/dist/testing/mod.js +4 -4
- package/dist/transformers-BjBg6Lag.cjs +116 -0
- package/dist/{transformers-Dna8Fg7k.js → transformers-N_ip_y4P.js} +5 -5
- package/dist/{types-BIgY6c-l.js → types-BEdCLHqP.js} +1 -3
- package/dist/types-Q-qkJXBV.cjs +315 -0
- package/dist/{types-RbpvCErq.js → types-hKTi53FO.js} +8 -169
- package/dist/{runtime/authdocloader.test.js → utils/docloader.test.js} +13 -15
- package/dist/utils/kv-cache.test.js +211 -0
- package/dist/utils/mod.cjs +10 -0
- package/dist/utils/mod.d.cts +4 -0
- package/dist/utils/mod.d.ts +6 -0
- package/dist/utils/mod.js +9 -0
- package/dist/utils-Db0ZmjcD.cjs +4 -0
- package/dist/utils-Wranxuoe.js +4 -0
- package/package.json +69 -55
- package/dist/actor-Bj1Vq2XG.js +0 -146
- package/dist/actor-C22bXuuC.d.ts +0 -130
- package/dist/actor-DNwcqwPT.js +0 -37312
- package/dist/assert_throws-BOO88avQ.js +0 -39
- package/dist/authdocloader-qkvj_KZY.js +0 -52
- package/dist/compat-Bb5myD13.js +0 -4
- package/dist/denokv-Bv33Xxea.js +0 -57
- package/dist/docloader-9_osWaaH.js +0 -4615
- package/dist/docloader-CxWcuWqQ.d.ts +0 -221
- package/dist/fixtures/activitypub.academy/users/brauca_darradiul.json +0 -83
- package/dist/fixtures/example.com/announce.json +0 -6
- package/dist/fixtures/example.com/collection.json +0 -19
- package/dist/fixtures/example.com/create.json +0 -6
- package/dist/fixtures/example.com/cross-origin-actor.json +0 -6
- package/dist/fixtures/example.com/hong-gildong.json +0 -11
- package/dist/fixtures/example.com/invite.json +0 -7
- package/dist/fixtures/example.com/key.json +0 -7
- package/dist/fixtures/example.com/key2.json +0 -6
- package/dist/fixtures/example.com/object.json +0 -6
- package/dist/fixtures/example.com/orderedcollectionpage.json +0 -24
- package/dist/fixtures/example.com/paged/a.json +0 -13
- package/dist/fixtures/example.com/paged/b.json +0 -16
- package/dist/fixtures/example.com/paged-collection.json +0 -6
- package/dist/fixtures/example.com/person.json +0 -22
- package/dist/fixtures/example.com/person2.json +0 -40
- package/dist/fixtures/example.com/test.json +0 -5
- package/dist/fixtures/example.com/users/handle.json +0 -16
- package/dist/fixtures/example.com/wrong-type.json +0 -3
- package/dist/fixtures/oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd.json +0 -24
- package/dist/fixtures/remote.domain/users/bob.json +0 -20
- package/dist/fixtures/server.example/users/alice.json +0 -20
- package/dist/fixtures/w3id.org/identity/v1.json +0 -152
- package/dist/fixtures/w3id.org/security/data-integrity/v1.json +0 -74
- package/dist/fixtures/w3id.org/security/multikey/v1.json +0 -35
- package/dist/fixtures/w3id.org/security/v1.json +0 -50
- package/dist/fixtures/wizard.casa/users/hongminhee.json +0 -69
- package/dist/fixtures/www.w3.org/ns/activitystreams.json +0 -379
- package/dist/fixtures/www.w3.org/ns/did/v1.json +0 -58
- package/dist/key-3jGPh5To.js +0 -10
- package/dist/key-C3CEOTh7.js +0 -10
- package/dist/key-CNCeen0u.js +0 -260
- package/dist/lookup-BNFlahf3.js +0 -131
- package/dist/lookup-CnJK1NUl.js +0 -322
- package/dist/middleware-CJbNYdw9.js +0 -17
- package/dist/middleware-zDdNBo-m.js +0 -26
- package/dist/mod-Cxt4Kpf6.d.ts +0 -291
- package/dist/mod-DBzN0aCM.d.ts +0 -115
- package/dist/mod-TFoH2Ql8.d.ts +0 -104
- package/dist/mod-g0xFzAP9.d.ts +0 -2
- package/dist/mq-CRGm1e_F.d.ts +0 -143
- package/dist/nodeinfo/semver.test.js +0 -143
- package/dist/nodeinfo-CyEbLjHs.js +0 -4
- package/dist/runtime/docloader.test.js +0 -522
- package/dist/runtime/key.test.js +0 -103
- package/dist/runtime/langstr.test.js +0 -39
- package/dist/runtime/mod.d.ts +0 -8
- package/dist/runtime/mod.js +0 -13
- package/dist/runtime/multibase/multibase.test.d.ts +0 -3
- package/dist/runtime/multibase/multibase.test.js +0 -358
- package/dist/runtime/url.test.d.ts +0 -3
- package/dist/runtime/url.test.js +0 -45
- package/dist/runtime-BSkOVUWM.js +0 -4
- package/dist/semver-dArNLkR9.js +0 -149
- package/dist/sig-BXJO--F9.js +0 -4
- package/dist/src/vocab/accept.yaml +0 -15
- package/dist/src/vocab/activity.yaml +0 -98
- package/dist/src/vocab/add.yaml +0 -16
- package/dist/src/vocab/announce.yaml +0 -30
- package/dist/src/vocab/application.yaml +0 -324
- package/dist/src/vocab/arrive.yaml +0 -15
- package/dist/src/vocab/article.yaml +0 -46
- package/dist/src/vocab/audio.yaml +0 -11
- package/dist/src/vocab/block.yaml +0 -16
- package/dist/src/vocab/chatmessage.yaml +0 -50
- package/dist/src/vocab/collection.yaml +0 -154
- package/dist/src/vocab/collectionpage.yaml +0 -55
- package/dist/src/vocab/create.yaml +0 -28
- package/dist/src/vocab/dataintegrityproof.yaml +0 -56
- package/dist/src/vocab/delete.yaml +0 -27
- package/dist/src/vocab/didservice.yaml +0 -22
- package/dist/src/vocab/dislike.yaml +0 -14
- package/dist/src/vocab/document.yaml +0 -31
- package/dist/src/vocab/emoji.yaml +0 -12
- package/dist/src/vocab/emojireact.yaml +0 -17
- package/dist/src/vocab/endpoints.yaml +0 -85
- package/dist/src/vocab/event.yaml +0 -11
- package/dist/src/vocab/export.yaml +0 -9
- package/dist/src/vocab/flag.yaml +0 -15
- package/dist/src/vocab/follow.yaml +0 -19
- package/dist/src/vocab/group.yaml +0 -324
- package/dist/src/vocab/hashtag.yaml +0 -14
- package/dist/src/vocab/ignore.yaml +0 -14
- package/dist/src/vocab/image.yaml +0 -9
- package/dist/src/vocab/intransitiveactivity.yaml +0 -15
- package/dist/src/vocab/invite.yaml +0 -14
- package/dist/src/vocab/join.yaml +0 -14
- package/dist/src/vocab/key.yaml +0 -28
- package/dist/src/vocab/leave.yaml +0 -14
- package/dist/src/vocab/like.yaml +0 -16
- package/dist/src/vocab/link.yaml +0 -101
- package/dist/src/vocab/listen.yaml +0 -12
- package/dist/src/vocab/mention.yaml +0 -9
- package/dist/src/vocab/move.yaml +0 -15
- package/dist/src/vocab/multikey.yaml +0 -36
- package/dist/src/vocab/note.yaml +0 -48
- package/dist/src/vocab/object.yaml +0 -404
- package/dist/src/vocab/offer.yaml +0 -15
- package/dist/src/vocab/orderedcollection.yaml +0 -39
- package/dist/src/vocab/orderedcollectionpage.yaml +0 -50
- package/dist/src/vocab/organization.yaml +0 -324
- package/dist/src/vocab/page.yaml +0 -11
- package/dist/src/vocab/person.yaml +0 -324
- package/dist/src/vocab/place.yaml +0 -75
- package/dist/src/vocab/profile.yaml +0 -26
- package/dist/src/vocab/propertyvalue.yaml +0 -32
- package/dist/src/vocab/question.yaml +0 -103
- package/dist/src/vocab/read.yaml +0 -13
- package/dist/src/vocab/reject.yaml +0 -14
- package/dist/src/vocab/relationship.yaml +0 -52
- package/dist/src/vocab/remove.yaml +0 -14
- package/dist/src/vocab/service.yaml +0 -324
- package/dist/src/vocab/source.yaml +0 -26
- package/dist/src/vocab/tentativeaccept.yaml +0 -14
- package/dist/src/vocab/tentativereject.yaml +0 -14
- package/dist/src/vocab/tombstone.yaml +0 -24
- package/dist/src/vocab/travel.yaml +0 -16
- package/dist/src/vocab/undo.yaml +0 -26
- package/dist/src/vocab/update.yaml +0 -58
- package/dist/src/vocab/video.yaml +0 -11
- package/dist/src/vocab/view.yaml +0 -13
- package/dist/testing/docloader.test.js +0 -24
- package/dist/type-qs0mWLTm.js +0 -42007
- package/dist/vocab/actor.test.d.ts +0 -3
- package/dist/vocab/actor.test.js +0 -5965
- package/dist/vocab/lookup.test.d.ts +0 -3
- package/dist/vocab/lookup.test.js +0 -206
- package/dist/vocab/mod.d.ts +0 -8
- package/dist/vocab/mod.js +0 -10
- package/dist/vocab/schema.yaml +0 -247
- 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/vocab.test.js +0 -3363
- package/dist/vocab-SOE1ifCr.d.ts +0 -14634
- package/dist/vocab-r-I1_ZmK.js +0 -246
- package/dist/webfinger/handler.test.d.ts +0 -3
- package/dist/webfinger/lookup.test.d.ts +0 -3
- package/dist/webfinger/lookup.test.js +0 -195
- package/dist/webfinger/mod.d.ts +0 -6
- package/dist/webfinger/mod.js +0 -9
- package/dist/webfinger-C3GIyXIg.js +0 -4
- package/dist/x/cfworkers.d.ts +0 -61
- package/dist/x/cfworkers.js +0 -98
- package/dist/x/cfworkers.test.d.ts +0 -3
- package/dist/x/cfworkers.test.js +0 -179
- package/dist/x/hono.d.ts +0 -56
- package/dist/x/hono.js +0 -60
- package/dist/x/sveltekit.d.ts +0 -48
- package/dist/x/sveltekit.js +0 -68
- /package/dist/{assert_not_equals-f3m3epl3.js → assert_not_equals-C80BG-_5.js} +0 -0
- /package/dist/{collection-CSzG2j1P.js → collection-CcnIw1qY.js} +0 -0
- /package/dist/{nodeinfo/semver.test.d.ts → federation/idempotency.test.d.ts} +0 -0
- /package/dist/{runtime/authdocloader.test.d.ts → federation/negotiation.test.d.ts} +0 -0
- /package/dist/{runtime/docloader.test.d.ts → federation/webfinger.test.d.ts} +0 -0
- /package/dist/{mod-1pDWKvUL.d.ts → mod-1E3W847c.d.ts} +0 -0
- /package/dist/{runtime/key.test.d.ts → otel/exporter.test.d.ts} +0 -0
- /package/dist/{std__assert-X-_kMxKM.js → std__assert-DWivtrGR.js} +0 -0
- /package/dist/{testing → utils}/docloader.test.d.ts +0 -0
- /package/dist/{runtime/langstr.test.d.ts → utils/kv-cache.test.d.ts} +0 -0
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { getDefaultActivityTransformers } from "./transformers-
|
|
6
|
-
import { deno_default,
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { doubleKnock, verifyRequest } from "./http-BqklewFY.js";
|
|
11
|
-
import { detachSignature, doesActorOwnKey, getKeyOwner, hasSignature, signJsonLd, signObject, verifyJsonLd, verifyObject } from "./proof-D436ezTT.js";
|
|
12
|
-
import { getNodeInfo, nodeInfoToJson } from "./types-RbpvCErq.js";
|
|
13
|
-
import { getAuthenticatedDocumentLoader } from "./authdocloader-qkvj_KZY.js";
|
|
14
|
-
import { lookupObject, traverseCollection } from "./vocab-r-I1_ZmK.js";
|
|
2
|
+
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
+
import { URLPattern } from "urlpattern-polyfill";
|
|
4
|
+
|
|
5
|
+
import { getDefaultActivityTransformers } from "./transformers-N_ip_y4P.js";
|
|
6
|
+
import { deno_default, doubleKnock, exportJwk, importJwk, validateCryptoKey, verifyRequest } from "./http-DJ7KWfiN.js";
|
|
7
|
+
import { detachSignature, doesActorOwnKey, getKeyOwner, hasSignature, signJsonLd, signObject, verifyJsonLd, verifyObject } from "./proof-Dp6V6HEi.js";
|
|
8
|
+
import { getNodeInfo, nodeInfoToJson } from "./types-hKTi53FO.js";
|
|
9
|
+
import { getAuthenticatedDocumentLoader, kvCache } from "./kv-cache-Cr66Hw1w.js";
|
|
15
10
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
11
|
+
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
16
12
|
import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
|
|
17
|
-
import { encodeHex } from "byte-encodings/hex";
|
|
18
13
|
import { cloneDeep } from "es-toolkit";
|
|
19
14
|
import { Router } from "uri-template-router";
|
|
20
15
|
import { parseTemplate } from "url-template";
|
|
16
|
+
import { encodeHex } from "byte-encodings/hex";
|
|
21
17
|
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";
|
|
18
|
+
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
19
|
+
import { lookupWebFinger } from "@fedify/webfinger";
|
|
22
20
|
import { domainToASCII } from "node:url";
|
|
23
21
|
|
|
24
22
|
//#region src/federation/inbox.ts
|
|
@@ -55,17 +53,34 @@ var InboxListenerSet = class InboxListenerSet {
|
|
|
55
53
|
return this.dispatchWithClass(activity)?.listener ?? null;
|
|
56
54
|
}
|
|
57
55
|
};
|
|
58
|
-
async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider }) {
|
|
56
|
+
async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
|
|
59
57
|
const logger$1 = getLogger([
|
|
60
58
|
"fedify",
|
|
61
59
|
"federation",
|
|
62
60
|
"inbox"
|
|
63
61
|
]);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
let cacheKey = null;
|
|
63
|
+
if (activity.id != null) {
|
|
64
|
+
const inboxContext = inboxContextFactory(recipient, json, activity.id?.href, getTypeId(activity).href);
|
|
65
|
+
const strategy = idempotencyStrategy ?? "per-inbox";
|
|
66
|
+
let keyString;
|
|
67
|
+
if (typeof strategy === "function") {
|
|
68
|
+
const result = await strategy(inboxContext, activity);
|
|
69
|
+
keyString = result;
|
|
70
|
+
} else switch (strategy) {
|
|
71
|
+
case "global":
|
|
72
|
+
keyString = activity.id.href;
|
|
73
|
+
break;
|
|
74
|
+
case "per-origin":
|
|
75
|
+
keyString = `${ctx.origin}\n${activity.id.href}`;
|
|
76
|
+
break;
|
|
77
|
+
case "per-inbox":
|
|
78
|
+
keyString = `${ctx.origin}\n${activity.id.href}\n${recipient == null ? "sharedInbox" : `inbox\n${recipient}`}`;
|
|
79
|
+
break;
|
|
80
|
+
default: keyString = `${ctx.origin}\n${activity.id.href}`;
|
|
81
|
+
}
|
|
82
|
+
if (keyString != null) cacheKey = [...kvPrefixes.activityIdempotence, keyString];
|
|
83
|
+
}
|
|
69
84
|
if (cacheKey != null) {
|
|
70
85
|
const cached = await kv.get(cacheKey);
|
|
71
86
|
if (cached === true) {
|
|
@@ -307,6 +322,7 @@ var FederationBuilderImpl = class {
|
|
|
307
322
|
inboxListeners;
|
|
308
323
|
inboxErrorHandler;
|
|
309
324
|
sharedInboxKeyDispatcher;
|
|
325
|
+
idempotencyStrategy;
|
|
310
326
|
collectionTypeIds;
|
|
311
327
|
collectionCallbacks;
|
|
312
328
|
/**
|
|
@@ -321,7 +337,7 @@ var FederationBuilderImpl = class {
|
|
|
321
337
|
this.collectionTypeIds = {};
|
|
322
338
|
}
|
|
323
339
|
async build(options) {
|
|
324
|
-
const { FederationImpl: FederationImpl$1 } = await import("./middleware-
|
|
340
|
+
const { FederationImpl: FederationImpl$1 } = await import("./middleware-jJYYmbt6.js");
|
|
325
341
|
const f = new FederationImpl$1(options);
|
|
326
342
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
327
343
|
f.router = this.router.clone();
|
|
@@ -343,6 +359,7 @@ var FederationBuilderImpl = class {
|
|
|
343
359
|
f.inboxListeners = this.inboxListeners?.clone();
|
|
344
360
|
f.inboxErrorHandler = this.inboxErrorHandler;
|
|
345
361
|
f.sharedInboxKeyDispatcher = this.sharedInboxKeyDispatcher;
|
|
362
|
+
f.idempotencyStrategy = this.idempotencyStrategy;
|
|
346
363
|
return f;
|
|
347
364
|
}
|
|
348
365
|
_getTracer() {
|
|
@@ -765,15 +782,19 @@ var FederationBuilderImpl = class {
|
|
|
765
782
|
setSharedKeyDispatcher: (dispatcher) => {
|
|
766
783
|
this.sharedInboxKeyDispatcher = dispatcher;
|
|
767
784
|
return setters;
|
|
785
|
+
},
|
|
786
|
+
withIdempotency: (strategy) => {
|
|
787
|
+
this.idempotencyStrategy = strategy;
|
|
788
|
+
return setters;
|
|
768
789
|
}
|
|
769
790
|
};
|
|
770
791
|
return setters;
|
|
771
792
|
}
|
|
772
|
-
setCollectionDispatcher(name,
|
|
773
|
-
return this.#setCustomCollectionDispatcher(name, "collection",
|
|
793
|
+
setCollectionDispatcher(name, itemType, path, dispatcher) {
|
|
794
|
+
return this.#setCustomCollectionDispatcher(name, "collection", itemType, path, dispatcher);
|
|
774
795
|
}
|
|
775
|
-
setOrderedCollectionDispatcher(name,
|
|
776
|
-
return this.#setCustomCollectionDispatcher(name, "orderedCollection",
|
|
796
|
+
setOrderedCollectionDispatcher(name, itemType, path, dispatcher) {
|
|
797
|
+
return this.#setCustomCollectionDispatcher(name, "orderedCollection", itemType, path, dispatcher);
|
|
777
798
|
}
|
|
778
799
|
#setCustomCollectionDispatcher(name, collectionType, itemType, path, dispatcher) {
|
|
779
800
|
const strName = String(name);
|
|
@@ -979,9 +1000,6 @@ function preferredMediaTypes(accept) {
|
|
|
979
1000
|
const accepts = parseAccept(accept === void 0 ? "*/*" : accept ?? "");
|
|
980
1001
|
return accepts.filter(isQuality).sort(compareSpecs).map(getFullType);
|
|
981
1002
|
}
|
|
982
|
-
|
|
983
|
-
//#endregion
|
|
984
|
-
//#region src/federation/handler.ts
|
|
985
1003
|
function acceptsJsonLd(request) {
|
|
986
1004
|
const accept = request.headers.get("Accept");
|
|
987
1005
|
const types = accept ? preferredMediaTypes(accept) : ["*/*"];
|
|
@@ -989,6 +1007,9 @@ function acceptsJsonLd(request) {
|
|
|
989
1007
|
if (types[0] === "text/html" || types[0] === "application/xhtml+xml") return false;
|
|
990
1008
|
return types.includes("application/activity+json") || types.includes("application/ld+json") || types.includes("application/json");
|
|
991
1009
|
}
|
|
1010
|
+
|
|
1011
|
+
//#endregion
|
|
1012
|
+
//#region src/federation/handler.ts
|
|
992
1013
|
/**
|
|
993
1014
|
* Handles an actor request.
|
|
994
1015
|
* @template TContextData The context data to pass to the context.
|
|
@@ -996,7 +1017,7 @@ function acceptsJsonLd(request) {
|
|
|
996
1017
|
* @param parameters The parameters for handling the actor.
|
|
997
1018
|
* @returns A promise that resolves to an HTTP response.
|
|
998
1019
|
*/
|
|
999
|
-
async function handleActor(request, { identifier, context: context$1, actorDispatcher, authorizePredicate, onNotFound,
|
|
1020
|
+
async function handleActor(request, { identifier, context: context$1, actorDispatcher, authorizePredicate, onNotFound, onUnauthorized }) {
|
|
1000
1021
|
const logger$1 = getLogger([
|
|
1001
1022
|
"fedify",
|
|
1002
1023
|
"federation",
|
|
@@ -1011,7 +1032,6 @@ async function handleActor(request, { identifier, context: context$1, actorDispa
|
|
|
1011
1032
|
logger$1.debug("Actor {identifier} not found.", { identifier });
|
|
1012
1033
|
return await onNotFound(request);
|
|
1013
1034
|
}
|
|
1014
|
-
if (!acceptsJsonLd(request)) return await onNotAcceptable(request);
|
|
1015
1035
|
if (authorizePredicate != null) {
|
|
1016
1036
|
let key = await context$1.getSignedKey();
|
|
1017
1037
|
key = key?.clone({}, { $warning: {
|
|
@@ -1046,11 +1066,10 @@ async function handleActor(request, { identifier, context: context$1, actorDispa
|
|
|
1046
1066
|
* @param parameters The parameters for handling the object.
|
|
1047
1067
|
* @returns A promise that resolves to an HTTP response.
|
|
1048
1068
|
*/
|
|
1049
|
-
async function handleObject(request, { values, context: context$1, objectDispatcher, authorizePredicate, onNotFound,
|
|
1069
|
+
async function handleObject(request, { values, context: context$1, objectDispatcher, authorizePredicate, onNotFound, onUnauthorized }) {
|
|
1050
1070
|
if (objectDispatcher == null) return await onNotFound(request);
|
|
1051
1071
|
const object = await objectDispatcher(context$1, values);
|
|
1052
1072
|
if (object == null) return await onNotFound(request);
|
|
1053
|
-
if (!acceptsJsonLd(request)) return await onNotAcceptable(request);
|
|
1054
1073
|
if (authorizePredicate != null) {
|
|
1055
1074
|
let key = await context$1.getSignedKey();
|
|
1056
1075
|
key = key?.clone({}, { $warning: {
|
|
@@ -1088,7 +1107,7 @@ async function handleObject(request, { values, context: context$1, objectDispatc
|
|
|
1088
1107
|
* @param parameters The parameters for handling the collection.
|
|
1089
1108
|
* @returns A promise that resolves to an HTTP response.
|
|
1090
1109
|
*/
|
|
1091
|
-
async function handleCollection(request, { name, identifier, uriGetter, filter, filterPredicate, context: context$1, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound
|
|
1110
|
+
async function handleCollection(request, { name, identifier, uriGetter, filter, filterPredicate, context: context$1, collectionCallbacks, tracerProvider, onUnauthorized, onNotFound }) {
|
|
1092
1111
|
const spanName = name.trim().replace(/\s+/g, "_");
|
|
1093
1112
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
1094
1113
|
const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
|
|
@@ -1201,7 +1220,6 @@ async function handleCollection(request, { name, identifier, uriGetter, filter,
|
|
|
1201
1220
|
partOf
|
|
1202
1221
|
});
|
|
1203
1222
|
}
|
|
1204
|
-
if (!acceptsJsonLd(request)) return await onNotAcceptable(request);
|
|
1205
1223
|
if (collectionCallbacks.authorizePredicate != null) {
|
|
1206
1224
|
let key = await context$1.getSignedKey();
|
|
1207
1225
|
key = key?.clone({}, { $warning: {
|
|
@@ -1296,7 +1314,8 @@ async function handleInbox(request, options) {
|
|
|
1296
1314
|
* @param span The OpenTelemetry span for tracing.
|
|
1297
1315
|
* @returns A promise that resolves to an HTTP response.
|
|
1298
1316
|
*/
|
|
1299
|
-
async function handleInboxInternal(request,
|
|
1317
|
+
async function handleInboxInternal(request, parameters, span) {
|
|
1318
|
+
const { recipient, context: ctx, inboxContextFactory, kv, kvPrefixes, queue, actorDispatcher, inboxListeners, inboxErrorHandler, onNotFound, signatureTimeWindow, skipSignatureVerification, tracerProvider } = parameters;
|
|
1300
1319
|
const logger$1 = getLogger([
|
|
1301
1320
|
"fedify",
|
|
1302
1321
|
"federation",
|
|
@@ -1470,6 +1489,13 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
|
|
|
1470
1489
|
}
|
|
1471
1490
|
if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
|
|
1472
1491
|
span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
|
|
1492
|
+
span.addEvent("activitypub.activity.received", {
|
|
1493
|
+
"activitypub.activity.json": JSON.stringify(json),
|
|
1494
|
+
"activitypub.activity.verified": activity != null,
|
|
1495
|
+
"ld_signatures.verified": ldSigVerified,
|
|
1496
|
+
"http_signatures.verified": httpSigKey != null,
|
|
1497
|
+
"http_signatures.key_id": httpSigKey?.id?.href ?? ""
|
|
1498
|
+
});
|
|
1473
1499
|
if (httpSigKey != null && !await doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
1474
1500
|
logger$1.error("The signer ({keyId}) and the actor ({actorId}) do not match.", {
|
|
1475
1501
|
activity: json,
|
|
@@ -1498,7 +1524,8 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
|
|
|
1498
1524
|
kvPrefixes,
|
|
1499
1525
|
queue,
|
|
1500
1526
|
span,
|
|
1501
|
-
tracerProvider
|
|
1527
|
+
tracerProvider,
|
|
1528
|
+
idempotencyStrategy: parameters.idempotencyStrategy
|
|
1502
1529
|
});
|
|
1503
1530
|
if (routeResult === "alreadyProcessed") return new Response(`Activity <${activity.id}> has already been processed.`, {
|
|
1504
1531
|
status: 202,
|
|
@@ -1528,7 +1555,7 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
|
|
|
1528
1555
|
/**
|
|
1529
1556
|
* Handles a custom collection request.
|
|
1530
1557
|
* @template TItem The type of items in the collection.
|
|
1531
|
-
* @template
|
|
1558
|
+
* @template TParam The parameter names of the requested URL.
|
|
1532
1559
|
* @template TContext The type of the context, extending {@link RequestContext}.
|
|
1533
1560
|
* @template TContextData The context data to pass to the `TContext`.
|
|
1534
1561
|
* @param request The HTTP request.
|
|
@@ -1539,7 +1566,6 @@ async function handleInboxInternal(request, { recipient, context: ctx, inboxCont
|
|
|
1539
1566
|
const handleCustomCollection = exceptWrapper(_handleCustomCollection);
|
|
1540
1567
|
async function _handleCustomCollection(request, { name, values, context: context$1, tracerProvider, collectionCallbacks: callbacks, filterPredicate }) {
|
|
1541
1568
|
verifyDefined(callbacks);
|
|
1542
|
-
verifyJsonLdRequest(request);
|
|
1543
1569
|
await authIfNeeded(context$1, values, callbacks);
|
|
1544
1570
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
1545
1571
|
return await new CustomCollectionHandler(name, values, context$1, callbacks, tracerProvider, Collection, CollectionPage, filterPredicate).fetchCollection(cursor).toJsonLd().then(respondAsActivity);
|
|
@@ -1547,7 +1573,7 @@ async function _handleCustomCollection(request, { name, values, context: context
|
|
|
1547
1573
|
/**
|
|
1548
1574
|
* Handles an ordered collection request.
|
|
1549
1575
|
* @template TItem The type of items in the collection.
|
|
1550
|
-
* @template
|
|
1576
|
+
* @template TParam The parameter names of the requested URL.
|
|
1551
1577
|
* @template TContext The type of the context, extending {@link RequestContext}.
|
|
1552
1578
|
* @template TContextData The context data to pass to the `TContext`.
|
|
1553
1579
|
* @param request The HTTP request.
|
|
@@ -1558,7 +1584,6 @@ async function _handleCustomCollection(request, { name, values, context: context
|
|
|
1558
1584
|
const handleOrderedCollection = exceptWrapper(_handleOrderedCollection);
|
|
1559
1585
|
async function _handleOrderedCollection(request, { name, values, context: context$1, tracerProvider, collectionCallbacks: callbacks, filterPredicate }) {
|
|
1560
1586
|
verifyDefined(callbacks);
|
|
1561
|
-
verifyJsonLdRequest(request);
|
|
1562
1587
|
await authIfNeeded(context$1, values, callbacks);
|
|
1563
1588
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
1564
1589
|
return await new CustomCollectionHandler(name, values, context$1, callbacks, tracerProvider, OrderedCollection, OrderedCollectionPage, filterPredicate).fetchCollection(cursor).toJsonLd().then(respondAsActivity);
|
|
@@ -1568,7 +1593,7 @@ async function _handleOrderedCollection(request, { name, values, context: contex
|
|
|
1568
1593
|
* The main flow is on `getCollection`, `dispatch`.
|
|
1569
1594
|
*
|
|
1570
1595
|
* @template TItem The type of items in the collection.
|
|
1571
|
-
* @template
|
|
1596
|
+
* @template TParam The parameter names of the requested URL.
|
|
1572
1597
|
* @template TContext The type of the context. {@link Context} or {@link RequestContext}.
|
|
1573
1598
|
* @template TContextData The context data to pass to the `TContext`.
|
|
1574
1599
|
* @template TCollection The type of the collection, extending {@link Collection}.
|
|
@@ -1602,14 +1627,14 @@ var CustomCollectionHandler = class {
|
|
|
1602
1627
|
#collection = null;
|
|
1603
1628
|
/**
|
|
1604
1629
|
* Creates a new CustomCollection instance.
|
|
1605
|
-
* @param
|
|
1606
|
-
* @param
|
|
1607
|
-
* @param
|
|
1608
|
-
* @param
|
|
1609
|
-
* @param
|
|
1610
|
-
* @param
|
|
1611
|
-
* @param
|
|
1612
|
-
* @param
|
|
1630
|
+
* @param name The name of the collection.
|
|
1631
|
+
* @param values The parameter values for the collection.
|
|
1632
|
+
* @param context The request context.
|
|
1633
|
+
* @param callbacks The collection callbacks.
|
|
1634
|
+
* @param tracerProvider The tracer provider for telemetry.
|
|
1635
|
+
* @param Collection The Collection constructor.
|
|
1636
|
+
* @param CollectionPage The CollectionPage constructor.
|
|
1637
|
+
* @param filterPredicate Optional filter predicate for items.
|
|
1613
1638
|
*/
|
|
1614
1639
|
constructor(name, values, context$1, callbacks, tracerProvider = trace.getTracerProvider(), Collection$1, CollectionPage$1, filterPredicate) {
|
|
1615
1640
|
this.name = name;
|
|
@@ -1734,7 +1759,7 @@ var CustomCollectionHandler = class {
|
|
|
1734
1759
|
/**
|
|
1735
1760
|
* Creates a function to wrap the dispatcher so tracing can be applied.
|
|
1736
1761
|
* @param params Parameters including cursor and total items.
|
|
1737
|
-
* @returns
|
|
1762
|
+
* @returns A function that handles the span operation.
|
|
1738
1763
|
*/
|
|
1739
1764
|
spanPages = ({ totalItems = null, cursor = null }) => async (span) => {
|
|
1740
1765
|
try {
|
|
@@ -1755,23 +1780,23 @@ var CustomCollectionHandler = class {
|
|
|
1755
1780
|
};
|
|
1756
1781
|
/**
|
|
1757
1782
|
* Dispatches the collection request to get items.
|
|
1758
|
-
* @param
|
|
1759
|
-
* @returns
|
|
1783
|
+
* @param cursor The cursor for pagination, or null for the first page.
|
|
1784
|
+
* @returns A promise that resolves to the page items.
|
|
1760
1785
|
*/
|
|
1761
1786
|
async dispatch(cursor = null) {
|
|
1762
1787
|
return await this.#dispatcher(this.context, this.values, cursor) ?? new ItemsNotFoundError().throw();
|
|
1763
1788
|
}
|
|
1764
1789
|
/**
|
|
1765
1790
|
* Filters the items in the collection.
|
|
1766
|
-
* @param
|
|
1767
|
-
* @returns
|
|
1791
|
+
* @param items The items to filter.
|
|
1792
|
+
* @returns The filtered items.
|
|
1768
1793
|
*/
|
|
1769
1794
|
filterItems(items) {
|
|
1770
1795
|
return filterCollectionItems(items, this.name, this.filterPredicate);
|
|
1771
1796
|
}
|
|
1772
1797
|
/**
|
|
1773
1798
|
* Appends a cursor to the URL if it exists.
|
|
1774
|
-
* @param
|
|
1799
|
+
* @param cursor The cursor to append, or null/undefined.
|
|
1775
1800
|
* @returns The URL with cursor appended, or null if cursor is null/undefined.
|
|
1776
1801
|
*/
|
|
1777
1802
|
appendToUrl(cursor) {
|
|
@@ -1779,8 +1804,7 @@ var CustomCollectionHandler = class {
|
|
|
1779
1804
|
}
|
|
1780
1805
|
/**
|
|
1781
1806
|
* Gets the stored collection or collection page.
|
|
1782
|
-
* @returns
|
|
1783
|
-
the collection or collection page.
|
|
1807
|
+
* @returns A promise that resolves to the collection or collection page.
|
|
1784
1808
|
*/
|
|
1785
1809
|
get collection() {
|
|
1786
1810
|
if (this.#collection === null) this.#collection = this.getCollection();
|
|
@@ -1788,8 +1812,8 @@ var CustomCollectionHandler = class {
|
|
|
1788
1812
|
}
|
|
1789
1813
|
/**
|
|
1790
1814
|
* Gets the total number of items in the collection.
|
|
1791
|
-
* @returns
|
|
1792
|
-
|
|
1815
|
+
* @returns A promise that resolves to the total items count,
|
|
1816
|
+
* or null if not available.
|
|
1793
1817
|
*/
|
|
1794
1818
|
get totalItems() {
|
|
1795
1819
|
if (this.#totalItems === void 0) this.totalItems = this.callbacks.counter?.(this.context, this.values);
|
|
@@ -1805,8 +1829,8 @@ var CustomCollectionHandler = class {
|
|
|
1805
1829
|
}
|
|
1806
1830
|
/**
|
|
1807
1831
|
* Gets the first cursor for pagination.
|
|
1808
|
-
* @returns
|
|
1809
|
-
or null if not available.
|
|
1832
|
+
* @returns A promise that resolves to the first cursor,
|
|
1833
|
+
* or null if not available.
|
|
1810
1834
|
*/
|
|
1811
1835
|
get firstCursor() {
|
|
1812
1836
|
const cursor = this.callbacks.firstCursor?.(this.context, this.values);
|
|
@@ -1836,10 +1860,9 @@ function exceptWrapper(handler) {
|
|
|
1836
1860
|
try {
|
|
1837
1861
|
return await handler(request, handlerParams);
|
|
1838
1862
|
} catch (error) {
|
|
1839
|
-
const { onNotFound,
|
|
1863
|
+
const { onNotFound, onUnauthorized } = handlerParams;
|
|
1840
1864
|
switch (error?.constructor) {
|
|
1841
1865
|
case ItemsNotFoundError: return await onNotFound(request);
|
|
1842
|
-
case NotAcceptableError: return await onNotAcceptable(request);
|
|
1843
1866
|
case UnauthorizedError: return await onUnauthorized(request);
|
|
1844
1867
|
default: throw error;
|
|
1845
1868
|
}
|
|
@@ -1857,15 +1880,6 @@ const verifyDefined = (callbacks) => {
|
|
|
1857
1880
|
if (callbacks === void 0) throw new ItemsNotFoundError();
|
|
1858
1881
|
};
|
|
1859
1882
|
/**
|
|
1860
|
-
* Verifies that a request accepts JSON-LD content type.
|
|
1861
|
-
* @param request The HTTP request to verify.
|
|
1862
|
-
* @throws {NotAcceptableError} If the request doesn't accept JSON-LD.
|
|
1863
|
-
* @since 1.8.0
|
|
1864
|
-
*/
|
|
1865
|
-
const verifyJsonLdRequest = (request) => {
|
|
1866
|
-
if (!acceptsJsonLd(request)) throw new NotAcceptableError();
|
|
1867
|
-
};
|
|
1868
|
-
/**
|
|
1869
1883
|
* Performs authorization if needed based on the authorization predicate.
|
|
1870
1884
|
* @template TContextData The context data type.
|
|
1871
1885
|
* @param {RequestContext<TContextData>} context The request context.
|
|
@@ -1949,15 +1963,6 @@ var ItemsNotFoundError = class extends HandlerError {
|
|
|
1949
1963
|
}
|
|
1950
1964
|
};
|
|
1951
1965
|
/**
|
|
1952
|
-
* Error thrown when the request is not acceptable (e.g., wrong content type).
|
|
1953
|
-
* @since 1.8.0
|
|
1954
|
-
*/
|
|
1955
|
-
var NotAcceptableError = class extends HandlerError {
|
|
1956
|
-
constructor() {
|
|
1957
|
-
super("The request is not acceptable.");
|
|
1958
|
-
}
|
|
1959
|
-
};
|
|
1960
|
-
/**
|
|
1961
1966
|
* Error thrown when access to a collection is unauthorized.
|
|
1962
1967
|
* @since 1.8.0
|
|
1963
1968
|
*/
|
|
@@ -2031,139 +2036,6 @@ function handleNodeInfoJrd(_request, context$1) {
|
|
|
2031
2036
|
return Promise.resolve(response);
|
|
2032
2037
|
}
|
|
2033
2038
|
|
|
2034
|
-
//#endregion
|
|
2035
|
-
//#region src/webfinger/handler.ts
|
|
2036
|
-
const logger = getLogger([
|
|
2037
|
-
"fedify",
|
|
2038
|
-
"webfinger",
|
|
2039
|
-
"server"
|
|
2040
|
-
]);
|
|
2041
|
-
/**
|
|
2042
|
-
* Handles a WebFinger request. You would not typically call this function
|
|
2043
|
-
* directly, but instead use {@link Federation.fetch} method.
|
|
2044
|
-
* @param request The WebFinger request to handle.
|
|
2045
|
-
* @param parameters The parameters for handling the request.
|
|
2046
|
-
* @returns The response to the request.
|
|
2047
|
-
*/
|
|
2048
|
-
async function handleWebFinger(request, options) {
|
|
2049
|
-
if (options.tracer == null) return await handleWebFingerInternal(request, options);
|
|
2050
|
-
return await options.tracer.startActiveSpan("webfinger.handle", { kind: SpanKind.SERVER }, async (span) => {
|
|
2051
|
-
try {
|
|
2052
|
-
const response = await handleWebFingerInternal(request, options);
|
|
2053
|
-
span.setStatus({ code: response.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR });
|
|
2054
|
-
return response;
|
|
2055
|
-
} catch (error) {
|
|
2056
|
-
span.setStatus({
|
|
2057
|
-
code: SpanStatusCode.ERROR,
|
|
2058
|
-
message: String(error)
|
|
2059
|
-
});
|
|
2060
|
-
throw error;
|
|
2061
|
-
} finally {
|
|
2062
|
-
span.end();
|
|
2063
|
-
}
|
|
2064
|
-
});
|
|
2065
|
-
}
|
|
2066
|
-
async function handleWebFingerInternal(request, { context: context$1, host, actorDispatcher, actorHandleMapper, actorAliasMapper, onNotFound, span, webFingerLinksDispatcher }) {
|
|
2067
|
-
if (actorDispatcher == null) {
|
|
2068
|
-
logger.error("Actor dispatcher is not set.");
|
|
2069
|
-
return await onNotFound(request);
|
|
2070
|
-
}
|
|
2071
|
-
const resource = context$1.url.searchParams.get("resource");
|
|
2072
|
-
if (resource == null) return new Response("Missing resource parameter.", { status: 400 });
|
|
2073
|
-
span?.setAttribute("webfinger.resource", resource);
|
|
2074
|
-
let resourceUrl;
|
|
2075
|
-
try {
|
|
2076
|
-
resourceUrl = new URL(resource);
|
|
2077
|
-
} catch (e) {
|
|
2078
|
-
if (e instanceof TypeError) return new Response("Invalid resource URL.", { status: 400 });
|
|
2079
|
-
throw e;
|
|
2080
|
-
}
|
|
2081
|
-
span?.setAttribute("webfinger.resource.scheme", resourceUrl.protocol.replace(/:$/, ""));
|
|
2082
|
-
async function mapUsernameToIdentifier(username) {
|
|
2083
|
-
if (actorHandleMapper == null) {
|
|
2084
|
-
logger.error("No actor handle mapper is set; use the WebFinger username {username} as the actor's internal identifier.", { username });
|
|
2085
|
-
return username;
|
|
2086
|
-
}
|
|
2087
|
-
const identifier$1 = await actorHandleMapper(context$1, username);
|
|
2088
|
-
if (identifier$1 == null) {
|
|
2089
|
-
logger.error("Actor {username} not found.", { username });
|
|
2090
|
-
return null;
|
|
2091
|
-
}
|
|
2092
|
-
return identifier$1;
|
|
2093
|
-
}
|
|
2094
|
-
let identifier = null;
|
|
2095
|
-
const uriParsed = context$1.parseUri(resourceUrl);
|
|
2096
|
-
if (uriParsed?.type != "actor") {
|
|
2097
|
-
const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
|
|
2098
|
-
if (match == null) {
|
|
2099
|
-
const result = await actorAliasMapper?.(context$1, resourceUrl);
|
|
2100
|
-
if (result == null) return await onNotFound(request);
|
|
2101
|
-
if ("identifier" in result) identifier = result.identifier;
|
|
2102
|
-
else identifier = await mapUsernameToIdentifier(result.username);
|
|
2103
|
-
} else {
|
|
2104
|
-
const portMatch = /:\d+$/.exec(match[2]);
|
|
2105
|
-
const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
|
|
2106
|
-
if (normalizedHost != context$1.url.host && normalizedHost != host) return await onNotFound(request);
|
|
2107
|
-
else {
|
|
2108
|
-
identifier = await mapUsernameToIdentifier(match[1]);
|
|
2109
|
-
resourceUrl = new URL(`acct:${match[1]}@${normalizedHost}`);
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2112
|
-
} else identifier = uriParsed.identifier;
|
|
2113
|
-
if (identifier == null) return await onNotFound(request);
|
|
2114
|
-
const actor = await actorDispatcher(context$1, identifier);
|
|
2115
|
-
if (actor == null) {
|
|
2116
|
-
logger.error("Actor {identifier} not found.", { identifier });
|
|
2117
|
-
return await onNotFound(request);
|
|
2118
|
-
}
|
|
2119
|
-
const links = [{
|
|
2120
|
-
rel: "self",
|
|
2121
|
-
href: context$1.getActorUri(identifier).href,
|
|
2122
|
-
type: "application/activity+json"
|
|
2123
|
-
}];
|
|
2124
|
-
for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
|
|
2125
|
-
rel: url.rel ?? "http://webfinger.net/rel/profile-page",
|
|
2126
|
-
href: url.href.href,
|
|
2127
|
-
type: url.mediaType == null ? void 0 : url.mediaType
|
|
2128
|
-
});
|
|
2129
|
-
else if (url instanceof URL) links.push({
|
|
2130
|
-
rel: "http://webfinger.net/rel/profile-page",
|
|
2131
|
-
href: url.href
|
|
2132
|
-
});
|
|
2133
|
-
for await (const image of actor.getIcons()) {
|
|
2134
|
-
if (image.url?.href == null) continue;
|
|
2135
|
-
const link = {
|
|
2136
|
-
rel: "http://webfinger.net/rel/avatar",
|
|
2137
|
-
href: image.url.href.toString()
|
|
2138
|
-
};
|
|
2139
|
-
if (image.mediaType != null) link.type = image.mediaType;
|
|
2140
|
-
links.push(link);
|
|
2141
|
-
}
|
|
2142
|
-
if (webFingerLinksDispatcher != null) {
|
|
2143
|
-
const customLinks = await webFingerLinksDispatcher(context$1, resourceUrl);
|
|
2144
|
-
if (customLinks != null) for (const link of customLinks) links.push(link);
|
|
2145
|
-
}
|
|
2146
|
-
const aliases = [];
|
|
2147
|
-
if (resourceUrl.protocol != "acct:" && actor.preferredUsername != null) {
|
|
2148
|
-
aliases.push(`acct:${actor.preferredUsername}@${host ?? context$1.url.host}`);
|
|
2149
|
-
if (host != null && host !== context$1.url.host) aliases.push(`acct:${actor.preferredUsername}@${context$1.url.host}`);
|
|
2150
|
-
}
|
|
2151
|
-
if (resourceUrl.href !== context$1.getActorUri(identifier).href) aliases.push(context$1.getActorUri(identifier).href);
|
|
2152
|
-
if (resourceUrl.protocol === "acct:" && host != null && host !== context$1.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
|
|
2153
|
-
const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
|
|
2154
|
-
aliases.push(`acct:${username}@${host}`);
|
|
2155
|
-
}
|
|
2156
|
-
const jrd = {
|
|
2157
|
-
subject: resourceUrl.href,
|
|
2158
|
-
aliases,
|
|
2159
|
-
links
|
|
2160
|
-
};
|
|
2161
|
-
return new Response(JSON.stringify(jrd), { headers: {
|
|
2162
|
-
"Content-Type": "application/jrd+json",
|
|
2163
|
-
"Access-Control-Allow-Origin": "*"
|
|
2164
|
-
} });
|
|
2165
|
-
}
|
|
2166
|
-
|
|
2167
2039
|
//#endregion
|
|
2168
2040
|
//#region src/federation/retry.ts
|
|
2169
2041
|
/**
|
|
@@ -2190,8 +2062,8 @@ function createExponentialBackoffPolicy(options = {}) {
|
|
|
2190
2062
|
milliseconds *= 1 + Math.random();
|
|
2191
2063
|
milliseconds = Math.round(milliseconds);
|
|
2192
2064
|
}
|
|
2193
|
-
const delay
|
|
2194
|
-
return Temporal.Duration.compare(delay
|
|
2065
|
+
const delay = Temporal.Duration.from({ milliseconds });
|
|
2066
|
+
return Temporal.Duration.compare(delay, maxDelay) > 0 ? maxDelay : delay;
|
|
2195
2067
|
};
|
|
2196
2068
|
}
|
|
2197
2069
|
|
|
@@ -2243,7 +2115,7 @@ function sendActivity(options) {
|
|
|
2243
2115
|
await sendActivityInternal({
|
|
2244
2116
|
...options,
|
|
2245
2117
|
tracerProvider
|
|
2246
|
-
});
|
|
2118
|
+
}, span);
|
|
2247
2119
|
} catch (e) {
|
|
2248
2120
|
span.setStatus({
|
|
2249
2121
|
code: SpanStatusCode.ERROR,
|
|
@@ -2255,7 +2127,7 @@ function sendActivity(options) {
|
|
|
2255
2127
|
}
|
|
2256
2128
|
});
|
|
2257
2129
|
}
|
|
2258
|
-
async function sendActivityInternal({ activity, activityId, keys, inbox, headers, specDeterminer, tracerProvider }) {
|
|
2130
|
+
async function sendActivityInternal({ activity, activityId, keys, inbox, headers, specDeterminer, tracerProvider }, span) {
|
|
2259
2131
|
const logger$1 = getLogger([
|
|
2260
2132
|
"fedify",
|
|
2261
2133
|
"federation",
|
|
@@ -2310,6 +2182,144 @@ async function sendActivityInternal({ activity, activityId, keys, inbox, headers
|
|
|
2310
2182
|
});
|
|
2311
2183
|
throw new Error(`Failed to send activity ${activityId} to ${inbox.href} (${response.status} ${response.statusText}):\n${error}`);
|
|
2312
2184
|
}
|
|
2185
|
+
span.addEvent("activitypub.activity.sent", {
|
|
2186
|
+
"activitypub.activity.json": JSON.stringify(activity),
|
|
2187
|
+
"activitypub.inbox.url": inbox.href,
|
|
2188
|
+
"activitypub.activity.id": activityId ?? ""
|
|
2189
|
+
});
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
//#endregion
|
|
2193
|
+
//#region src/federation/webfinger.ts
|
|
2194
|
+
const logger = getLogger([
|
|
2195
|
+
"fedify",
|
|
2196
|
+
"webfinger",
|
|
2197
|
+
"server"
|
|
2198
|
+
]);
|
|
2199
|
+
/**
|
|
2200
|
+
* Handles a WebFinger request. You would not typically call this function
|
|
2201
|
+
* directly, but instead use {@link Federation.fetch} method.
|
|
2202
|
+
* @param request The WebFinger request to handle.
|
|
2203
|
+
* @param parameters The parameters for handling the request.
|
|
2204
|
+
* @returns The response to the request.
|
|
2205
|
+
*/
|
|
2206
|
+
async function handleWebFinger(request, options) {
|
|
2207
|
+
if (options.tracer == null) return await handleWebFingerInternal(request, options);
|
|
2208
|
+
return await options.tracer.startActiveSpan("webfinger.handle", { kind: SpanKind.SERVER }, async (span) => {
|
|
2209
|
+
try {
|
|
2210
|
+
const response = await handleWebFingerInternal(request, options);
|
|
2211
|
+
span.setStatus({ code: response.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR });
|
|
2212
|
+
return response;
|
|
2213
|
+
} catch (error) {
|
|
2214
|
+
span.setStatus({
|
|
2215
|
+
code: SpanStatusCode.ERROR,
|
|
2216
|
+
message: String(error)
|
|
2217
|
+
});
|
|
2218
|
+
throw error;
|
|
2219
|
+
} finally {
|
|
2220
|
+
span.end();
|
|
2221
|
+
}
|
|
2222
|
+
});
|
|
2223
|
+
}
|
|
2224
|
+
async function handleWebFingerInternal(request, { context: context$1, host, actorDispatcher, actorHandleMapper, actorAliasMapper, onNotFound, span, webFingerLinksDispatcher }) {
|
|
2225
|
+
if (actorDispatcher == null) {
|
|
2226
|
+
logger.error("Actor dispatcher is not set.");
|
|
2227
|
+
return await onNotFound(request);
|
|
2228
|
+
}
|
|
2229
|
+
const resource = context$1.url.searchParams.get("resource");
|
|
2230
|
+
if (resource == null) return new Response("Missing resource parameter.", { status: 400 });
|
|
2231
|
+
span?.setAttribute("webfinger.resource", resource);
|
|
2232
|
+
let resourceUrl;
|
|
2233
|
+
try {
|
|
2234
|
+
resourceUrl = new URL(resource);
|
|
2235
|
+
} catch (e) {
|
|
2236
|
+
if (e instanceof TypeError) return new Response("Invalid resource URL.", { status: 400 });
|
|
2237
|
+
throw e;
|
|
2238
|
+
}
|
|
2239
|
+
span?.setAttribute("webfinger.resource.scheme", resourceUrl.protocol.replace(/:$/, ""));
|
|
2240
|
+
async function mapUsernameToIdentifier(username) {
|
|
2241
|
+
if (actorHandleMapper == null) {
|
|
2242
|
+
logger.error("No actor handle mapper is set; use the WebFinger username {username} as the actor's internal identifier.", { username });
|
|
2243
|
+
return username;
|
|
2244
|
+
}
|
|
2245
|
+
const identifier$1 = await actorHandleMapper(context$1, username);
|
|
2246
|
+
if (identifier$1 == null) {
|
|
2247
|
+
logger.error("Actor {username} not found.", { username });
|
|
2248
|
+
return null;
|
|
2249
|
+
}
|
|
2250
|
+
return identifier$1;
|
|
2251
|
+
}
|
|
2252
|
+
let identifier = null;
|
|
2253
|
+
const uriParsed = context$1.parseUri(resourceUrl);
|
|
2254
|
+
if (uriParsed?.type != "actor") {
|
|
2255
|
+
const match = /^acct:([^@]+)@([^@]+)$/.exec(resource);
|
|
2256
|
+
if (match == null) {
|
|
2257
|
+
const result = await actorAliasMapper?.(context$1, resourceUrl);
|
|
2258
|
+
if (result == null) return await onNotFound(request);
|
|
2259
|
+
if ("identifier" in result) identifier = result.identifier;
|
|
2260
|
+
else identifier = await mapUsernameToIdentifier(result.username);
|
|
2261
|
+
} else {
|
|
2262
|
+
const portMatch = /:\d+$/.exec(match[2]);
|
|
2263
|
+
const normalizedHost = portMatch == null ? domainToASCII(match[2].toLowerCase()) : domainToASCII(match[2].substring(0, portMatch.index).toLowerCase()) + portMatch[0];
|
|
2264
|
+
if (normalizedHost != context$1.url.host && normalizedHost != host) return await onNotFound(request);
|
|
2265
|
+
else {
|
|
2266
|
+
identifier = await mapUsernameToIdentifier(match[1]);
|
|
2267
|
+
resourceUrl = new URL(`acct:${match[1]}@${normalizedHost}`);
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
} else identifier = uriParsed.identifier;
|
|
2271
|
+
if (identifier == null) return await onNotFound(request);
|
|
2272
|
+
const actor = await actorDispatcher(context$1, identifier);
|
|
2273
|
+
if (actor == null) {
|
|
2274
|
+
logger.error("Actor {identifier} not found.", { identifier });
|
|
2275
|
+
return await onNotFound(request);
|
|
2276
|
+
}
|
|
2277
|
+
const links = [{
|
|
2278
|
+
rel: "self",
|
|
2279
|
+
href: context$1.getActorUri(identifier).href,
|
|
2280
|
+
type: "application/activity+json"
|
|
2281
|
+
}];
|
|
2282
|
+
for (const url of actor.urls) if (url instanceof Link && url.href != null) links.push({
|
|
2283
|
+
rel: url.rel ?? "http://webfinger.net/rel/profile-page",
|
|
2284
|
+
href: url.href.href,
|
|
2285
|
+
type: url.mediaType == null ? void 0 : url.mediaType
|
|
2286
|
+
});
|
|
2287
|
+
else if (url instanceof URL) links.push({
|
|
2288
|
+
rel: "http://webfinger.net/rel/profile-page",
|
|
2289
|
+
href: url.href
|
|
2290
|
+
});
|
|
2291
|
+
for await (const image of actor.getIcons()) {
|
|
2292
|
+
if (image.url?.href == null) continue;
|
|
2293
|
+
const link = {
|
|
2294
|
+
rel: "http://webfinger.net/rel/avatar",
|
|
2295
|
+
href: image.url.href.toString()
|
|
2296
|
+
};
|
|
2297
|
+
if (image.mediaType != null) link.type = image.mediaType;
|
|
2298
|
+
links.push(link);
|
|
2299
|
+
}
|
|
2300
|
+
if (webFingerLinksDispatcher != null) {
|
|
2301
|
+
const customLinks = await webFingerLinksDispatcher(context$1, resourceUrl);
|
|
2302
|
+
if (customLinks != null) for (const link of customLinks) links.push(link);
|
|
2303
|
+
}
|
|
2304
|
+
const aliases = [];
|
|
2305
|
+
if (resourceUrl.protocol != "acct:" && actor.preferredUsername != null) {
|
|
2306
|
+
aliases.push(`acct:${actor.preferredUsername}@${host ?? context$1.url.host}`);
|
|
2307
|
+
if (host != null && host !== context$1.url.host) aliases.push(`acct:${actor.preferredUsername}@${context$1.url.host}`);
|
|
2308
|
+
}
|
|
2309
|
+
if (resourceUrl.href !== context$1.getActorUri(identifier).href) aliases.push(context$1.getActorUri(identifier).href);
|
|
2310
|
+
if (resourceUrl.protocol === "acct:" && host != null && host !== context$1.url.host && !resourceUrl.href.endsWith(`@${host}`)) {
|
|
2311
|
+
const username = resourceUrl.href.replace(/^acct:/, "").replace(/@.*$/, "");
|
|
2312
|
+
aliases.push(`acct:${username}@${host}`);
|
|
2313
|
+
}
|
|
2314
|
+
const jrd = {
|
|
2315
|
+
subject: resourceUrl.href,
|
|
2316
|
+
aliases,
|
|
2317
|
+
links
|
|
2318
|
+
};
|
|
2319
|
+
return new Response(JSON.stringify(jrd), { headers: {
|
|
2320
|
+
"Content-Type": "application/jrd+json",
|
|
2321
|
+
"Access-Control-Allow-Origin": "*"
|
|
2322
|
+
} });
|
|
2313
2323
|
}
|
|
2314
2324
|
|
|
2315
2325
|
//#endregion
|
|
@@ -2349,7 +2359,6 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2349
2359
|
firstKnock;
|
|
2350
2360
|
constructor(options) {
|
|
2351
2361
|
super();
|
|
2352
|
-
const logger$1 = getLogger(["fedify", "federation"]);
|
|
2353
2362
|
this.kv = options.kv;
|
|
2354
2363
|
this.kvPrefixes = {
|
|
2355
2364
|
activityIdempotence: ["_fedify", "activityIdempotence"],
|
|
@@ -2397,8 +2406,9 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2397
2406
|
this.router.trailingSlashInsensitive = options.trailingSlashInsensitive ?? false;
|
|
2398
2407
|
this._initializeRouter();
|
|
2399
2408
|
if (options.allowPrivateAddress || options.userAgent != null) {
|
|
2400
|
-
if (options.
|
|
2401
|
-
|
|
2409
|
+
if (options.documentLoaderFactory != null) throw new TypeError("Cannot set documentLoaderFactory with allowPrivateAddress or userAgent options.");
|
|
2410
|
+
if (options.contextLoaderFactory != null) throw new TypeError("Cannot set contextLoaderFactory with allowPrivateAddress or userAgent options.");
|
|
2411
|
+
if (options.authenticatedDocumentLoaderFactory != null) throw new TypeError("Cannot set authenticatedDocumentLoaderFactory with allowPrivateAddress or userAgent options.");
|
|
2402
2412
|
}
|
|
2403
2413
|
const { allowPrivateAddress, userAgent } = options;
|
|
2404
2414
|
this.allowPrivateAddress = allowPrivateAddress ?? false;
|
|
@@ -2412,11 +2422,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2412
2422
|
prefix: this.kvPrefixes.remoteDocument
|
|
2413
2423
|
});
|
|
2414
2424
|
});
|
|
2415
|
-
|
|
2416
|
-
if (options.contextLoaderFactory != null) throw new TypeError("Cannot set both contextLoader and contextLoaderFactory options at a time; use contextLoaderFactory only.");
|
|
2417
|
-
this.contextLoaderFactory = () => options.contextLoader;
|
|
2418
|
-
logger$1.warn("The contextLoader option is deprecated; use contextLoaderFactory option instead.");
|
|
2419
|
-
} else this.contextLoaderFactory = options.contextLoaderFactory ?? this.documentLoaderFactory;
|
|
2425
|
+
this.contextLoaderFactory = options.contextLoaderFactory ?? this.documentLoaderFactory;
|
|
2420
2426
|
this.authenticatedDocumentLoaderFactory = options.authenticatedDocumentLoaderFactory ?? ((identity) => getAuthenticatedDocumentLoader(identity, {
|
|
2421
2427
|
allowPrivateAddress,
|
|
2422
2428
|
userAgent,
|
|
@@ -2620,11 +2626,11 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2620
2626
|
});
|
|
2621
2627
|
throw error;
|
|
2622
2628
|
}
|
|
2623
|
-
const delay
|
|
2629
|
+
const delay = this.outboxRetryPolicy({
|
|
2624
2630
|
elapsedTime: Temporal.Instant.from(message.started).until(Temporal.Now.instant()),
|
|
2625
2631
|
attempts: message.attempt
|
|
2626
2632
|
});
|
|
2627
|
-
if (delay
|
|
2633
|
+
if (delay != null) {
|
|
2628
2634
|
logger$1.error("Failed to send activity {activityId} to {inbox} (attempt #{attempt}); retry...:\n{error}", {
|
|
2629
2635
|
...logData,
|
|
2630
2636
|
error
|
|
@@ -2632,7 +2638,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2632
2638
|
await this.outboxQueue?.enqueue({
|
|
2633
2639
|
...message,
|
|
2634
2640
|
attempt: message.attempt + 1
|
|
2635
|
-
}, { delay: Temporal.Duration.compare(delay
|
|
2641
|
+
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2636
2642
|
} else logger$1.error("Failed to send activity {activityId} to {inbox} after {attempt} attempts; giving up:\n{error}", {
|
|
2637
2643
|
...logData,
|
|
2638
2644
|
error
|
|
@@ -2719,11 +2725,11 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2719
2725
|
span$1.end();
|
|
2720
2726
|
throw error;
|
|
2721
2727
|
}
|
|
2722
|
-
const delay
|
|
2728
|
+
const delay = this.inboxRetryPolicy({
|
|
2723
2729
|
elapsedTime: Temporal.Instant.from(message.started).until(Temporal.Now.instant()),
|
|
2724
2730
|
attempts: message.attempt
|
|
2725
2731
|
});
|
|
2726
|
-
if (delay
|
|
2732
|
+
if (delay != null) {
|
|
2727
2733
|
logger$1.error("Failed to process the incoming activity {activityId} (attempt #{attempt}); retry...:\n{error}", {
|
|
2728
2734
|
error,
|
|
2729
2735
|
attempt: message.attempt,
|
|
@@ -2734,7 +2740,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2734
2740
|
await this.inboxQueue?.enqueue({
|
|
2735
2741
|
...message,
|
|
2736
2742
|
attempt: message.attempt + 1
|
|
2737
|
-
}, { delay: Temporal.Duration.compare(delay
|
|
2743
|
+
}, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
|
|
2738
2744
|
} else logger$1.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
|
|
2739
2745
|
error,
|
|
2740
2746
|
activityId: activity.id?.href,
|
|
@@ -2955,6 +2961,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2955
2961
|
span,
|
|
2956
2962
|
tracer
|
|
2957
2963
|
});
|
|
2964
|
+
if (acceptsJsonLd(request)) response.headers.set("Vary", "Accept");
|
|
2958
2965
|
} catch (error) {
|
|
2959
2966
|
span.setStatus({
|
|
2960
2967
|
code: SpanStatusCode.ERROR,
|
|
@@ -3018,6 +3025,9 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3018
3025
|
context: context$1,
|
|
3019
3026
|
nodeInfoDispatcher: this.nodeInfoDispatcher
|
|
3020
3027
|
});
|
|
3028
|
+
}
|
|
3029
|
+
if (request.method !== "POST" && !acceptsJsonLd(request)) return await onNotAcceptable(request);
|
|
3030
|
+
switch (routeName) {
|
|
3021
3031
|
case "actor":
|
|
3022
3032
|
context$1 = this.#createContext(request, contextData, { invokedFromActorDispatcher: { identifier: route.values.identifier ?? route.values.handle } });
|
|
3023
3033
|
return await handleActor(request, {
|
|
@@ -3026,8 +3036,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3026
3036
|
actorDispatcher: this.actorCallbacks?.dispatcher,
|
|
3027
3037
|
authorizePredicate: this.actorCallbacks?.authorizePredicate,
|
|
3028
3038
|
onUnauthorized,
|
|
3029
|
-
onNotFound
|
|
3030
|
-
onNotAcceptable
|
|
3039
|
+
onNotFound
|
|
3031
3040
|
});
|
|
3032
3041
|
case "object": {
|
|
3033
3042
|
const typeId = route.name.replace(/^object:/, "");
|
|
@@ -3043,8 +3052,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3043
3052
|
objectDispatcher: callbacks?.dispatcher,
|
|
3044
3053
|
authorizePredicate: callbacks?.authorizePredicate,
|
|
3045
3054
|
onUnauthorized,
|
|
3046
|
-
onNotFound
|
|
3047
|
-
onNotAcceptable
|
|
3055
|
+
onNotFound
|
|
3048
3056
|
});
|
|
3049
3057
|
}
|
|
3050
3058
|
case "outbox": return await handleCollection(request, {
|
|
@@ -3055,8 +3063,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3055
3063
|
collectionCallbacks: this.outboxCallbacks,
|
|
3056
3064
|
tracerProvider: this.tracerProvider,
|
|
3057
3065
|
onUnauthorized,
|
|
3058
|
-
onNotFound
|
|
3059
|
-
onNotAcceptable
|
|
3066
|
+
onNotFound
|
|
3060
3067
|
});
|
|
3061
3068
|
case "inbox":
|
|
3062
3069
|
if (request.method !== "POST") return await handleCollection(request, {
|
|
@@ -3067,8 +3074,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3067
3074
|
collectionCallbacks: this.inboxCallbacks,
|
|
3068
3075
|
tracerProvider: this.tracerProvider,
|
|
3069
3076
|
onUnauthorized,
|
|
3070
|
-
onNotFound
|
|
3071
|
-
onNotAcceptable
|
|
3077
|
+
onNotFound
|
|
3072
3078
|
});
|
|
3073
3079
|
context$1 = this.#createContext(request, contextData, { documentLoader: await context$1.getDocumentLoader({ identifier: route.values.identifier ?? route.values.handle }) });
|
|
3074
3080
|
case "sharedInbox":
|
|
@@ -3090,7 +3096,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3090
3096
|
onNotFound,
|
|
3091
3097
|
signatureTimeWindow: this.signatureTimeWindow,
|
|
3092
3098
|
skipSignatureVerification: this.skipSignatureVerification,
|
|
3093
|
-
tracerProvider: this.tracerProvider
|
|
3099
|
+
tracerProvider: this.tracerProvider,
|
|
3100
|
+
idempotencyStrategy: this.idempotencyStrategy
|
|
3094
3101
|
});
|
|
3095
3102
|
case "following": return await handleCollection(request, {
|
|
3096
3103
|
name: "following",
|
|
@@ -3100,8 +3107,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3100
3107
|
collectionCallbacks: this.followingCallbacks,
|
|
3101
3108
|
tracerProvider: this.tracerProvider,
|
|
3102
3109
|
onUnauthorized,
|
|
3103
|
-
onNotFound
|
|
3104
|
-
onNotAcceptable
|
|
3110
|
+
onNotFound
|
|
3105
3111
|
});
|
|
3106
3112
|
case "followers": {
|
|
3107
3113
|
let baseUrl = url.searchParams.get("base-url");
|
|
@@ -3124,8 +3130,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3124
3130
|
collectionCallbacks: this.followersCallbacks,
|
|
3125
3131
|
tracerProvider: this.tracerProvider,
|
|
3126
3132
|
onUnauthorized,
|
|
3127
|
-
onNotFound
|
|
3128
|
-
onNotAcceptable
|
|
3133
|
+
onNotFound
|
|
3129
3134
|
});
|
|
3130
3135
|
}
|
|
3131
3136
|
case "liked": return await handleCollection(request, {
|
|
@@ -3136,8 +3141,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3136
3141
|
collectionCallbacks: this.likedCallbacks,
|
|
3137
3142
|
tracerProvider: this.tracerProvider,
|
|
3138
3143
|
onUnauthorized,
|
|
3139
|
-
onNotFound
|
|
3140
|
-
onNotAcceptable
|
|
3144
|
+
onNotFound
|
|
3141
3145
|
});
|
|
3142
3146
|
case "featured": return await handleCollection(request, {
|
|
3143
3147
|
name: "featured",
|
|
@@ -3147,8 +3151,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3147
3151
|
collectionCallbacks: this.featuredCallbacks,
|
|
3148
3152
|
tracerProvider: this.tracerProvider,
|
|
3149
3153
|
onUnauthorized,
|
|
3150
|
-
onNotFound
|
|
3151
|
-
onNotAcceptable
|
|
3154
|
+
onNotFound
|
|
3152
3155
|
});
|
|
3153
3156
|
case "featuredTags": return await handleCollection(request, {
|
|
3154
3157
|
name: "featured tags",
|
|
@@ -3158,8 +3161,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3158
3161
|
collectionCallbacks: this.featuredTagsCallbacks,
|
|
3159
3162
|
tracerProvider: this.tracerProvider,
|
|
3160
3163
|
onUnauthorized,
|
|
3161
|
-
onNotFound
|
|
3162
|
-
onNotAcceptable
|
|
3164
|
+
onNotFound
|
|
3163
3165
|
});
|
|
3164
3166
|
case "collection": {
|
|
3165
3167
|
const name = route.name.replace(/^collection:/, "");
|
|
@@ -3171,8 +3173,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3171
3173
|
collectionCallbacks: callbacks,
|
|
3172
3174
|
tracerProvider: this.tracerProvider,
|
|
3173
3175
|
onUnauthorized,
|
|
3174
|
-
onNotFound
|
|
3175
|
-
onNotAcceptable
|
|
3176
|
+
onNotFound
|
|
3176
3177
|
});
|
|
3177
3178
|
}
|
|
3178
3179
|
case "orderedCollection": {
|
|
@@ -3185,8 +3186,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3185
3186
|
collectionCallbacks: callbacks,
|
|
3186
3187
|
tracerProvider: this.tracerProvider,
|
|
3187
3188
|
onUnauthorized,
|
|
3188
|
-
onNotFound
|
|
3189
|
-
onNotAcceptable
|
|
3189
|
+
onNotFound
|
|
3190
3190
|
});
|
|
3191
3191
|
}
|
|
3192
3192
|
default: {
|
|
@@ -3481,15 +3481,16 @@ var ContextImpl = class ContextImpl {
|
|
|
3481
3481
|
"actor"
|
|
3482
3482
|
]);
|
|
3483
3483
|
if (this.federation.actorCallbacks?.keyPairsDispatcher == null) throw new Error("No actor key pairs dispatcher registered.");
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
})
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3484
|
+
let actorUri;
|
|
3485
|
+
try {
|
|
3486
|
+
actorUri = this.getActorUri(identifier);
|
|
3487
|
+
} catch (error) {
|
|
3488
|
+
if (error instanceof RouterError) {
|
|
3489
|
+
logger$1.warn(error.message);
|
|
3490
|
+
return [];
|
|
3491
|
+
}
|
|
3492
|
+
throw error;
|
|
3491
3493
|
}
|
|
3492
|
-
const actorUri = new URL(path, this.canonicalOrigin);
|
|
3493
3494
|
const keyPairs = await this.federation.actorCallbacks?.keyPairsDispatcher(new ContextImpl({
|
|
3494
3495
|
...this,
|
|
3495
3496
|
invokedFromActorKeyPairsDispatcher: { identifier }
|
|
@@ -3650,12 +3651,11 @@ var ContextImpl = class ContextImpl {
|
|
|
3650
3651
|
if (identifier == null) throw new Error("If recipients is \"followers\", sender must be an actor identifier or username.");
|
|
3651
3652
|
expandedRecipients = [];
|
|
3652
3653
|
for await (const recipient of this.getFollowers(identifier)) expandedRecipients.push(recipient);
|
|
3653
|
-
if (options.syncCollection) {
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
opts.collectionSync = collectionId == null ? void 0 : new URL(collectionId, this.canonicalOrigin).href;
|
|
3654
|
+
if (options.syncCollection) try {
|
|
3655
|
+
opts.collectionSync = this.getFollowersUri(identifier).href;
|
|
3656
|
+
} catch (error) {
|
|
3657
|
+
if (error instanceof RouterError) opts.collectionSync = void 0;
|
|
3658
|
+
else throw error;
|
|
3659
3659
|
}
|
|
3660
3660
|
} else expandedRecipients = [recipients];
|
|
3661
3661
|
span.setAttribute("activitypub.inboxes", expandedRecipients.length);
|
|
@@ -3840,7 +3840,8 @@ var ContextImpl = class ContextImpl {
|
|
|
3840
3840
|
kvPrefixes: this.federation.kvPrefixes,
|
|
3841
3841
|
queue: this.federation.inboxQueue,
|
|
3842
3842
|
span,
|
|
3843
|
-
tracerProvider: options.tracerProvider ?? this.tracerProvider
|
|
3843
|
+
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
3844
|
+
idempotencyStrategy: this.federation.idempotencyStrategy
|
|
3844
3845
|
});
|
|
3845
3846
|
return routeResult === "alreadyProcessed" || routeResult === "enqueued" || routeResult === "unsupportedActivity" || routeResult === "success";
|
|
3846
3847
|
}
|
|
@@ -4154,4 +4155,4 @@ function getRequestId(request) {
|
|
|
4154
4155
|
}
|
|
4155
4156
|
|
|
4156
4157
|
//#endregion
|
|
4157
|
-
export { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, Router$1 as Router, RouterError, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, respondWithObject, respondWithObjectIfAcceptable };
|
|
4158
|
+
export { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, Router$1 as Router, RouterError, buildCollectionSynchronizationHeader, createExponentialBackoffPolicy, createFederation, createFederationBuilder, digest, handleWebFinger, respondWithObject, respondWithObjectIfAcceptable };
|