refactor: implement recordClientVersion as middleware (@fehmer) (#5750)

* refactor: implement recordClientVersion as middleware (@fehmer)

* move csp for docs into docs route

* fix

* review comments
This commit is contained in:
Christian Fehmer 2024-08-09 14:20:16 +02:00 committed by GitHub
parent 8e343bc390
commit 02505750ad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 29 additions and 18 deletions

View file

@ -1,4 +1,4 @@
import { Router } from "express";
import { Response, Router } from "express";
import * as swaggerUi from "swagger-ui-express";
import publicSwaggerSpec from "../../documentation/public-swagger.json";
@ -12,6 +12,7 @@ const router = Router();
const root = __dirname + "../../../static";
router.use("/v2/internal", (req, res) => {
setCsp(res);
res.sendFile("api/internal.html", { root });
});
@ -21,6 +22,7 @@ router.use("/v2/internal.json", (req, res) => {
});
router.use(["/v2/public", "/v2/"], (req, res) => {
setCsp(res);
res.sendFile("api/public.html", { root });
});
@ -38,3 +40,10 @@ router.use(
);
export default router;
function setCsp(res: Response): void {
res.setHeader(
"Content-Security-Policy",
"default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' monkeytype.com cdn.redoc.ly data:;object-src 'none';script-src 'self' cdn.redoc.ly 'unsafe-inline'; worker-src blob: data;script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests"
);
}

View file

@ -19,7 +19,6 @@ import leaderboards from "./leaderboards";
import addSwaggerMiddlewares from "./swagger";
import { asyncHandler } from "../../middlewares/utility";
import { MonkeyResponse } from "../../utils/monkey-response";
import { recordClientVersion } from "../../utils/prometheus";
import {
Application,
IRouter,
@ -152,20 +151,6 @@ function applyApiRoutes(app: Application): void {
return;
}
if (req.path === "/psas") {
const clientVersion =
(req.headers["x-client-version"] as string) ||
req.headers["client-version"];
recordClientVersion(clientVersion?.toString() ?? "unknown");
}
if (req.path.startsWith("/docs")) {
res.setHeader(
"Content-Security-Policy",
"default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' monkeytype.com cdn.redoc.ly data:;object-src 'none';script-src 'self' cdn.redoc.ly 'unsafe-inline'; worker-src blob: data;script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests"
);
}
next();
}
);

View file

@ -3,11 +3,12 @@ import { initServer } from "@ts-rest/express";
import * as RateLimit from "../../middlewares/rate-limit";
import * as PsaController from "../controllers/psa";
import { callController } from "../ts-rest-adapter";
import { recordClientVersion } from "../../middlewares/utility";
const s = initServer();
export default s.router(psasContract, {
get: {
middleware: [RateLimit.psaGet],
middleware: [recordClientVersion(), RateLimit.psaGet],
handler: async (r) => callController(PsaController.getPsas)(r),
},
});

View file

@ -1,7 +1,8 @@
import _ from "lodash";
import type { Response, NextFunction, RequestHandler } from "express";
import type { Request, Response, NextFunction, RequestHandler } from "express";
import { handleMonkeyResponse, MonkeyResponse } from "../utils/monkey-response";
import { isDevEnvironment } from "../utils/misc";
import { recordClientVersion as prometheusRecordClientVersion } from "../utils/prometheus";
export const emptyMiddleware = (
_req: MonkeyTypes.Request,
@ -45,3 +46,18 @@ export function useInProduction(
isDevEnvironment() ? emptyMiddleware : middleware
);
}
/**
* record the client version from the `x-client-version` or ` client-version` header to prometheus
*/
export function recordClientVersion(): RequestHandler {
return (req: Request, _res: Response, next: NextFunction) => {
const clientVersion =
(req.headers["x-client-version"] as string) ||
req.headers["client-version"];
prometheusRecordClientVersion(clientVersion?.toString() ?? "unknown");
next();
};
}