@fedify/fedify 2.3.0-dev.1131 → 2.3.0-dev.1145
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/README.md +3 -0
- package/dist/{assert-DikXweDx.mjs → assert-OguE97r2.mjs} +1 -1
- package/dist/{assert_instance_of-C4Ri6VuN.mjs → assert_instance_of-DBC5X09g.mjs} +1 -1
- package/dist/{assert_not_equals--wG9hV7u.mjs → assert_not_equals-DkVK8oqV.mjs} +1 -1
- package/dist/{assert_rejects-DQP-q39h.mjs → assert_rejects-DN60FHPX.mjs} +2 -2
- package/dist/{assert_strict_equals-Dmjbg-bA.mjs → assert_strict_equals-XEgZAlrj.mjs} +1 -1
- package/dist/{assert_throws-4NwKEy2q.mjs → assert_throws-BOkhLGYc.mjs} +1 -1
- package/dist/{builder-DckAhD27.mjs → builder-ShiR1K6b.mjs} +60 -41
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/outgoing-jsonld.test.mjs +3 -3
- package/dist/compat/public-audience.test.mjs +3 -3
- package/dist/compat/transformers.test.mjs +5 -5
- package/dist/{context-Cq18Gplu.d.ts → context-DCtsSHDv.d.ts} +2 -86
- package/dist/{context-tc6VOOOL.d.cts → context-DI2gRbyN.d.cts} +1 -87
- package/dist/{context-BAE7AKLA.mjs → context-DVoTs_wM.mjs} +1 -1
- package/dist/{deno--CS-SBS9.mjs → deno-h0TWFuEz.mjs} +1 -1
- package/dist/{docloader-k6huZLQL.mjs → docloader-BdDN0Aqx.mjs} +3 -3
- package/dist/federation/builder.test.mjs +138 -10
- package/dist/federation/collection.test.mjs +3 -3
- package/dist/federation/handler.test.mjs +12 -12
- package/dist/federation/idempotency.test.mjs +6 -6
- package/dist/federation/inbox.test.mjs +3 -3
- package/dist/federation/keycache.test.mjs +5 -5
- package/dist/federation/kv.test.mjs +3 -3
- package/dist/federation/metrics.test.mjs +63 -4
- package/dist/federation/middleware.test.mjs +30 -18
- package/dist/federation/mod.cjs +155 -3
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +153 -1
- package/dist/federation/mq.test.mjs +5 -5
- package/dist/federation/negotiation.test.mjs +4 -4
- package/dist/federation/retry.test.mjs +3 -3
- package/dist/federation/router.test.mjs +190 -9
- package/dist/federation/send.test.mjs +16 -16
- package/dist/federation/webfinger.test.mjs +151 -6
- package/dist/{getMachineId-bsd-BY01PL1n.mjs → getMachineId-bsd-etIyxDet.mjs} +1 -1
- package/dist/{getMachineId-darwin-Dr1gkBkp.mjs → getMachineId-darwin-D23zTf4g.mjs} +1 -1
- package/dist/{getMachineId-win-QEYwcJiy.mjs → getMachineId-win-Dpap6v5i.mjs} +1 -1
- package/dist/{http-CJfvRL7D.cjs → http-7kAB7PVx.cjs} +53 -1
- package/dist/{http-cqujdCRz.js → http-B2hxA7dO.js} +48 -2
- package/dist/{http-IywnQdiX.mjs → http-QzW9IWfs.mjs} +4 -4
- package/dist/{key-Df3tMleh.mjs → key-Dh2OK1XQ.mjs} +2 -2
- package/dist/{kv-cache-L0SMQkcd.cjs → kv-cache-DCPp-MT0.cjs} +1 -1
- package/dist/{kv-cache-q9Ec2ryS.mjs → kv-cache-EZRIPZXD.mjs} +1 -1
- package/dist/{kv-cache-pEejzYq4.js → kv-cache-b22dNkjt.js} +1 -1
- package/dist/{ld-BGwiJpl3.mjs → ld-eZbar1rr.mjs} +3 -3
- package/dist/{metrics-BTOMkW8C.mjs → metrics-E0hAHtLZ.mjs} +48 -2
- package/dist/{middleware-B2rtdpFV.cjs → middleware-BUl1BH4x.cjs} +163 -212
- package/dist/{middleware-DtOddSVg.js → middleware-BrGIM_Ra.js} +127 -164
- package/dist/{middleware-BB0IbDow.mjs → middleware-CyJDCmNg.mjs} +89 -37
- package/dist/{middleware-Dnql59Y8.mjs → middleware-mToCR2tG.mjs} +1 -1
- package/dist/mod-CI9fduEi.d.cts +182 -0
- package/dist/mod-CkRiJHGA.d.ts +182 -0
- package/dist/mod.cjs +6 -6
- package/dist/mod.d.cts +2 -2
- package/dist/mod.d.ts +2 -2
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/client.test.mjs +4 -4
- package/dist/nodeinfo/handler.test.mjs +5 -5
- package/dist/nodeinfo/types.test.mjs +4 -4
- package/dist/otel/exporter.test.mjs +3 -3
- package/dist/{outgoing-jsonld-BNL8AC14.mjs → outgoing-jsonld-BgFLCJQ_.mjs} +1 -1
- package/dist/{owner-CIt4hvmM.mjs → owner-ByO_Fw6U.mjs} +2 -2
- package/dist/{proof-DMGIjHYH.js → proof-BkRyFchv.js} +1 -1
- package/dist/{proof-BYlrRSmZ.mjs → proof-CSo0S8OK.mjs} +5 -5
- package/dist/{proof-B1_u25UV.cjs → proof-jVqClF49.cjs} +1 -1
- package/dist/{send-DJFpze7B.mjs → send-jzrTV1FU.mjs} +3 -3
- package/dist/sig/accept.test.mjs +1 -1
- package/dist/sig/http.test.mjs +9 -9
- package/dist/sig/key.test.mjs +6 -6
- package/dist/sig/ld.test.mjs +7 -7
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +6 -6
- package/dist/sig/proof.test.mjs +8 -8
- package/dist/{std__assert-BTEgfoJo.mjs → std__assert-BBjXFNOb.mjs} +4 -4
- package/dist/testing/mod.d.mts +1 -0
- package/dist/testing/mod.mjs +1 -1
- package/dist/utils/docloader.test.mjs +7 -7
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +6 -7
- package/dist/mod-CajNYYkt.d.ts +0 -63
- package/dist/mod-DnzgcPcy.d.cts +0 -63
- package/dist/router-BT_F5748.mjs +0 -114
- /package/dist/{accept-CgDcxvjV.mjs → accept-CceiKpCy.mjs} +0 -0
- /package/dist/{activity-listener-BeTGV3wc.mjs → activity-listener-tztVvlNb.mjs} +0 -0
- /package/dist/{assert_equals-Ew3jOFa3.mjs → assert_equals-C-ZRDbaf.mjs} +0 -0
- /package/dist/{client-Bneh_DYR.mjs → client-B_A6mfn3.mjs} +0 -0
- /package/dist/{collection-Cc3DVAhE.mjs → collection-CA3V5zyK.mjs} +0 -0
- /package/dist/{esm-sdtqOUPu.mjs → esm-BQRw925N.mjs} +0 -0
- /package/dist/{execAsync-Dxb7rNf3.mjs → execAsync-DCBrgFiV.mjs} +0 -0
- /package/dist/{getMachineId-linux-Bbhofx-s.mjs → getMachineId-linux-ObI47Hql.mjs} +0 -0
- /package/dist/{getMachineId-unsupported-dIOte2Ct.mjs → getMachineId-unsupported-Ddu-PFeh.mjs} +0 -0
- /package/dist/{keycache-BeU0LCII.mjs → keycache-BYMd8q7F.mjs} +0 -0
- /package/dist/{keys-CSYsOMFG.mjs → keys-C3kae-6B.mjs} +0 -0
- /package/dist/{kv-QHE0oeM3.mjs → kv-x2IvBUyq.mjs} +0 -0
- /package/dist/{negotiation-DDstyBvc.mjs → negotiation-CDW-_gUU.mjs} +0 -0
- /package/dist/{public-audience-c9zmYKgA.mjs → public-audience-N3pyOx2p.mjs} +0 -0
- /package/dist/{retry-_VvV0h9f.mjs → retry-v_sGLH1d.mjs} +0 -0
- /package/dist/{types-D09GN0uZ.mjs → types-BFowWFTT.mjs} +0 -0
|
@@ -2,17 +2,16 @@ import { Temporal } from "@js-temporal/polyfill";
|
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
import { t as __exportAll } from "./chunk-CRNNMoPX.js";
|
|
4
4
|
import { r as getDefaultActivityTransformers } from "./transformers-BGMIq1cs.js";
|
|
5
|
-
import { C as
|
|
6
|
-
import { c as getKeyOwner, d as detachSignature, f as hasSignatureLike, i as verifyObject, m as verifyJsonLd, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, p as signJsonLd, r as signObject, s as doesActorOwnKey } from "./proof-
|
|
5
|
+
import { C as recordWebFingerHandle, O as name, S as recordOutboxEnqueue, a as verifyRequestDetailed, b as recordInboxActivity, d as validateCryptoKey, f as getDurationMs, g as isAbortError, h as instrumentDocumentLoader, i as verifyRequest, k as version, m as getRemoteHost, n as parseRfc9421SignatureInput, o as exportJwk, p as getFederationMetrics, t as doubleKnock, u as importJwk, w as formatAcceptSignature, x as recordOutboxActivity, y as recordFanoutRecipients } from "./http-B2hxA7dO.js";
|
|
6
|
+
import { c as getKeyOwner, d as detachSignature, f as hasSignatureLike, i as verifyObject, m as verifyJsonLd, n as hasProofLike, o as normalizeOutgoingActivityJsonLd, p as signJsonLd, r as signObject, s as doesActorOwnKey } from "./proof-BkRyFchv.js";
|
|
7
7
|
import { n as getNodeInfo, t as nodeInfoToJson } from "./types-CAY3OdLq.js";
|
|
8
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-b22dNkjt.js";
|
|
9
9
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
10
|
+
import { Router, RouterError, assertPath } from "@fedify/uri-template";
|
|
10
11
|
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
11
12
|
import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
|
|
12
|
-
import { cloneDeep, uniq } from "es-toolkit";
|
|
13
|
-
import { Router } from "uri-template-router";
|
|
14
|
-
import { parseTemplate } from "url-template";
|
|
15
13
|
import { encodeHex } from "byte-encodings/hex";
|
|
14
|
+
import { uniq } from "es-toolkit";
|
|
16
15
|
import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
|
|
17
16
|
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
17
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
@@ -52,126 +51,33 @@ var ActivityListenerSet = class {
|
|
|
52
51
|
}
|
|
53
52
|
};
|
|
54
53
|
//#endregion
|
|
55
|
-
//#region src/federation/
|
|
56
|
-
|
|
57
|
-
const clone = new Router();
|
|
58
|
-
clone.nid = router.nid;
|
|
59
|
-
clone.fsm = cloneDeep(router.fsm);
|
|
60
|
-
clone.routeSet = new Set(router.routeSet);
|
|
61
|
-
clone.templateRouteMap = new Map(router.templateRouteMap);
|
|
62
|
-
clone.valueRouteMap = new Map(router.valueRouteMap);
|
|
63
|
-
clone.hierarchy = cloneDeep(router.hierarchy);
|
|
64
|
-
return clone;
|
|
65
|
-
}
|
|
54
|
+
//#region src/federation/builder.ts
|
|
55
|
+
const ACTOR_ALIAS_PREFIX = "actorAlias:";
|
|
66
56
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
57
|
+
* Route options shared by every dispatcher whose path must expose exactly
|
|
58
|
+
* one `{identifier}` variable bound to a single, non-empty value
|
|
59
|
+
* for `setOutboxDispatcher/Listener()`.
|
|
69
60
|
*/
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
#templateStrings;
|
|
74
|
-
/**
|
|
75
|
-
* Whether to ignore trailing slashes when matching paths.
|
|
76
|
-
* @since 1.6.0
|
|
77
|
-
*/
|
|
78
|
-
trailingSlashInsensitive;
|
|
79
|
-
/**
|
|
80
|
-
* Create a new {@link Router}.
|
|
81
|
-
* @param options Options for the router.
|
|
82
|
-
*/
|
|
83
|
-
constructor(options = {}) {
|
|
84
|
-
this.#router = new Router();
|
|
85
|
-
this.#templates = {};
|
|
86
|
-
this.#templateStrings = {};
|
|
87
|
-
this.trailingSlashInsensitive = options.trailingSlashInsensitive ?? false;
|
|
88
|
-
}
|
|
89
|
-
clone() {
|
|
90
|
-
const clone = new Router$1({ trailingSlashInsensitive: this.trailingSlashInsensitive });
|
|
91
|
-
clone.#router = cloneInnerRouter(this.#router);
|
|
92
|
-
clone.#templates = { ...this.#templates };
|
|
93
|
-
clone.#templateStrings = { ...this.#templateStrings };
|
|
94
|
-
return clone;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Checks if a path name exists in the router.
|
|
98
|
-
* @param name The name of the path.
|
|
99
|
-
* @returns `true` if the path name exists, otherwise `false`.
|
|
100
|
-
*/
|
|
101
|
-
has(name) {
|
|
102
|
-
return name in this.#templates;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Adds a new path rule to the router.
|
|
106
|
-
* @param template The path pattern.
|
|
107
|
-
* @param name The name of the path.
|
|
108
|
-
* @returns The names of the variables in the path pattern.
|
|
109
|
-
*/
|
|
110
|
-
add(template, name) {
|
|
111
|
-
if (!template.startsWith("/")) throw new RouterError("Path must start with a slash.");
|
|
112
|
-
const rule = this.#router.addTemplate(template, {}, name);
|
|
113
|
-
this.#templates[name] = parseTemplate(template);
|
|
114
|
-
this.#templateStrings[name] = template;
|
|
115
|
-
return new Set(rule.variables.map((v) => v.varname));
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Resolves a path name and values from a URL, if any match.
|
|
119
|
-
* @param url The URL to resolve.
|
|
120
|
-
* @returns The name of the path and its values, if any match. Otherwise,
|
|
121
|
-
* `null`.
|
|
122
|
-
*/
|
|
123
|
-
route(url) {
|
|
124
|
-
let match = this.#router.resolveURI(url);
|
|
125
|
-
if (match == null) {
|
|
126
|
-
if (!this.trailingSlashInsensitive) return null;
|
|
127
|
-
url = url.endsWith("/") ? url.replace(/\/+$/, "") : `${url}/`;
|
|
128
|
-
match = this.#router.resolveURI(url);
|
|
129
|
-
if (match == null) return null;
|
|
130
|
-
}
|
|
131
|
-
return {
|
|
132
|
-
name: match.matchValue,
|
|
133
|
-
template: this.#templateStrings[match.matchValue],
|
|
134
|
-
values: match.params
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Constructs a URL/path from a path name and values.
|
|
139
|
-
* @param name The name of the path.
|
|
140
|
-
* @param values The values to expand the path with.
|
|
141
|
-
* @returns The URL/path, if the name exists. Otherwise, `null`.
|
|
142
|
-
*/
|
|
143
|
-
build(name, values) {
|
|
144
|
-
if (name in this.#templates) return this.#templates[name].expand(values);
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
61
|
+
const identifierSingular = {
|
|
62
|
+
exact: true,
|
|
63
|
+
variables: { identifier: { operatables: [""] } }
|
|
147
64
|
};
|
|
148
65
|
/**
|
|
149
|
-
*
|
|
66
|
+
* Route options shared by every dispatcher whose path must expose
|
|
67
|
+
* `{identifier}` and `{+identifier}` variables bound to the same single,
|
|
68
|
+
* non-empty value for following setters:
|
|
69
|
+
* - `setActorDispatcher()` (actor path)
|
|
70
|
+
* - `setInboxDispatcher/Listener()` (inbox path)
|
|
71
|
+
* - `setFollowingDispatcher()` (following path)
|
|
72
|
+
* - `setFollowersDispatcher()` (followers path)
|
|
73
|
+
* - `setLikedDispatcher()` (liked path)
|
|
74
|
+
* - `setFeaturedDispatcher()` (featured path)
|
|
75
|
+
* - `setFeaturedTagsDispatcher()` (featured tags path)
|
|
150
76
|
*/
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
* @param message The error message.
|
|
155
|
-
*/
|
|
156
|
-
constructor(message) {
|
|
157
|
-
super(message);
|
|
158
|
-
this.name = "RouterError";
|
|
159
|
-
}
|
|
77
|
+
const identifierSingularAllowPlus = {
|
|
78
|
+
exact: true,
|
|
79
|
+
variables: { identifier: { operatables: ["", "+"] } }
|
|
160
80
|
};
|
|
161
|
-
//#endregion
|
|
162
|
-
//#region src/federation/builder.ts
|
|
163
|
-
const ACTOR_ALIAS_PREFIX = "actorAlias:";
|
|
164
|
-
function validateSingleIdentifierVariablePath(path, errorMessage) {
|
|
165
|
-
const operatorMatches = globalThis.Array.from(path.matchAll(/{([+#./;?&]?)([A-Za-z_][A-Za-z0-9_]*)}/g));
|
|
166
|
-
if (operatorMatches.length !== 1 || operatorMatches[0]?.[2] !== "identifier") throw new RouterError(errorMessage);
|
|
167
|
-
if (operatorMatches.some((match) => [
|
|
168
|
-
"?",
|
|
169
|
-
"&",
|
|
170
|
-
"#"
|
|
171
|
-
].includes(match[1]) && match[2] === "identifier")) throw new RouterError(errorMessage);
|
|
172
|
-
const variables = new Router$1().add(path, "outbox");
|
|
173
|
-
if (variables.size !== 1 || !variables.has("identifier")) throw new RouterError(errorMessage);
|
|
174
|
-
}
|
|
175
81
|
var FederationBuilderImpl = class {
|
|
176
82
|
router;
|
|
177
83
|
actorCallbacks;
|
|
@@ -204,7 +110,7 @@ var FederationBuilderImpl = class {
|
|
|
204
110
|
*/
|
|
205
111
|
#symbolRegistry = /* @__PURE__ */ new Map();
|
|
206
112
|
constructor() {
|
|
207
|
-
this.router = new Router
|
|
113
|
+
this.router = new Router();
|
|
208
114
|
this.objectCallbacks = {};
|
|
209
115
|
this.objectTypeIds = {};
|
|
210
116
|
this.collectionCallbacks = {};
|
|
@@ -247,8 +153,8 @@ var FederationBuilderImpl = class {
|
|
|
247
153
|
}
|
|
248
154
|
setActorDispatcher(path, dispatcher) {
|
|
249
155
|
if (this.router.has("actor")) throw new RouterError("Actor dispatcher already set.");
|
|
250
|
-
|
|
251
|
-
|
|
156
|
+
assertPath(path);
|
|
157
|
+
this.router.add(path, "actor", identifierSingularAllowPlus);
|
|
252
158
|
const callbacks = { dispatcher: async (context, identifier) => {
|
|
253
159
|
const actor = await this._getTracer().startActiveSpan("activitypub.dispatch_actor", {
|
|
254
160
|
kind: SpanKind.SERVER,
|
|
@@ -350,7 +256,7 @@ var FederationBuilderImpl = class {
|
|
|
350
256
|
mapActorAlias: (path, identifier) => {
|
|
351
257
|
if (identifier === "") throw new RouterError("Identifier cannot be empty.");
|
|
352
258
|
if (this.router.has(`actorAlias:${identifier}`)) throw new RouterError(`Actor alias for "${identifier}" already set.`);
|
|
353
|
-
if (
|
|
259
|
+
if (Router.variables(path).size > 0) throw new RouterError("Path for actor alias must have no variables.");
|
|
354
260
|
const existingRoute = this.router.route(path);
|
|
355
261
|
if (existingRoute != null) throw new RouterError(`Actor alias path "${path}" conflicts with existing route "${existingRoute.name}".`);
|
|
356
262
|
this.router.add(path, `${ACTOR_ALIAS_PREFIX}${identifier}`);
|
|
@@ -365,7 +271,8 @@ var FederationBuilderImpl = class {
|
|
|
365
271
|
}
|
|
366
272
|
setNodeInfoDispatcher(path, dispatcher) {
|
|
367
273
|
if (this.router.has("nodeInfo")) throw new RouterError("NodeInfo dispatcher already set.");
|
|
368
|
-
if (
|
|
274
|
+
if (Router.variables(path).size !== 0) throw new RouterError("Path for NodeInfo dispatcher must have no variables.");
|
|
275
|
+
this.router.add(path, "nodeInfo");
|
|
369
276
|
this.nodeInfoDispatcher = dispatcher;
|
|
370
277
|
}
|
|
371
278
|
setWebFingerLinksDispatcher(dispatcher) {
|
|
@@ -374,8 +281,9 @@ var FederationBuilderImpl = class {
|
|
|
374
281
|
setObjectDispatcher(cls, path, dispatcher) {
|
|
375
282
|
const routeName = `object:${cls.typeId.href}`;
|
|
376
283
|
if (this.router.has(routeName)) throw new RouterError(`Object dispatcher for ${cls.name} already set.`);
|
|
377
|
-
|
|
378
|
-
|
|
284
|
+
assertPath(path);
|
|
285
|
+
const variables = Router.variables(path);
|
|
286
|
+
this.router.add(path, routeName);
|
|
379
287
|
const callbacks = {
|
|
380
288
|
dispatcher: (ctx, values) => {
|
|
381
289
|
return this._getTracer().startActiveSpan("activitypub.dispatch_object", {
|
|
@@ -417,8 +325,8 @@ var FederationBuilderImpl = class {
|
|
|
417
325
|
if (this.router.has("inbox")) {
|
|
418
326
|
if (this.inboxPath !== path) throw new RouterError("Inbox dispatcher path must match inbox listener path.");
|
|
419
327
|
} else {
|
|
420
|
-
|
|
421
|
-
|
|
328
|
+
assertPath(path);
|
|
329
|
+
this.router.add(path, "inbox", identifierSingularAllowPlus);
|
|
422
330
|
this.inboxPath = path;
|
|
423
331
|
}
|
|
424
332
|
const callbacks = { dispatcher };
|
|
@@ -448,8 +356,8 @@ var FederationBuilderImpl = class {
|
|
|
448
356
|
if (this.router.has("outbox")) {
|
|
449
357
|
if (this.outboxPath !== path) throw new RouterError("Outbox dispatcher path must match outbox listener path.");
|
|
450
358
|
} else {
|
|
451
|
-
|
|
452
|
-
this.router.add(path, "outbox");
|
|
359
|
+
assertPath(path);
|
|
360
|
+
this.router.add(path, "outbox", identifierSingular);
|
|
453
361
|
this.outboxPath = path;
|
|
454
362
|
}
|
|
455
363
|
const callbacks = { dispatcher };
|
|
@@ -479,8 +387,8 @@ var FederationBuilderImpl = class {
|
|
|
479
387
|
if (this.router.has("outbox")) {
|
|
480
388
|
if (this.outboxPath !== outboxPath) throw new RouterError("Outbox listener path must match outbox dispatcher path.");
|
|
481
389
|
} else {
|
|
482
|
-
|
|
483
|
-
this.router.add(outboxPath, "outbox");
|
|
390
|
+
assertPath(outboxPath);
|
|
391
|
+
this.router.add(outboxPath, "outbox", identifierSingular);
|
|
484
392
|
this.outboxPath = outboxPath;
|
|
485
393
|
}
|
|
486
394
|
const listeners = this.outboxListeners = new ActivityListenerSet();
|
|
@@ -502,8 +410,8 @@ var FederationBuilderImpl = class {
|
|
|
502
410
|
}
|
|
503
411
|
setFollowingDispatcher(path, dispatcher) {
|
|
504
412
|
if (this.router.has("following")) throw new RouterError("Following collection dispatcher already set.");
|
|
505
|
-
|
|
506
|
-
|
|
413
|
+
assertPath(path);
|
|
414
|
+
this.router.add(path, "following", identifierSingularAllowPlus);
|
|
507
415
|
const callbacks = { dispatcher };
|
|
508
416
|
this.followingCallbacks = callbacks;
|
|
509
417
|
const setters = {
|
|
@@ -528,8 +436,8 @@ var FederationBuilderImpl = class {
|
|
|
528
436
|
}
|
|
529
437
|
setFollowersDispatcher(path, dispatcher) {
|
|
530
438
|
if (this.router.has("followers")) throw new RouterError("Followers collection dispatcher already set.");
|
|
531
|
-
|
|
532
|
-
|
|
439
|
+
assertPath(path);
|
|
440
|
+
this.router.add(path, "followers", identifierSingularAllowPlus);
|
|
533
441
|
const callbacks = { dispatcher };
|
|
534
442
|
this.followersCallbacks = callbacks;
|
|
535
443
|
const setters = {
|
|
@@ -554,8 +462,8 @@ var FederationBuilderImpl = class {
|
|
|
554
462
|
}
|
|
555
463
|
setLikedDispatcher(path, dispatcher) {
|
|
556
464
|
if (this.router.has("liked")) throw new RouterError("Liked collection dispatcher already set.");
|
|
557
|
-
|
|
558
|
-
|
|
465
|
+
assertPath(path);
|
|
466
|
+
this.router.add(path, "liked", identifierSingularAllowPlus);
|
|
559
467
|
const callbacks = { dispatcher };
|
|
560
468
|
this.likedCallbacks = callbacks;
|
|
561
469
|
const setters = {
|
|
@@ -580,8 +488,8 @@ var FederationBuilderImpl = class {
|
|
|
580
488
|
}
|
|
581
489
|
setFeaturedDispatcher(path, dispatcher) {
|
|
582
490
|
if (this.router.has("featured")) throw new RouterError("Featured collection dispatcher already set.");
|
|
583
|
-
|
|
584
|
-
|
|
491
|
+
assertPath(path);
|
|
492
|
+
this.router.add(path, "featured", identifierSingularAllowPlus);
|
|
585
493
|
const callbacks = { dispatcher };
|
|
586
494
|
this.featuredCallbacks = callbacks;
|
|
587
495
|
const setters = {
|
|
@@ -606,8 +514,8 @@ var FederationBuilderImpl = class {
|
|
|
606
514
|
}
|
|
607
515
|
setFeaturedTagsDispatcher(path, dispatcher) {
|
|
608
516
|
if (this.router.has("featuredTags")) throw new RouterError("Featured tags collection dispatcher already set.");
|
|
609
|
-
|
|
610
|
-
|
|
517
|
+
assertPath(path);
|
|
518
|
+
this.router.add(path, "featuredTags", identifierSingularAllowPlus);
|
|
611
519
|
const callbacks = { dispatcher };
|
|
612
520
|
this.featuredTagsCallbacks = callbacks;
|
|
613
521
|
const setters = {
|
|
@@ -635,12 +543,13 @@ var FederationBuilderImpl = class {
|
|
|
635
543
|
if (this.router.has("inbox")) {
|
|
636
544
|
if (this.inboxPath !== inboxPath) throw new RouterError("Inbox listener path must match inbox dispatcher path.");
|
|
637
545
|
} else {
|
|
638
|
-
|
|
639
|
-
|
|
546
|
+
assertPath(inboxPath);
|
|
547
|
+
this.router.add(inboxPath, "inbox", identifierSingularAllowPlus);
|
|
640
548
|
this.inboxPath = inboxPath;
|
|
641
549
|
}
|
|
642
550
|
if (sharedInboxPath != null) {
|
|
643
|
-
if (
|
|
551
|
+
if (Router.variables(sharedInboxPath).size !== 0) throw new RouterError("Path for shared inbox must have no variables.");
|
|
552
|
+
this.router.add(sharedInboxPath, "sharedInbox");
|
|
644
553
|
}
|
|
645
554
|
const listeners = this.inboxListeners = new ActivityListenerSet();
|
|
646
555
|
const setters = {
|
|
@@ -678,7 +587,9 @@ var FederationBuilderImpl = class {
|
|
|
678
587
|
const routeName = `${collectionType}:${this.#uniqueCollectionId(name)}`;
|
|
679
588
|
if (this.router.has(routeName)) throw new RouterError(`Collection dispatcher for ${strName} already set.`);
|
|
680
589
|
if (this.collectionCallbacks[name] != null) throw new RouterError(`Collection dispatcher for ${strName} already set.`);
|
|
681
|
-
|
|
590
|
+
assertPath(path);
|
|
591
|
+
if (Router.variables(path).size < 1) throw new RouterError("Path for collection dispatcher must have at least one variable.");
|
|
592
|
+
this.router.add(path, routeName);
|
|
682
593
|
const callbacks = { dispatcher };
|
|
683
594
|
this.collectionCallbacks[name] = callbacks;
|
|
684
595
|
this.collectionTypeIds[name] = itemType;
|
|
@@ -2690,22 +2601,72 @@ const logger = getLogger([
|
|
|
2690
2601
|
* @returns The response to the request.
|
|
2691
2602
|
*/
|
|
2692
2603
|
async function handleWebFinger(request, options) {
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
});
|
|
2704
|
-
throw error;
|
|
2705
|
-
} finally {
|
|
2706
|
-
span.end();
|
|
2604
|
+
const meterProvider = options.meterProvider;
|
|
2605
|
+
const start = meterProvider == null ? 0 : performance.now();
|
|
2606
|
+
const scheme = computeResourceScheme(options.context.url.searchParams.get("resource"));
|
|
2607
|
+
let notFoundResponse;
|
|
2608
|
+
const wrappedOptions = {
|
|
2609
|
+
...options,
|
|
2610
|
+
async onNotFound(req) {
|
|
2611
|
+
const r = await options.onNotFound(req);
|
|
2612
|
+
notFoundResponse = r;
|
|
2613
|
+
return r;
|
|
2707
2614
|
}
|
|
2708
|
-
}
|
|
2615
|
+
};
|
|
2616
|
+
let response;
|
|
2617
|
+
try {
|
|
2618
|
+
if (options.tracer == null) response = await handleWebFingerInternal(request, wrappedOptions);
|
|
2619
|
+
else response = await options.tracer.startActiveSpan("webfinger.handle", { kind: SpanKind.SERVER }, async (span) => {
|
|
2620
|
+
try {
|
|
2621
|
+
const inner = await handleWebFingerInternal(request, wrappedOptions);
|
|
2622
|
+
span.setStatus({ code: inner.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR });
|
|
2623
|
+
return inner;
|
|
2624
|
+
} catch (error) {
|
|
2625
|
+
span.setStatus({
|
|
2626
|
+
code: SpanStatusCode.ERROR,
|
|
2627
|
+
message: String(error)
|
|
2628
|
+
});
|
|
2629
|
+
throw error;
|
|
2630
|
+
} finally {
|
|
2631
|
+
span.end();
|
|
2632
|
+
}
|
|
2633
|
+
});
|
|
2634
|
+
return response;
|
|
2635
|
+
} finally {
|
|
2636
|
+
if (meterProvider != null) recordWebFingerHandle(meterProvider, {
|
|
2637
|
+
durationMs: Math.max(0, performance.now() - start),
|
|
2638
|
+
result: classifyWebFingerHandleResult(response, notFoundResponse),
|
|
2639
|
+
scheme,
|
|
2640
|
+
statusCode: response?.status
|
|
2641
|
+
});
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
const WEBFINGER_HANDLE_SCHEME_WHITELIST = new Set([
|
|
2645
|
+
"acct",
|
|
2646
|
+
"http",
|
|
2647
|
+
"https",
|
|
2648
|
+
"mailto"
|
|
2649
|
+
]);
|
|
2650
|
+
function isAllowedResourceScheme(scheme) {
|
|
2651
|
+
return WEBFINGER_HANDLE_SCHEME_WHITELIST.has(scheme);
|
|
2652
|
+
}
|
|
2653
|
+
function computeResourceScheme(resource) {
|
|
2654
|
+
if (resource == null) return void 0;
|
|
2655
|
+
const colon = resource.indexOf(":");
|
|
2656
|
+
if (colon <= 0) return void 0;
|
|
2657
|
+
const candidate = resource.substring(0, colon).toLowerCase();
|
|
2658
|
+
return isAllowedResourceScheme(candidate) ? candidate : "other";
|
|
2659
|
+
}
|
|
2660
|
+
function classifyWebFingerHandleResult(response, notFoundResponse) {
|
|
2661
|
+
if (response == null) return "error";
|
|
2662
|
+
if (notFoundResponse != null && response === notFoundResponse) return "not_found";
|
|
2663
|
+
switch (response.status) {
|
|
2664
|
+
case 200: return "resolved";
|
|
2665
|
+
case 400: return "invalid";
|
|
2666
|
+
case 404: return "not_found";
|
|
2667
|
+
case 410: return "tombstoned";
|
|
2668
|
+
default: return "error";
|
|
2669
|
+
}
|
|
2709
2670
|
}
|
|
2710
2671
|
async function handleWebFingerInternal(request, { context, host, actorDispatcher, actorHandleMapper, actorAliasMapper, onNotFound, span, webFingerLinksDispatcher }) {
|
|
2711
2672
|
if (actorDispatcher == null) {
|
|
@@ -3739,7 +3700,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3739
3700
|
actorAliasMapper: this.actorCallbacks?.aliasMapper,
|
|
3740
3701
|
webFingerLinksDispatcher: this.webFingerLinksDispatcher,
|
|
3741
3702
|
onNotFound,
|
|
3742
|
-
tracer
|
|
3703
|
+
tracer,
|
|
3704
|
+
meterProvider: this._meterProvider
|
|
3743
3705
|
});
|
|
3744
3706
|
case "nodeInfoJrd": return await handleNodeInfoJrd(request, context);
|
|
3745
3707
|
case "nodeInfo": return await handleNodeInfo(request, {
|
|
@@ -4298,6 +4260,7 @@ var ContextImpl = class ContextImpl {
|
|
|
4298
4260
|
...options,
|
|
4299
4261
|
userAgent: options.userAgent ?? this.federation.userAgent,
|
|
4300
4262
|
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
4263
|
+
meterProvider: options.meterProvider ?? this.federation._meterProvider,
|
|
4301
4264
|
allowPrivateAddress: this.federation.allowPrivateAddress
|
|
4302
4265
|
});
|
|
4303
4266
|
}
|
|
@@ -5002,4 +4965,4 @@ function getRequestId(request) {
|
|
|
5002
4965
|
return `req_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
5003
4966
|
}
|
|
5004
4967
|
//#endregion
|
|
5005
|
-
export { createExponentialBackoffPolicy as a, buildCollectionSynchronizationHeader as c,
|
|
4968
|
+
export { createExponentialBackoffPolicy as a, buildCollectionSynchronizationHeader as c, SendActivityError as i, digest as l, middleware_exports as n, respondWithObject as o, handleWebFinger as r, respondWithObjectIfAcceptable as s, createFederation as t, createFederationBuilder as u };
|
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as
|
|
5
|
-
import { n as
|
|
6
|
-
import {
|
|
7
|
-
import { t as
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { r as
|
|
15
|
-
import {
|
|
16
|
-
import { t as
|
|
17
|
-
import { t as
|
|
18
|
-
import {
|
|
19
|
-
import { t as
|
|
20
|
-
import { t as
|
|
21
|
-
import { t as
|
|
22
|
-
import { t as
|
|
23
|
-
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-DJFpze7B.mjs";
|
|
4
|
+
import { n as version, t as name } from "./deno-h0TWFuEz.mjs";
|
|
5
|
+
import { a as instrumentDocumentLoader, d as recordInboxActivity, h as recordWebFingerHandle, i as getRemoteHost, m as recordOutboxEnqueue, n as getDurationMs, o as isAbortError, p as recordOutboxActivity, r as getFederationMetrics, u as recordFanoutRecipients } from "./metrics-E0hAHtLZ.mjs";
|
|
6
|
+
import { t as formatAcceptSignature } from "./accept-CceiKpCy.mjs";
|
|
7
|
+
import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-Dh2OK1XQ.mjs";
|
|
8
|
+
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-QzW9IWfs.mjs";
|
|
9
|
+
import { t as getAuthenticatedDocumentLoader } from "./docloader-BdDN0Aqx.mjs";
|
|
10
|
+
import { n as kvCache } from "./kv-cache-EZRIPZXD.mjs";
|
|
11
|
+
import { a as signJsonLd, i as hasSignatureLike, o as verifyJsonLd, r as detachSignature } from "./ld-eZbar1rr.mjs";
|
|
12
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-ByO_Fw6U.mjs";
|
|
13
|
+
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-BgFLCJQ_.mjs";
|
|
14
|
+
import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-CSo0S8OK.mjs";
|
|
15
|
+
import { t as getNodeInfo } from "./client-B_A6mfn3.mjs";
|
|
16
|
+
import { t as nodeInfoToJson } from "./types-BFowWFTT.mjs";
|
|
17
|
+
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-ShiR1K6b.mjs";
|
|
18
|
+
import { t as buildCollectionSynchronizationHeader } from "./collection-CA3V5zyK.mjs";
|
|
19
|
+
import { t as KvKeyCache } from "./keycache-BYMd8q7F.mjs";
|
|
20
|
+
import { t as acceptsJsonLd } from "./negotiation-CDW-_gUU.mjs";
|
|
21
|
+
import { t as createExponentialBackoffPolicy } from "./retry-v_sGLH1d.mjs";
|
|
22
|
+
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-jzrTV1FU.mjs";
|
|
24
23
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
24
|
+
import { RouterError } from "@fedify/uri-template";
|
|
25
25
|
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
26
26
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
27
27
|
import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
|
|
28
|
-
import { uniq } from "es-toolkit";
|
|
29
28
|
import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
|
|
30
29
|
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";
|
|
30
|
+
import { uniq } from "es-toolkit";
|
|
31
31
|
import { domainToASCII } from "node:url";
|
|
32
32
|
//#region src/compat/transformers.ts
|
|
33
33
|
const logger$1 = getLogger([
|
|
@@ -1600,22 +1600,72 @@ const logger = getLogger([
|
|
|
1600
1600
|
* @returns The response to the request.
|
|
1601
1601
|
*/
|
|
1602
1602
|
async function handleWebFinger(request, options) {
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
});
|
|
1614
|
-
throw error;
|
|
1615
|
-
} finally {
|
|
1616
|
-
span.end();
|
|
1603
|
+
const meterProvider = options.meterProvider;
|
|
1604
|
+
const start = meterProvider == null ? 0 : performance.now();
|
|
1605
|
+
const scheme = computeResourceScheme(options.context.url.searchParams.get("resource"));
|
|
1606
|
+
let notFoundResponse;
|
|
1607
|
+
const wrappedOptions = {
|
|
1608
|
+
...options,
|
|
1609
|
+
async onNotFound(req) {
|
|
1610
|
+
const r = await options.onNotFound(req);
|
|
1611
|
+
notFoundResponse = r;
|
|
1612
|
+
return r;
|
|
1617
1613
|
}
|
|
1618
|
-
}
|
|
1614
|
+
};
|
|
1615
|
+
let response;
|
|
1616
|
+
try {
|
|
1617
|
+
if (options.tracer == null) response = await handleWebFingerInternal(request, wrappedOptions);
|
|
1618
|
+
else response = await options.tracer.startActiveSpan("webfinger.handle", { kind: SpanKind.SERVER }, async (span) => {
|
|
1619
|
+
try {
|
|
1620
|
+
const inner = await handleWebFingerInternal(request, wrappedOptions);
|
|
1621
|
+
span.setStatus({ code: inner.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR });
|
|
1622
|
+
return inner;
|
|
1623
|
+
} catch (error) {
|
|
1624
|
+
span.setStatus({
|
|
1625
|
+
code: SpanStatusCode.ERROR,
|
|
1626
|
+
message: String(error)
|
|
1627
|
+
});
|
|
1628
|
+
throw error;
|
|
1629
|
+
} finally {
|
|
1630
|
+
span.end();
|
|
1631
|
+
}
|
|
1632
|
+
});
|
|
1633
|
+
return response;
|
|
1634
|
+
} finally {
|
|
1635
|
+
if (meterProvider != null) recordWebFingerHandle(meterProvider, {
|
|
1636
|
+
durationMs: Math.max(0, performance.now() - start),
|
|
1637
|
+
result: classifyWebFingerHandleResult(response, notFoundResponse),
|
|
1638
|
+
scheme,
|
|
1639
|
+
statusCode: response?.status
|
|
1640
|
+
});
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
const WEBFINGER_HANDLE_SCHEME_WHITELIST = new Set([
|
|
1644
|
+
"acct",
|
|
1645
|
+
"http",
|
|
1646
|
+
"https",
|
|
1647
|
+
"mailto"
|
|
1648
|
+
]);
|
|
1649
|
+
function isAllowedResourceScheme(scheme) {
|
|
1650
|
+
return WEBFINGER_HANDLE_SCHEME_WHITELIST.has(scheme);
|
|
1651
|
+
}
|
|
1652
|
+
function computeResourceScheme(resource) {
|
|
1653
|
+
if (resource == null) return void 0;
|
|
1654
|
+
const colon = resource.indexOf(":");
|
|
1655
|
+
if (colon <= 0) return void 0;
|
|
1656
|
+
const candidate = resource.substring(0, colon).toLowerCase();
|
|
1657
|
+
return isAllowedResourceScheme(candidate) ? candidate : "other";
|
|
1658
|
+
}
|
|
1659
|
+
function classifyWebFingerHandleResult(response, notFoundResponse) {
|
|
1660
|
+
if (response == null) return "error";
|
|
1661
|
+
if (notFoundResponse != null && response === notFoundResponse) return "not_found";
|
|
1662
|
+
switch (response.status) {
|
|
1663
|
+
case 200: return "resolved";
|
|
1664
|
+
case 400: return "invalid";
|
|
1665
|
+
case 404: return "not_found";
|
|
1666
|
+
case 410: return "tombstoned";
|
|
1667
|
+
default: return "error";
|
|
1668
|
+
}
|
|
1619
1669
|
}
|
|
1620
1670
|
async function handleWebFingerInternal(request, { context, host, actorDispatcher, actorHandleMapper, actorAliasMapper, onNotFound, span, webFingerLinksDispatcher }) {
|
|
1621
1671
|
if (actorDispatcher == null) {
|
|
@@ -2641,7 +2691,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
2641
2691
|
actorAliasMapper: this.actorCallbacks?.aliasMapper,
|
|
2642
2692
|
webFingerLinksDispatcher: this.webFingerLinksDispatcher,
|
|
2643
2693
|
onNotFound,
|
|
2644
|
-
tracer
|
|
2694
|
+
tracer,
|
|
2695
|
+
meterProvider: this._meterProvider
|
|
2645
2696
|
});
|
|
2646
2697
|
case "nodeInfoJrd": return await handleNodeInfoJrd(request, context);
|
|
2647
2698
|
case "nodeInfo": return await handleNodeInfo(request, {
|
|
@@ -3200,6 +3251,7 @@ var ContextImpl = class ContextImpl {
|
|
|
3200
3251
|
...options,
|
|
3201
3252
|
userAgent: options.userAgent ?? this.federation.userAgent,
|
|
3202
3253
|
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
3254
|
+
meterProvider: options.meterProvider ?? this.federation._meterProvider,
|
|
3203
3255
|
allowPrivateAddress: this.federation.allowPrivateAddress
|
|
3204
3256
|
});
|
|
3205
3257
|
}
|