@fedify/fedify 1.3.0-dev.568 → 1.3.0-dev.570
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/esm/deno.js +1 -1
- package/esm/federation/handler.js +41 -5
- package/esm/federation/middleware.js +91 -4
- package/esm/vocab/vocab.js +173 -173
- package/package.json +1 -1
- package/types/federation/handler.d.ts +2 -1
- package/types/federation/handler.d.ts.map +1 -1
- package/types/federation/middleware.d.ts.map +1 -1
package/esm/deno.js
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
import * as dntShim from "../_dnt.shims.js";
|
2
2
|
import { getLogger } from "@logtape/logtape";
|
3
|
+
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
3
4
|
import { accepts } from "../deps/jsr.io/@std/http/1.0.11/negotiation.js";
|
5
|
+
import metadata from "../deno.js";
|
4
6
|
import { verifyRequest } from "../sig/http.js";
|
5
7
|
import { detachSignature, verifyJsonLd } from "../sig/ld.js";
|
6
8
|
import { doesActorOwnKey } from "../sig/owner.js";
|
7
9
|
import { verifyObject } from "../sig/proof.js";
|
10
|
+
import { getTypeId } from "../vocab/type.js";
|
8
11
|
import { Activity, CryptographicKey, Link, Multikey, Object, OrderedCollection, OrderedCollectionPage, } from "../vocab/vocab.js";
|
9
12
|
export function acceptsJsonLd(request) {
|
10
13
|
const types = accepts(request);
|
@@ -68,21 +71,46 @@ export async function handleObject(request, { values, context, objectDispatcher,
|
|
68
71
|
},
|
69
72
|
});
|
70
73
|
}
|
71
|
-
export
|
72
|
-
|
73
|
-
|
74
|
+
export function handleCollection(request, params) {
|
75
|
+
const name = params.name.trim().replace(/\s+/g, "_");
|
76
|
+
const tracerProvider = params.tracerProvider ?? trace.getTracerProvider();
|
77
|
+
const tracer = tracerProvider.getTracer(metadata.name, metadata.version);
|
74
78
|
const url = new URL(request.url);
|
75
79
|
const cursor = url.searchParams.get("cursor");
|
80
|
+
return tracer.startActiveSpan(cursor == null
|
81
|
+
? `activitypub.dispatch_collection ${name}`
|
82
|
+
: `activitypub.dispatch_collection_page ${name}`, { kind: SpanKind.SERVER }, async (span) => {
|
83
|
+
try {
|
84
|
+
return await handleCollectionInternal(request, cursor, params, span);
|
85
|
+
}
|
86
|
+
catch (e) {
|
87
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(e) });
|
88
|
+
throw e;
|
89
|
+
}
|
90
|
+
finally {
|
91
|
+
span.end();
|
92
|
+
}
|
93
|
+
});
|
94
|
+
}
|
95
|
+
async function handleCollectionInternal(request, cursor, { name, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, onUnauthorized, onNotFound, onNotAcceptable, }, span) {
|
96
|
+
if (collectionCallbacks == null)
|
97
|
+
return await onNotFound(request);
|
76
98
|
let collection;
|
77
99
|
const baseUri = uriGetter(identifier);
|
78
100
|
if (cursor == null) {
|
79
101
|
const firstCursor = await collectionCallbacks.firstCursor?.(context, identifier);
|
80
102
|
const totalItems = await collectionCallbacks.counter?.(context, identifier);
|
103
|
+
if (totalItems != null) {
|
104
|
+
span.setAttribute("activitypub.collection.total_items", Number(totalItems));
|
105
|
+
}
|
81
106
|
if (firstCursor == null) {
|
82
107
|
const page = await collectionCallbacks.dispatcher(context, identifier, null, filter);
|
83
|
-
if (page == null)
|
108
|
+
if (page == null) {
|
109
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
84
110
|
return await onNotFound(request);
|
111
|
+
}
|
85
112
|
const { items } = page;
|
113
|
+
span.setAttribute("fedify.collection.items", items.length);
|
86
114
|
collection = new OrderedCollection({
|
87
115
|
id: baseUri,
|
88
116
|
totalItems: totalItems == null ? null : Number(totalItems),
|
@@ -107,12 +135,16 @@ export async function handleCollection(request, { name, identifier, uriGetter, f
|
|
107
135
|
}
|
108
136
|
}
|
109
137
|
else {
|
138
|
+
span.setAttribute("fedify.collection.cursor", cursor);
|
110
139
|
const uri = new URL(baseUri);
|
111
140
|
uri.searchParams.set("cursor", cursor);
|
112
141
|
const page = await collectionCallbacks.dispatcher(context, identifier, cursor, filter);
|
113
|
-
if (page == null)
|
142
|
+
if (page == null) {
|
143
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
114
144
|
return await onNotFound(request);
|
145
|
+
}
|
115
146
|
const { items, prevCursor, nextCursor } = page;
|
147
|
+
span.setAttribute("fedify.collection.items", items.length);
|
116
148
|
let prev = null;
|
117
149
|
if (prevCursor != null) {
|
118
150
|
prev = new URL(context.url);
|
@@ -142,6 +174,10 @@ export async function handleCollection(request, { name, identifier, uriGetter, f
|
|
142
174
|
return await onUnauthorized(request);
|
143
175
|
}
|
144
176
|
}
|
177
|
+
if (collection.id != null) {
|
178
|
+
span.setAttribute("activitypub.collection.id", collection.id.href);
|
179
|
+
}
|
180
|
+
span.setAttribute("activitypub.collection.type", getTypeId(collection).href);
|
145
181
|
const jsonLd = await collection.toJsonLd(context);
|
146
182
|
return new Response(JSON.stringify(jsonLd), {
|
147
183
|
headers: {
|
@@ -11,6 +11,7 @@ import { hasSignature, signJsonLd } from "../sig/ld.js";
|
|
11
11
|
import { getKeyOwner } from "../sig/owner.js";
|
12
12
|
import { signObject } from "../sig/proof.js";
|
13
13
|
import { lookupObject, traverseCollection, } from "../vocab/lookup.js";
|
14
|
+
import { getTypeId } from "../vocab/type.js";
|
14
15
|
import { Activity, CryptographicKey, Multikey, } from "../vocab/vocab.js";
|
15
16
|
import { handleWebFinger } from "../webfinger/handler.js";
|
16
17
|
import { buildCollectionSynchronizationHeader } from "./collection.js";
|
@@ -402,7 +403,32 @@ export class FederationImpl {
|
|
402
403
|
}
|
403
404
|
const callbacks = {
|
404
405
|
dispatcher: async (context, identifier) => {
|
405
|
-
const actor = await
|
406
|
+
const actor = await this.#getTracer().startActiveSpan("activitypub.dispatch_actor", {
|
407
|
+
kind: SpanKind.SERVER,
|
408
|
+
attributes: { "fedify.actor.identifier": identifier },
|
409
|
+
}, async (span) => {
|
410
|
+
try {
|
411
|
+
const actor = await dispatcher(context, identifier);
|
412
|
+
span.setAttribute("activitypub.actor.id", (actor?.id ?? context.getActorUri(identifier)).href);
|
413
|
+
if (actor == null) {
|
414
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
415
|
+
}
|
416
|
+
else {
|
417
|
+
span.setAttribute("activitypub.actor.type", getTypeId(actor).href);
|
418
|
+
}
|
419
|
+
return actor;
|
420
|
+
}
|
421
|
+
catch (error) {
|
422
|
+
span.setStatus({
|
423
|
+
code: SpanStatusCode.ERROR,
|
424
|
+
message: String(error),
|
425
|
+
});
|
426
|
+
throw error;
|
427
|
+
}
|
428
|
+
finally {
|
429
|
+
span.end();
|
430
|
+
}
|
431
|
+
});
|
406
432
|
if (actor == null)
|
407
433
|
return null;
|
408
434
|
const logger = getLogger(["fedify", "federation", "actor"]);
|
@@ -536,8 +562,28 @@ export class FederationImpl {
|
|
536
562
|
};
|
537
563
|
this.actorCallbacks = callbacks;
|
538
564
|
const setters = {
|
539
|
-
setKeyPairsDispatcher(dispatcher) {
|
540
|
-
callbacks.keyPairsDispatcher =
|
565
|
+
setKeyPairsDispatcher: (dispatcher) => {
|
566
|
+
callbacks.keyPairsDispatcher = (ctx, identifier) => this.#getTracer().startActiveSpan("activitypub.dispatch_actor_key_pairs", {
|
567
|
+
kind: SpanKind.SERVER,
|
568
|
+
attributes: {
|
569
|
+
"activitypub.actor.id": ctx.getActorUri(identifier).href,
|
570
|
+
"fedify.actor.identifier": identifier,
|
571
|
+
},
|
572
|
+
}, async (span) => {
|
573
|
+
try {
|
574
|
+
return await dispatcher(ctx, identifier);
|
575
|
+
}
|
576
|
+
catch (e) {
|
577
|
+
span.setStatus({
|
578
|
+
code: SpanStatusCode.ERROR,
|
579
|
+
message: String(e),
|
580
|
+
});
|
581
|
+
throw e;
|
582
|
+
}
|
583
|
+
finally {
|
584
|
+
span.end();
|
585
|
+
}
|
586
|
+
});
|
541
587
|
return setters;
|
542
588
|
},
|
543
589
|
mapHandle(mapper) {
|
@@ -563,7 +609,41 @@ export class FederationImpl {
|
|
563
609
|
throw new RouterError("Path for object dispatcher must have at least one variable.");
|
564
610
|
}
|
565
611
|
const callbacks = {
|
566
|
-
dispatcher,
|
612
|
+
dispatcher: (ctx, values) => {
|
613
|
+
const tracer = this.#getTracer();
|
614
|
+
return tracer.startActiveSpan("activitypub.dispatch_object", {
|
615
|
+
kind: SpanKind.SERVER,
|
616
|
+
attributes: {
|
617
|
+
"fedify.object.type": cls.typeId.href,
|
618
|
+
...globalThis.Object.fromEntries(globalThis.Object.entries(values).map(([k, v]) => [
|
619
|
+
`fedify.object.values.${k}`,
|
620
|
+
v,
|
621
|
+
])),
|
622
|
+
},
|
623
|
+
}, async (span) => {
|
624
|
+
try {
|
625
|
+
const object = await dispatcher(ctx, values);
|
626
|
+
span.setAttribute("activitypub.object.id", (object?.id ?? ctx.getObjectUri(cls, values)).href);
|
627
|
+
if (object == null) {
|
628
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
629
|
+
}
|
630
|
+
else {
|
631
|
+
span.setAttribute("activitypub.object.type", getTypeId(object).href);
|
632
|
+
}
|
633
|
+
return object;
|
634
|
+
}
|
635
|
+
catch (e) {
|
636
|
+
span.setStatus({
|
637
|
+
code: SpanStatusCode.ERROR,
|
638
|
+
message: String(e),
|
639
|
+
});
|
640
|
+
throw e;
|
641
|
+
}
|
642
|
+
finally {
|
643
|
+
span.end();
|
644
|
+
}
|
645
|
+
});
|
646
|
+
},
|
567
647
|
parameters: variables,
|
568
648
|
};
|
569
649
|
this.objectCallbacks[cls.typeId.href] = callbacks;
|
@@ -1143,6 +1223,7 @@ export class FederationImpl {
|
|
1143
1223
|
uriGetter: context.getOutboxUri.bind(context),
|
1144
1224
|
context,
|
1145
1225
|
collectionCallbacks: this.outboxCallbacks,
|
1226
|
+
tracerProvider: this.tracerProvider,
|
1146
1227
|
onUnauthorized,
|
1147
1228
|
onNotFound,
|
1148
1229
|
onNotAcceptable,
|
@@ -1155,6 +1236,7 @@ export class FederationImpl {
|
|
1155
1236
|
uriGetter: context.getInboxUri.bind(context),
|
1156
1237
|
context,
|
1157
1238
|
collectionCallbacks: this.inboxCallbacks,
|
1239
|
+
tracerProvider: this.tracerProvider,
|
1158
1240
|
onUnauthorized,
|
1159
1241
|
onNotFound,
|
1160
1242
|
onNotAcceptable,
|
@@ -1202,6 +1284,7 @@ export class FederationImpl {
|
|
1202
1284
|
uriGetter: context.getFollowingUri.bind(context),
|
1203
1285
|
context,
|
1204
1286
|
collectionCallbacks: this.followingCallbacks,
|
1287
|
+
tracerProvider: this.tracerProvider,
|
1205
1288
|
onUnauthorized,
|
1206
1289
|
onNotFound,
|
1207
1290
|
onNotAcceptable,
|
@@ -1222,6 +1305,7 @@ export class FederationImpl {
|
|
1222
1305
|
? ((i) => (i instanceof URL ? i.href : i.id?.href ?? "").startsWith(baseUrl))
|
1223
1306
|
: undefined,
|
1224
1307
|
collectionCallbacks: this.followersCallbacks,
|
1308
|
+
tracerProvider: this.tracerProvider,
|
1225
1309
|
onUnauthorized,
|
1226
1310
|
onNotFound,
|
1227
1311
|
onNotAcceptable,
|
@@ -1234,6 +1318,7 @@ export class FederationImpl {
|
|
1234
1318
|
uriGetter: context.getLikedUri.bind(context),
|
1235
1319
|
context,
|
1236
1320
|
collectionCallbacks: this.likedCallbacks,
|
1321
|
+
tracerProvider: this.tracerProvider,
|
1237
1322
|
onUnauthorized,
|
1238
1323
|
onNotFound,
|
1239
1324
|
onNotAcceptable,
|
@@ -1245,6 +1330,7 @@ export class FederationImpl {
|
|
1245
1330
|
uriGetter: context.getFeaturedUri.bind(context),
|
1246
1331
|
context,
|
1247
1332
|
collectionCallbacks: this.featuredCallbacks,
|
1333
|
+
tracerProvider: this.tracerProvider,
|
1248
1334
|
onUnauthorized,
|
1249
1335
|
onNotFound,
|
1250
1336
|
onNotAcceptable,
|
@@ -1256,6 +1342,7 @@ export class FederationImpl {
|
|
1256
1342
|
uriGetter: context.getFeaturedTagsUri.bind(context),
|
1257
1343
|
context,
|
1258
1344
|
collectionCallbacks: this.featuredTagsCallbacks,
|
1345
|
+
tracerProvider: this.tracerProvider,
|
1259
1346
|
onUnauthorized,
|
1260
1347
|
onNotFound,
|
1261
1348
|
onNotAcceptable,
|