@fedify/fedify 2.3.0-dev.1048 → 2.3.0-dev.1050

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.
Files changed (43) hide show
  1. package/dist/{builder-BhiIuyGK.mjs → builder-5M0ZV0s3.mjs} +2 -2
  2. package/dist/compat/transformers.test.mjs +1 -1
  3. package/dist/{deno-D9LpbVQR.mjs → deno-BvRV20GH.mjs} +1 -1
  4. package/dist/{docloader-y2viZ2Tx.mjs → docloader-YOsFpxMZ.mjs} +2 -2
  5. package/dist/federation/builder.test.mjs +1 -1
  6. package/dist/federation/handler.test.mjs +2 -2
  7. package/dist/federation/idempotency.test.mjs +2 -2
  8. package/dist/federation/middleware.test.mjs +199 -6
  9. package/dist/federation/mod.cjs +1 -1
  10. package/dist/federation/mod.js +1 -1
  11. package/dist/federation/send.test.mjs +3 -3
  12. package/dist/federation/webfinger.test.mjs +1 -1
  13. package/dist/{http-D6yvDhyL.mjs → http-BETUCsB0.mjs} +2 -2
  14. package/dist/{http-CA4xKsSY.js → http-Cj-JmUpS.js} +1 -1
  15. package/dist/{http-Bj0uN6d-.cjs → http-DT4PVP4u.cjs} +1 -1
  16. package/dist/{key-BPjHWwyv.mjs → key-CjtOXvjb.mjs} +1 -1
  17. package/dist/{kv-cache-DarvCOHt.js → kv-cache-BOU_yvQi.js} +1 -1
  18. package/dist/{kv-cache-BdSTsjLb.cjs → kv-cache-DqiCNMDz.cjs} +1 -1
  19. package/dist/{ld-D9yQwfkO.mjs → ld-WRlX-hAe.mjs} +2 -2
  20. package/dist/{middleware-0n0ctSu_.js → middleware-B0YQlYeu.js} +96 -7
  21. package/dist/{middleware-THfK90u_.mjs → middleware-BD-WrN2n.mjs} +50 -13
  22. package/dist/{middleware-Ccpokmfe.cjs → middleware-C-fzauLy.cjs} +97 -8
  23. package/dist/{middleware-C5ao_lvm.mjs → middleware-CAUZmBAN.mjs} +1 -1
  24. package/dist/{middleware-DTxZNOqy.cjs → middleware-D3TvoZdj.cjs} +1 -1
  25. package/dist/mod.cjs +4 -4
  26. package/dist/mod.js +4 -4
  27. package/dist/nodeinfo/handler.test.mjs +1 -1
  28. package/dist/{owner-CebIXUof.mjs → owner-B6F-ovsj.mjs} +2 -2
  29. package/dist/{proof-UXZOysVc.mjs → proof-CN82dCfF.mjs} +2 -2
  30. package/dist/{proof-C2QsttUL.cjs → proof-CP3pE1Ok.cjs} +1 -1
  31. package/dist/{proof-Cdxbeq4n.js → proof-DCfIkmPR.js} +1 -1
  32. package/dist/{send-_8qtDYZA.mjs → send-DNs8Rwv0.mjs} +54 -2
  33. package/dist/sig/http.test.mjs +2 -2
  34. package/dist/sig/key.test.mjs +1 -1
  35. package/dist/sig/ld.test.mjs +2 -2
  36. package/dist/sig/mod.cjs +2 -2
  37. package/dist/sig/mod.js +2 -2
  38. package/dist/sig/owner.test.mjs +1 -1
  39. package/dist/sig/proof.test.mjs +1 -1
  40. package/dist/utils/docloader.test.mjs +2 -2
  41. package/dist/utils/mod.cjs +1 -1
  42. package/dist/utils/mod.js +1 -1
  43. package/package.json +6 -6
@@ -2,21 +2,21 @@ import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { n as RouterError } from "./router-CrMLXoOr.mjs";
5
- import { n as version, t as name } from "./deno-D9LpbVQR.mjs";
5
+ import { n as version, t as name } from "./deno-BvRV20GH.mjs";
6
6
  import { t as formatAcceptSignature } from "./accept-CceiKpCy.mjs";
7
- import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-BPjHWwyv.mjs";
8
- import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-D6yvDhyL.mjs";
9
- import { t as getAuthenticatedDocumentLoader } from "./docloader-y2viZ2Tx.mjs";
7
+ import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-CjtOXvjb.mjs";
8
+ import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-BETUCsB0.mjs";
9
+ import { t as getAuthenticatedDocumentLoader } from "./docloader-YOsFpxMZ.mjs";
10
10
  import { n as kvCache } from "./kv-cache-Bmv7tUzz.mjs";
