mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-28 18:08:15 +03:00
90 lines
2.7 KiB
TypeScript
90 lines
2.7 KiB
TypeScript
import express from "express";
|
|
import "express-async-errors";
|
|
import CreateLogCtx from "./logger";
|
|
import expressSession from "express-session";
|
|
import { SESSION_SECRET } from "./secrets";
|
|
import { integer } from "kamaitachi-common";
|
|
import { RedisClient, RedisStore } from "./redis/redis-store";
|
|
|
|
const logger = CreateLogCtx("server.ts");
|
|
|
|
const userSessionMiddleware = expressSession({
|
|
// append node_env onto the end of the session name
|
|
// so we can separate tokens under the same URL.
|
|
// say for staging.kamaitachi.xyz
|
|
name: `ktblack_session_${process.env.NODE_ENV}`,
|
|
secret: SESSION_SECRET,
|
|
store: new RedisStore({
|
|
host: "localhost",
|
|
port: 6379,
|
|
client: RedisClient,
|
|
}),
|
|
resave: true,
|
|
saveUninitialized: false,
|
|
cookie: {
|
|
secure: process.env.NODE_ENV === "production",
|
|
},
|
|
});
|
|
|
|
const app = express();
|
|
|
|
app.use(userSessionMiddleware);
|
|
|
|
// Most of these options are leveraged from KTAPI
|
|
|
|
// allow nginx to work its magic
|
|
app.set("trust proxy", "loopback");
|
|
|
|
// 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 });
|
|
});
|
|
|
|
// enable reading json bodies
|
|
// limit them so as not to choke the api
|
|
app.use(express.json({ limit: "1mb" }));
|
|
|
|
import internalApiRouter from "./internal-api/internal-api";
|
|
|
|
app.use("/internal-api", internalApiRouter);
|
|
|
|
/**
|
|
* If any user gets to this point, we send them index.html and let react router do the routing (and 404ing)
|
|
* @name *
|
|
*/
|
|
app.get("*", (req, res) => res.status(200).send("todo"));
|
|
|
|
// completely stolen from ktapi error handler
|
|
interface ExpressJSONErr extends SyntaxError {
|
|
status: integer;
|
|
message: string;
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
const MAIN_ERR_HANDLER: express.ErrorRequestHandler = (err, req, res, _next) => {
|
|
if (err instanceof SyntaxError) {
|
|
let expErr: ExpressJSONErr = err as ExpressJSONErr;
|
|
if (expErr.status === 400 && "body" in expErr) {
|
|
return res.status(400).send({ success: false, description: err.message });
|
|
}
|
|
|
|
// else, this isn't a JSON parsing error
|
|
}
|
|
|
|
logger.error(err, req.route);
|
|
return res.status(500).json({
|
|
success: false,
|
|
description: "A fatal internal server error has occured.",
|
|
});
|
|
};
|
|
|
|
app.use(MAIN_ERR_HANDLER);
|
|
|
|
export default app;
|