diff --git a/lib/mastodon/middleware/load-settings.js b/lib/mastodon/middleware/load-settings.js new file mode 100644 index 0000000..af59068 --- /dev/null +++ b/lib/mastodon/middleware/load-settings.js @@ -0,0 +1,35 @@ +/** + * Settings cache middleware for Mastodon API hot paths. + * + * Loads settings once per minute (not per request) and attaches + * to req.app.locals.apSettings for all downstream handlers. + */ +import { getSettings } from "../../settings.js"; + +let cachedSettings = null; +let cacheExpiry = 0; +const CACHE_TTL = 60_000; // 1 minute + +export async function loadSettingsMiddleware(req, res, next) { + try { + const now = Date.now(); + if (cachedSettings && now < cacheExpiry) { + req.app.locals.apSettings = cachedSettings; + return next(); + } + + const collections = req.app.locals.application?.collections; + cachedSettings = await getSettings(collections); + cacheExpiry = now + CACHE_TTL; + req.app.locals.apSettings = cachedSettings; + next(); + } catch { + // On error, use defaults + if (!cachedSettings) { + const { DEFAULTS } = await import("../../settings.js"); + cachedSettings = { ...DEFAULTS }; + } + req.app.locals.apSettings = cachedSettings; + next(); + } +} diff --git a/lib/mastodon/router.js b/lib/mastodon/router.js index 8ba5140..fc616bd 100644 --- a/lib/mastodon/router.js +++ b/lib/mastodon/router.js @@ -8,6 +8,7 @@ import express from "express"; import rateLimit from "express-rate-limit"; import { corsMiddleware } from "./middleware/cors.js"; +import { loadSettingsMiddleware } from "./middleware/load-settings.js"; import { tokenRequired, optionalToken } from "./middleware/token-required.js"; import { errorHandler, notImplementedHandler } from "./middleware/error-handler.js"; @@ -77,6 +78,10 @@ export function createMastodonRouter({ collections, pluginOptions = {} }) { // ─── CORS ─────────────────────────────────────────────────────────────── router.use("/api", corsMiddleware); router.use("/oauth/token", corsMiddleware); + + // ─── Settings cache ──────────────────────────────────────────────────── + // Loads plugin settings once per minute, available as req.app.locals.apSettings + router.use("/api", loadSettingsMiddleware); router.use("/oauth/revoke", corsMiddleware); router.use("/.well-known/oauth-authorization-server", corsMiddleware);