11
- import { a as signJsonLd, i as hasSignatureLike, o as verifyJsonLd, r as detachSignature } from "./ld-D9yQwfkO.mjs";
12
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-CebIXUof.mjs";
11
+ import { a as signJsonLd, i as hasSignatureLike, o as verifyJsonLd, r as detachSignature } from "./ld-WRlX-hAe.mjs";
12
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-B6F-ovsj.mjs";
13
13
  import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-Bi7n-dEy.mjs";
14
- import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-UXZOysVc.mjs";
14
+ import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-CN82dCfF.mjs";
15
15
  import { t as getNodeInfo } from "./client-CIiz1WX7.mjs";
16
16
  import { t as nodeInfoToJson } from "./types-BFowWFTT.mjs";
17
- import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-BhiIuyGK.mjs";
17
+ import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-5M0ZV0s3.mjs";
18
18
  import { t as buildCollectionSynchronizationHeader } from "./collection-CA3V5zyK.mjs";
19
- import { a as getFederationMetrics, i as getDurationMs, n as extractInboxes, o as getRemoteHost, r as sendActivity, t as SendActivityError } from "./send-_8qtDYZA.mjs";
19
+ import { a as getFederationMetrics, i as getDurationMs, n as extractInboxes, o as getRemoteHost, r as sendActivity, t as SendActivityError } from "./send-DNs8Rwv0.mjs";
20
20
  import { t as KvKeyCache } from "./keycache-BeU0LCII.mjs";
21
21
  import { t as acceptsJsonLd } from "./negotiation-VnHNB0Q5.mjs";
22
22
  import { t as createExponentialBackoffPolicy } from "./retry-_VvV0h9f.mjs";
@@ -2425,6 +2425,8 @@ var FederationImpl = class extends FederationBuilderImpl {
2425
2425
  fetch(request, options) {
2426
2426
  return withContext({ requestId: getRequestId(request) }, async () => {
2427
2427
  const tracer = this._getTracer();
2428
+ const metricState = {};
2429
+ const metricStart = performance.now();
2428
2430
  return await tracer.startActiveSpan(request.method, {
2429
2431
  kind: SpanKind.SERVER,
2430
2432
  attributes: {
@@ -2448,10 +2450,12 @@ var FederationImpl = class extends FederationBuilderImpl {
2448
2450
  response = await this.#fetch(request, {
2449
2451
  ...options,
2450
2452
  span,
2451
- tracer
2453
+ tracer,
2454
+ metricState
2452
2455
  });
2453
2456
  if (acceptsJsonLd(request)) response.headers.set("Vary", "Accept");
2454
2457
  } catch (error) {
2458
+ getFederationMetrics(this.meterProvider).recordHttpServerRequest(request.method, metricState.endpoint ?? "error", getDurationMs(metricStart), { routeTemplate: metricState.routeTemplate });
2455
2459
  span.setStatus({
2456
2460
  code: SpanStatusCode.ERROR,
2457
2461
  message: `${error}`
@@ -2464,6 +2468,10 @@ var FederationImpl = class extends FederationBuilderImpl {
2464
2468
  });
2465
2469
  throw error;
2466
2470
  }
2471
+ getFederationMetrics(this.meterProvider).recordHttpServerRequest(request.method, metricState.endpoint ?? "error", getDurationMs(metricStart), {
2472
+ statusCode: response.status,
2473
+ routeTemplate: metricState.routeTemplate
2474
+ });
2467
2475
  if (span.isRecording()) {
2468
2476
  span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, response.status);
2469
2477
  for (const [k, v] of response.headers) span.setAttribute(ATTR_HTTP_RESPONSE_HEADER(k), [v]);
@@ -2489,13 +2497,18 @@ var FederationImpl = class extends FederationBuilderImpl {
2489
2497
  });
2490
2498
  });
2491
2499
  }
2492
- async #fetch(request, { onNotFound, onNotAcceptable, onUnauthorized, contextData, span, tracer }) {
2500
+ async #fetch(request, { onNotFound, onNotAcceptable, onUnauthorized, contextData, span, tracer, metricState }) {
2493
2501
  onNotFound ??= notFound;
2494
2502
  onNotAcceptable ??= notAcceptable;
2495
2503
  onUnauthorized ??= unauthorized;
2496
2504
  const url = new URL(request.url);
2497
2505
  const route = this.router.route(url.pathname);
2498
- if (route == null) return await onNotFound(request);
2506
+ if (route == null) {
2507
+ metricState.endpoint = "not_found";
2508
+ return await onNotFound(request);
2509
+ }
2510
+ metricState.routeTemplate = route.template;
2511
+ metricState.endpoint = getEndpointCategory(route.name);
2499
2512
  span.updateName(`${request.method} ${route.template}`);
2500
2513
  let context = this.#createContext(request, contextData);
2501
2514
  const routeName = route.name.replace(/:.*$/, "");
@@ -2516,7 +2529,10 @@ var FederationImpl = class extends FederationBuilderImpl {
2516
2529
  nodeInfoDispatcher: this.nodeInfoDispatcher
2517
2530
  });
2518
2531
  }
