kozukata-toa/src/servers/allnet/index.ts

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;