89 lines
2.6 KiB
TypeScript
89 lines
2.6 KiB
TypeScript
// THIS IMPORT **MUST** GO HERE. DO NOT MOVE IT. IT MUST OCCUR BEFORE ANYTHING HAPPENS WITH EXPRESS
|
|
// BUT AFTER EXPRESS IS IMPORTED.
|
|
/* eslint-disable import/order */
|
|
import express from "express";
|
|
import "express-async-errors";
|
|
|
|
import mainRouter from "./router/router";
|
|
import CreateLogCtx from "lib/logger/logger";
|
|
import { DFIRequestResponse } from "./middleware/dfi";
|
|
import type { Express } from "express";
|
|
import { RequestLoggerMiddleware } from "../../lib/middleware/request-logger";
|
|
import { IsRecord } from "utils/misc";
|
|
|
|
const logger = CreateLogCtx(__filename);
|
|
|
|
const app: Express = express();
|
|
|
|
// Pass the IP of the user up our increasingly insane chain of nginx/docker nonsense
|
|
app.set("trust proxy", ["loopback", "linklocal", "uniquelocal"]);
|
|
|
|
// we don't allow nesting in query strings.
|
|
app.set("query parser", "simple");
|
|
|
|
// taken from https://nodejs.org/api/process.html#process_event_unhandledrejection
|
|
// to avoid future deprecation.
|
|
process.on("unhandledRejection", (reason, promise) => {
|
|
// @ts-expect-error reason is an error, and the logger can handle errors
|
|
// it just refuses.
|
|
logger.error(reason, { promise });
|
|
});
|
|
|
|
// We do the body handling here so logging is properly handled.
|
|
app.use((req, res, next) => {
|
|
if (req.path === "/sys/servlet/PowerOn") {
|
|
DFIRequestResponse(true)(req, res, next);
|
|
} else if (req.path === "/report-api/Report") {
|
|
express.json({ limit: "4mb", type: (_) => true })(req, res, next);
|
|
} else {
|
|
DFIRequestResponse(false)(req, res, next);
|
|
}
|
|
});
|
|
|
|
app.use((req, res, next) => {
|
|
if (req.method !== "GET" && (typeof req.body !== "object" || req.body === null)) {
|
|
req.body = {};
|
|
}
|
|
|
|
req.safeBody = req.body as Record<string, unknown>;
|
|
|
|
next();
|
|
});
|
|
|
|
app.use(RequestLoggerMiddleware);
|
|
|
|
app.use("/", mainRouter);
|
|
|
|
const MAIN_ERR_HANDLER: express.ErrorRequestHandler = (err, req, res, _next) => {
|
|
// eslint-disable-next-line cadence/no-instanceof
|
|
if (err instanceof SyntaxError && req.path === "/report-api/Report") {
|
|
logger.error("Could not parse download report as JSON.", { err });
|
|
return res.status(200).send("NG");
|
|
}
|
|
|
|
logger.info(`MAIN_ERR_HANDLER hit by request.`, { url: req.originalUrl });
|
|
|
|
const unknownErr = err as unknown;
|
|
|
|
if (IsRecord(unknownErr) && unknownErr.type === "entity.too.large") {
|
|
return res.status(413).json({
|
|
success: false,
|
|
description: "Your request body was too large. The limit is 4MB.",
|
|
});
|
|
}
|
|
|
|
logger.error("Fatal error propagated to server root? ", {
|
|
err: unknownErr,
|
|
url: req.originalUrl,
|
|
});
|
|
|
|
return res.status(500).json({
|
|
success: false,
|
|
description: "A fatal internal server error has occured.",
|
|
});
|
|
};
|
|
|
|
app.use(MAIN_ERR_HANDLER);
|
|
|
|
export default app;
|