2519
- if (request.method !== "POST" && !acceptsJsonLd(request)) return await onNotAcceptable(request);
2532
+ if (request.method !== "POST" && !acceptsJsonLd(request)) {
2533
+ metricState.endpoint = "not_acceptable";
2534
+ return await onNotAcceptable(request);
2535
+ }
2520
2536
  switch (routeName) {
2521
2537
  case "actor":
2522
2538
  case "actorAlias": {
@@ -2707,12 +2723,33 @@ var FederationImpl = class extends FederationBuilderImpl {
2707
2723
  });
2708
2724
  }
2709
2725
  default: {
2726
+ metricState.endpoint = "not_found";
2710
2727
  const response = onNotFound(request);
2711
2728
  return response instanceof Promise ? await response : response;
2712
2729
  }
2713
2730
  }
2714
2731
  }
2715
2732
  };
2733
+ function getEndpointCategory(routeName) {
2734
+ if (routeName.startsWith("object:")) return "object";
2735
+ if (routeName.startsWith("collection:") || routeName.startsWith("orderedCollection:")) return "collection";
2736
+ if (routeName.startsWith("actorAlias:")) return "actor";
2737
+ switch (routeName) {
2738
+ case "webfinger": return "webfinger";
2739
+ case "nodeInfoJrd":
2740
+ case "nodeInfo": return "nodeinfo";
2741
+ case "actor": return "actor";
2742
+ case "inbox": return "inbox";
2743
+ case "sharedInbox": return "shared_inbox";
2744
+ case "outbox": return "outbox";
2745
+ case "following": return "following";
2746
+ case "followers": return "followers";
2747
+ case "liked": return "liked";
2748
+ case "featured": return "featured";
2749
+ case "featuredTags": return "featured_tags";
2750
+ default: return "not_found";
2751
+ }
2752
+ }
2716
2753
  const FANOUT_THRESHOLD = 5;
2717
2754
  var ContextImpl = class ContextImpl {
2718
2755
  url;
@@ -2,10 +2,10 @@ const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  require("./chunk-DDcVe30Y.cjs");
4
4
  const require_transformers = require("./transformers-NeAONrAq.cjs");
5
- const require_http = require("./http-Bj0uN6d-.cjs");
6
- const require_proof = require("./proof-C2QsttUL.cjs");
5
+ const require_http = require("./http-DT4PVP4u.cjs");
6
+ const require_proof = require("./proof-CP3pE1Ok.cjs");
7
7
  const require_types = require("./types-KC4QAoxe.cjs");
8
- const require_kv_cache = require("./kv-cache-BdSTsjLb.cjs");
8
+ const require_kv_cache = require("./kv-cache-DqiCNMDz.cjs");
9
9
  let _logtape_logtape = require("@logtape/logtape");
10
10
  let _fedify_vocab = require("@fedify/vocab");
11
11
  let _opentelemetry_api = require("@opentelemetry/api");
@@ -211,7 +211,7 @@ var FederationBuilderImpl = class {
211
211
  this.collectionTypeIds = {};
212
212
  }
213
213
  async build(options) {
214
- const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-DTxZNOqy.cjs"));
214
+ const { FederationImpl } = await Promise.resolve().then(() => require("./middleware-D3TvoZdj.cjs"));
215
215
  const f = new FederationImpl(options);
216
216
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
217
217
  f.router = this.router.clone();
@@ -786,6 +786,8 @@ var FederationMetrics = class {
786
786
  signatureVerificationFailure;
787
787
  deliveryDuration;
788
788
  inboxProcessingDuration;
789
+ httpServerRequestCount;
790
+ httpServerRequestDuration;
789
791
  constructor(meterProvider) {
790
792
  const meter = meterProvider.getMeter(require_http.name, require_http.version);
791
793
  this.deliverySent = meter.createCounter("activitypub.delivery.sent", {
@@ -808,6 +810,30 @@ var FederationMetrics = class {
808
810
  description: "Duration of ActivityPub inbox listener processing.",
809
811
  unit: "ms"
810
812
  });
813
+ this.httpServerRequestCount = meter.createCounter("fedify.http.server.request.count", {
814
+ description: "HTTP requests handled by Federation.fetch().",
815
+ unit: "{request}"
816
+ });
817
+ this.httpServerRequestDuration = meter.createHistogram("fedify.http.server.request.duration", {
818
+ description: "Duration of HTTP requests handled by Federation.fetch().",
819
+ unit: "ms",
820
+ advice: { explicitBucketBoundaries: [
821
+ 5,
822
+ 10,
823
+ 25,
824
+ 50,
825
+ 75,
826
+ 100,
827
+ 250,
828
+ 500,
829
+ 750,
830
+ 1e3,
831
+ 2500,
832
+ 5e3,
833
+ 7500,
834
+ 1e4
835
+ ] }
836
+ });
811
837
  }
812
838
  recordDelivery(inbox, durationMs, success, activityType) {
813
839
  const deliveryAttributes = {
@@ -832,7 +858,33 @@ var FederationMetrics = class {
832
858
  recordInboxProcessingDuration(activityType, durationMs) {
833
859
  this.inboxProcessingDuration.record(durationMs, { "activitypub.activity.type": activityType });
834
860
  }
861
+ recordHttpServerRequest(method, endpoint, durationMs, options = {}) {
862
+ const attributes = {
863
+ "http.request.method": normalizeHttpMethod(method),
864
+ "fedify.endpoint": endpoint
865
+ };
866
+ if (options.statusCode != null) attributes["http.response.status_code"] = options.statusCode;
867
+ if (options.routeTemplate != null) attributes["fedify.route.template"] = options.routeTemplate;
868
+ this.httpServerRequestCount.add(1, attributes);
869
+ this.httpServerRequestDuration.record(durationMs, attributes);
870
+ }
835
871
  };
872
+ const KNOWN_HTTP_METHODS = new Set([
873
+ "CONNECT",
874
+ "DELETE",
875
+ "GET",
876
+ "HEAD",
877
+ "OPTIONS",
878
+ "PATCH",
879
+ "POST",
880
+ "PUT",
881
+ "QUERY",
882
+ "TRACE"
883
+ ]);
884
+ function normalizeHttpMethod(method) {
885
+ const upper = method.toUpperCase();
886
+ return KNOWN_HTTP_METHODS.has(upper) ? upper : "_OTHER";
887
+ }
836
888
  const federationMetrics = /* @__PURE__ */ new WeakMap();
837
889
  /**
838
890
  * Gets the cached Fedify metric instruments for a meter provider.
@@ -3569,6 +3621,8 @@ var FederationImpl = class extends FederationBuilderImpl {
3569
3621
  fetch(request, options) {
3570
3622
  return (0, _logtape_logtape.withContext)({ requestId: getRequestId(request) }, async () => {
3571
3623
  const tracer = this._getTracer();
3624
+ const metricState = {};
3625
+ const metricStart = performance.now();
3572
3626
  return await tracer.startActiveSpan(request.method, {
3573
3627
  kind: _opentelemetry_api.SpanKind.SERVER,
3574
3628
  attributes: {
@@ -3592,10 +3646,12 @@ var FederationImpl = class extends FederationBuilderImpl {
3592
3646
  response = await this.#fetch(request, {
3593
3647
  ...options,
3594
3648
  span,
3595
- tracer
3649
+ tracer,
3650
+ metricState
3596
3651
  });
3597
3652
  if (acceptsJsonLd(request)) response.headers.set("Vary", "Accept");
3598
3653
  } catch (error) {
3654
+ getFederationMetrics(this.meterProvider).recordHttpServerRequest(request.method, metricState.endpoint ?? "error", getDurationMs(metricStart), { routeTemplate: metricState.routeTemplate });
3599
3655
  span.setStatus({
3600
3656
  code: _opentelemetry_api.SpanStatusCode.ERROR,
3601
3657
  message: `${error}`
@@ -3608,6 +3664,10 @@ var FederationImpl = class extends FederationBuilderImpl {
3608
3664
  });
3609
3665
  throw error;
3610
3666
  }
3667
+ getFederationMetrics(this.meterProvider).recordHttpServerRequest(request.method, metricState.endpoint ?? "error", getDurationMs(metricStart), {
3668
+ statusCode: response.status,
3669
+ routeTemplate: metricState.routeTemplate
3670
+ });
3611
3671
  if (span.isRecording()) {
3612
3672
  span.setAttribute(_opentelemetry_semantic_conventions.ATTR_HTTP_RESPONSE_STATUS_CODE, response.status);
3613
3673
  for (const [k, v] of response.headers) span.setAttribute((0, _opentelemetry_semantic_conventions.ATTR_HTTP_RESPONSE_HEADER)(k), [v]);
@@ -3633,13 +3693,18 @@ var FederationImpl = class extends FederationBuilderImpl {
3633
3693
  });
3634
3694
  });
3635
3695
  }
3636
- async #fetch(request, { onNotFound, onNotAcceptable, onUnauthorized, contextData, span, tracer }) {
3696
+ async #fetch(request, { onNotFound, onNotAcceptable, onUnauthorized, contextData, span, tracer, metricState }) {
3637
3697
  onNotFound ??= notFound;
3638
3698
  onNotAcceptable ??= notAcceptable;
3639
3699
  onUnauthorized ??= unauthorized;
3640
3700
  const url = new URL(request.url);
3641
3701
  const route = this.router.route(url.pathname);
3642
- if (route == null) return await onNotFound(request);
3702
+ if (route == null) {
3703
+ metricState.endpoint = "not_found";
3704
+ return await onNotFound(request);
3705
+ }
3706
+ metricState.routeTemplate = route.template;
3707
+ metricState.endpoint = getEndpointCategory(route.name);
3643
3708
  span.updateName(`${request.method} ${route.template}`);
3644
3709
  let context = this.#createContext(request, contextData);
3645
3710
  const routeName = route.name.replace(/:.*$/, "");
@@ -3660,7 +3725,10 @@ var FederationImpl = class extends FederationBuilderImpl {
3660
3725
  nodeInfoDispatcher: this.nodeInfoDispatcher
3661
3726
  });
3662
3727
  }
3663
- if (request.method !== "POST" && !acceptsJsonLd(request)) return await onNotAcceptable(request);
3728
+ if (request.method !== "POST" && !acceptsJsonLd(request)) {
3729
+ metricState.endpoint = "not_acceptable";
3730
+ return await onNotAcceptable(request);
3731
+ }
3664
3732
  switch (routeName) {
3665
3733
  case "actor":
3666
3734
  case "actorAlias": {
@@ -3851,12 +3919,33 @@ var FederationImpl = class extends FederationBuilderImpl {
3851
3919
  });
3852
3920
  }
3853
3921
  default: {
3922
+ metricState.endpoint = "not_found";
3854
3923
  const response = onNotFound(request);
3855
3924
  return response instanceof Promise ? await response : response;
3856
3925
  }
3857
3926
  }
3858
3927
  }
3859
3928
  };
3929
+ function getEndpointCategory(routeName) {
3930
+ if (routeName.startsWith("object:")) return "object";
3931
+ if (routeName.startsWith("collection:") || routeName.startsWith("orderedCollection:")) return "collection";
3932
+ if (routeName.startsWith("actorAlias:")) return "actor";
3933
+ switch (routeName) {
3934
+ case "webfinger": return "webfinger";
3935
+ case "nodeInfoJrd":
3936
+ case "nodeInfo": return "nodeinfo";
3937
+ case "actor": return "actor";
3938
+ case "inbox": return "inbox";
3939
+ case "sharedInbox": return "shared_inbox";
3940
+ case "outbox": return "outbox";
3941
+ case "following": return "following";
3942
+ case "followers": return "followers";
3943
+ case "liked": return "liked";
3944
+ case "featured": return "featured";
3945
+ case "featuredTags": return "featured_tags";
3946
+ default: return "not_found";
3947
+ }
3948
+ }
3860
3949
  const FANOUT_THRESHOLD = 5;
3861
3950
  var ContextImpl = class ContextImpl {
3862
3951
  url;
@@ -1,5 +1,5 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as FederationImpl } from "./middleware-THfK90u_.mjs";
4
+ import { n as FederationImpl } from "./middleware-BD-WrN2n.mjs";
5
5
  export { FederationImpl };
@@ -1,4 +1,4 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
- const require_middleware = require("./middleware-Ccpokmfe.cjs");
3
+ const require_middleware = require("./middleware-C-fzauLy.cjs");
4
4
  exports.FederationImpl = require_middleware.FederationImpl;
package/dist/mod.cjs CHANGED
@@ -4,11 +4,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  require("./chunk-DDcVe30Y.cjs");
5
5
  const require_transformers = require("./transformers-NeAONrAq.cjs");
6
6
  require("./compat/mod.cjs");
7
- const require_http = require("./http-Bj0uN6d-.cjs");
8
- const require_middleware = require("./middleware-Ccpokmfe.cjs");
9
- const require_proof = require("./proof-C2QsttUL.cjs");
7
+ const require_http = require("./http-DT4PVP4u.cjs");
8
+ const require_middleware = require("./middleware-C-fzauLy.cjs");
9
+ const require_proof = require("./proof-CP3pE1Ok.cjs");
10
10
  const require_types = require("./types-KC4QAoxe.cjs");
11
- const require_kv_cache = require("./kv-cache-BdSTsjLb.cjs");
11
+ const require_kv_cache = require("./kv-cache-DqiCNMDz.cjs");
12
12
  const require_federation_mod = require("./federation/mod.cjs");
13
13
  require("./nodeinfo/mod.cjs");
14
14
  require("./runtime/mod.cjs");
package/dist/mod.js CHANGED
@@ -3,11 +3,11 @@ import "urlpattern-polyfill";
3
3
  import "./chunk-nlSIicah.js";
4
4
  import { n as autoIdAssigner, r as getDefaultActivityTransformers, t as actorDehydrator } from "./transformers-ve6e2xcg.js";
5
5
  import "./compat/mod.js";
6
- import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "./http-CA4xKsSY.js";
7
- import { a as createExponentialBackoffPolicy, c as buildCollectionSynchronizationHeader, d as Router, f as RouterError, i as SendActivityError, l as digest, o as respondWithObject, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as createFederationBuilder } from "./middleware-0n0ctSu_.js";
8
- import { a as verifyProof, c as getKeyOwner, d as detachSignature, f as hasSignatureLike, h as verifySignature, i as verifyObject, l as attachSignature, m as verifyJsonLd, n as hasProofLike, p as signJsonLd, r as signObject, s as doesActorOwnKey, t as createProof, u as createSignature } from "./proof-Cdxbeq4n.js";
6
+ import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "./http-Cj-JmUpS.js";
7
+ import { a as createExponentialBackoffPolicy, c as buildCollectionSynchronizationHeader, d as Router, f as RouterError, i as SendActivityError, l as digest, o as respondWithObject, r as handleWebFinger, s as respondWithObjectIfAcceptable, t as createFederation, u as createFederationBuilder } from "./middleware-B0YQlYeu.js";
8
+ import { a as verifyProof, c as getKeyOwner, d as detachSignature, f as hasSignatureLike, h as verifySignature, i as verifyObject, l as attachSignature, m as verifyJsonLd, n as hasProofLike, p as signJsonLd, r as signObject, s as doesActorOwnKey, t as createProof, u as createSignature } from "./proof-DCfIkmPR.js";
9
9
  import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "./types-hvL8ElAs.js";
10
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-DarvCOHt.js";
10
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-BOU_yvQi.js";
11
11
  import { InProcessMessageQueue, MemoryKvStore, ParallelMessageQueue } from "./federation/mod.js";
12
12
  import "./nodeinfo/mod.js";
13
13
  import "./runtime/mod.js";
@@ -5,7 +5,7 @@ import { r as createRequestContext } from "../context-7Azky82W.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
6
  import "../std__assert-CRDpx_HF.mjs";
7
7
  import { t as MemoryKvStore } from "../kv-x2IvBUyq.mjs";
8
- import { _ as handleNodeInfoJrd, g as handleNodeInfo, o as createFederation } from "../middleware-THfK90u_.mjs";
8
+ import { _ as handleNodeInfoJrd, g as handleNodeInfo, o as createFederation } from "../middleware-BD-WrN2n.mjs";
9
9
  import { test } from "@fedify/fixture";
10
10
  //#region src/nodeinfo/handler.test.ts
11
11
  test("handleNodeInfo()", async () => {
@@ -1,8 +1,8 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-D9LpbVQR.mjs";
5
- import "./key-BPjHWwyv.mjs";
4
+ import { n as version, t as name } from "./deno-BvRV20GH.mjs";
5
+ import "./key-CjtOXvjb.mjs";
6
6
  import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
7
7
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
8
8
  import { getDocumentLoader } from "@fedify/vocab-runtime";
@@ -1,8 +1,8 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-D9LpbVQR.mjs";
5
- import { n as fetchKey, o as validateCryptoKey } from "./key-BPjHWwyv.mjs";
4
+ import { n as version, t as name } from "./deno-BvRV20GH.mjs";
5
+ import { n as fetchKey, o as validateCryptoKey } from "./key-CjtOXvjb.mjs";
6
6
  import { n as preloadedOnlyDocumentLoader } from "./public-audience-PVTwU_Ex.mjs";
7
7
  import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-Bi7n-dEy.mjs";
8
8
  import { Activity, DataIntegrityProof, Multikey, getTypeId } from "@fedify/vocab";
@@ -1,7 +1,7 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  const require_chunk = require("./chunk-DDcVe30Y.cjs");
4
- const require_http = require("./http-Bj0uN6d-.cjs");
4
+ const require_http = require("./http-DT4PVP4u.cjs");
5
5
  let _logtape_logtape = require("@logtape/logtape");
6
6
  let _fedify_vocab = require("@fedify/vocab");
7
7
  let _opentelemetry_api = require("@opentelemetry/api");
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
- import { _ as version, d as validateCryptoKey, g as name, s as fetchKey } from "./http-CA4xKsSY.js";
3
+ import { _ as version, d as validateCryptoKey, g as name, s as fetchKey } from "./http-Cj-JmUpS.js";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, PUBLIC_COLLECTION, getTypeId, isActor } from "@fedify/vocab";
6
6
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
@@ -1,8 +1,8 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-D9LpbVQR.mjs";
5
- import { n as doubleKnock } from "./http-D6yvDhyL.mjs";
4
+ import { n as version, t as name } from "./deno-BvRV20GH.mjs";
5
+ import { n as doubleKnock } from "./http-BETUCsB0.mjs";
6
6
  import { SpanKind, SpanStatusCode, metrics, trace } from "@opentelemetry/api";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  //#region src/federation/metrics.ts
@@ -12,6 +12,8 @@ var FederationMetrics = class {
12
12
  signatureVerificationFailure;
13
13
  deliveryDuration;
14
14
  inboxProcessingDuration;
15
+ httpServerRequestCount;
16
+ httpServerRequestDuration;
15
17
  constructor(meterProvider) {
16
18
  const meter = meterProvider.getMeter(name, version);
17
19
  this.deliverySent = meter.createCounter("activitypub.delivery.sent", {
@@ -34,6 +36,30 @@ var FederationMetrics = class {
34
36
  description: "Duration of ActivityPub inbox listener processing.",
35
37
  unit: "ms"
36
38
  });
39
+ this.httpServerRequestCount = meter.createCounter("fedify.http.server.request.count", {
40
+ description: "HTTP requests handled by Federation.fetch().",
41
+ unit: "{request}"
42
+ });
43
+ this.httpServerRequestDuration = meter.createHistogram("fedify.http.server.request.duration", {
44
+ description: "Duration of HTTP requests handled by Federation.fetch().",
45
+ unit: "ms",
46
+ advice: { explicitBucketBoundaries: [
47
+ 5,
48
+ 10,
49
+ 25,
50
+ 50,
51
+ 75,
52
+ 100,
53
+ 250,
54
+ 500,
55
+ 750,
56
+ 1e3,
57
+ 2500,
58
+ 5e3,
59
+ 7500,
60
+ 1e4
61
+ ] }
62
+ });
37
63
  }
38
64
  recordDelivery(inbox, durationMs, success, activityType) {
39
65
  const deliveryAttributes = {
@@ -58,7 +84,33 @@ var FederationMetrics = class {
58
84
  recordInboxProcessingDuration(activityType, durationMs) {
59
85
  this.inboxProcessingDuration.record(durationMs, { "activitypub.activity.type": activityType });
60
86
  }
87
+ recordHttpServerRequest(method, endpoint, durationMs, options = {}) {
88
+ const attributes = {
89
+ "http.request.method": normalizeHttpMethod(method),
90
+ "fedify.endpoint": endpoint
91
+ };
92
+ if (options.statusCode != null) attributes["http.response.status_code"] = options.statusCode;
93
+ if (options.routeTemplate != null) attributes["fedify.route.template"] = options.routeTemplate;
94
+ this.httpServerRequestCount.add(1, attributes);
95
+ this.httpServerRequestDuration.record(durationMs, attributes);
96
+ }
61
97
  };
98
+ const KNOWN_HTTP_METHODS = new Set([
99
+ "CONNECT",
100
+ "DELETE",
101
+ "GET",
102
+ "HEAD",
103
+ "OPTIONS",
104
+ "PATCH",
105
+ "POST",
106
+ "PUT",
107
+ "QUERY",
108
+ "TRACE"
109
+ ]);
110
+ function normalizeHttpMethod(method) {
111
+ const upper = method.toUpperCase();
112
+ return KNOWN_HTTP_METHODS.has(upper) ? upper : "_OTHER";
113
+ }
62
114
  const federationMetrics = /* @__PURE__ */ new WeakMap();
63
115
  /**
64
116
  * Gets the cached Fedify metric instruments for a meter provider.
@@ -7,8 +7,8 @@ import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z
7
7
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
8
8
  import { t as assert } from "../assert-DikXweDx.mjs";
9
9
  import { t as esm_default } from "../esm-DhnRLoG9.mjs";
10
- import { t as exportJwk } from "../key-BPjHWwyv.mjs";
11
- import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase, u as verifyRequestDetailed } from "../http-D6yvDhyL.mjs";
10
+ import { t as exportJwk } from "../key-CjtOXvjb.mjs";
11
+ import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase, u as verifyRequestDetailed } from "../http-BETUCsB0.mjs";
12
12
  import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-C3kae-6B.mjs";
13
13
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
14
14
  import { FetchError, exportSpki } from "@fedify/vocab-runtime";
@@ -5,7 +5,7 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import "../std__assert-CRDpx_HF.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
8
- import { a as importJwk, i as generateCryptoKeyPair, n as fetchKey, o as validateCryptoKey, r as fetchKeyDetailed, t as exportJwk } from "../key-BPjHWwyv.mjs";
8
+ import { a as importJwk, i as generateCryptoKeyPair, n as fetchKey, o as validateCryptoKey, r as fetchKeyDetailed, t as exportJwk } from "../key-CjtOXvjb.mjs";
9
9
  import { c as rsaPublicKey3, i as rsaPrivateKey2, o as rsaPublicKey1, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-C3kae-6B.mjs";
10
10
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { CryptographicKey, Multikey } from "@fedify/vocab";
@@ -5,9 +5,9 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
6
6
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
7
7
  import { t as assert } from "../assert-DikXweDx.mjs";
8
- import { i as generateCryptoKeyPair } from "../key-BPjHWwyv.mjs";
8
+ import { i as generateCryptoKeyPair } from "../key-CjtOXvjb.mjs";
9
9
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-C3kae-6B.mjs";
10
- import { a as signJsonLd, i as hasSignatureLike, n as createSignature, o as verifyJsonLd, r as detachSignature, s as verifySignature, t as attachSignature } from "../ld-D9yQwfkO.mjs";
10
+ import { a as signJsonLd, i as hasSignatureLike, n as createSignature, o as verifyJsonLd, r as detachSignature, s as verifySignature, t as attachSignature } from "../ld-WRlX-hAe.mjs";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  import { CryptographicKey } from "@fedify/vocab";
13
13
  import { encodeBase64 } from "byte-encodings/base64";
package/dist/sig/mod.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const require_http = require("../http-Bj0uN6d-.cjs");
5
- const require_proof = require("../proof-C2QsttUL.cjs");
4
+ const require_http = require("../http-DT4PVP4u.cjs");
5
+ const require_proof = require("../proof-CP3pE1Ok.cjs");
6
6
  exports.attachSignature = require_proof.attachSignature;
7
7
  exports.createProof = require_proof.createProof;
8
8
  exports.createSignature = require_proof.createSignature;
package/dist/sig/mod.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
- import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-CA4xKsSY.js";
4
- import { a as verifyProof, c as getKeyOwner, d as detachSignature, f as hasSignatureLike, h as verifySignature, i as verifyObject, l as attachSignature, m as verifyJsonLd, n as hasProofLike, p as signJsonLd, r as signObject, s as doesActorOwnKey, t as createProof, u as createSignature } from "../proof-Cdxbeq4n.js";
3
+ import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-Cj-JmUpS.js";
4
+ import { a as verifyProof, c as getKeyOwner, d as detachSignature, f as hasSignatureLike, h as verifySignature, i as verifyObject, l as attachSignature, m as verifyJsonLd, n as hasProofLike, p as signJsonLd, r as signObject, s as doesActorOwnKey, t as createProof, u as createSignature } from "../proof-DCfIkmPR.js";
5
5
  export { attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
@@ -6,7 +6,7 @@ import "../std__assert-CRDpx_HF.mjs";
6
6
  import { n as assertFalse } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assert } from "../assert-DikXweDx.mjs";
8
8
  import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-C3kae-6B.mjs";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-CebIXUof.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-B6F-ovsj.mjs";
10
10
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { Create, CryptographicKey, lookupObject } from "@fedify/vocab";
12
12
  //#region src/sig/owner.test.ts
@@ -8,7 +8,7 @@ import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
8
8
  import { t as assert } from "../assert-DikXweDx.mjs";
9
9
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-C3kae-6B.mjs";
10
10
  import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-Bi7n-dEy.mjs";
11
- import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-UXZOysVc.mjs";
11
+ import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-CN82dCfF.mjs";
12
12
  import { mockDocumentLoader, test } from "@fedify/fixture";
13
13
  import { Create, DataIntegrityProof, Document, Multikey, Note, PUBLIC_COLLECTION, Place } from "@fedify/vocab";
14
14
  import { decodeMultibase, importMultibaseKey } from "@fedify/vocab-runtime";
@@ -5,9 +5,9 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import "../std__assert-CRDpx_HF.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as esm_default } from "../esm-DhnRLoG9.mjs";
8
- import { l as verifyRequest } from "../http-D6yvDhyL.mjs";
8
+ import { l as verifyRequest } from "../http-BETUCsB0.mjs";
9
9
  import { i as rsaPrivateKey2 } from "../keys-C3kae-6B.mjs";
10
- import { t as getAuthenticatedDocumentLoader } from "../docloader-y2viZ2Tx.mjs";
10
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-YOsFpxMZ.mjs";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  import { UrlError } from "@fedify/vocab-runtime";
13
13
  //#region src/utils/docloader.test.ts
@@ -1,6 +1,6 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const require_kv_cache = require("../kv-cache-BdSTsjLb.cjs");
4
+ const require_kv_cache = require("../kv-cache-DqiCNMDz.cjs");
5
5
  exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
6
6
  exports.kvCache = require_kv_cache.kvCache;
package/dist/utils/mod.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-DarvCOHt.js";
3
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-BOU_yvQi.js";
4
4
  export { getAuthenticatedDocumentLoader, kvCache };