server/index.ts
Rama main · réplica de lectura del repositorio original.
import express from 'express';
import basicAuth from 'express-basic-auth';
import log4js from 'log4js';
import routes from './controllers/routes';
import { makeUrlPrefixRegExp } from './helpers';
import init from './init';
import { User } from './models';
async function start() {
// Spawn the Express app.
const app = express();
// Middlewares.
// Middleware for removing the url prefix, if it's set.
if (process.kresus.urlPrefix !== '/') {
const rootRegexp = makeUrlPrefixRegExp(process.kresus.urlPrefix);
// We use a trick here, by having something that rewrites the URL by
// removing the URL prefix if it was set.
//
// This means that if the browser tries to access any resource without
// the URL prefix, this would work; so make sure to return 404 on these
// accesses, to avoid hard-to-debug situations.
app.use((req, res, next) => {
// Safeguard against misuses.
if (!req.url.startsWith(process.kresus.urlPrefix)) {
res.status(404);
return false;
}
req.url = req.url.replace(rootRegexp, '/');
return next();
});
}
// Generic express middlewares.
app.use(
log4js.connectLogger(log4js.getLogger('HTTP'), {
level: 'auto',
format: ':method :url - :status (:response-time ms)',
// By default all 3xx status codes, whereas not harmful, will emit a warning message.
// Only keep the warning for 300 (multiple choices) & 310 (too many redirections).
statusRules: [
{
from: 301,
to: 309,
level: 'info',
},
],
})
);
if (process.kresus.basicAuth) {
app.use(
basicAuth({
users: process.kresus.basicAuth,
challenge: true,
realm: 'Kresus Basic Auth',
})
);
}
app.use(
express.json({
limit: '100mb',
})
);
app.use(
express.urlencoded({
extended: true,
limit: '10mb',
})
);
app.use(
express.text({
limit: '100mb',
})
);
app.use(express.static(`${__dirname}/../client`, {}));
if (process.env.NODE_ENV === 'development') {
// In development mode, allow any cross-origin resource sharing.
// Note that having both Allow-Origin set to "*" and credentials in a
// request are disallowed, so we just reflect the origin header back in
// the allow-origin CORS header.
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Headers', 'content-type');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Credentials', 'true');
next();
});
}
// Use a passportjs compatible middleware for logging the only current
// user.
app.use(async (req, res, next) => {
const { userLoginHttpHeader, defaultUser } = process.kresus;
if (userLoginHttpHeader) {
// Try to retrieve the user login from this header name.
const userLogin = req.get(userLoginHttpHeader);
if (!userLogin) {
res.status(401).json({
code: 401,
message: `missing "${userLoginHttpHeader}" header`,
});
return;
}
// Then check if this user actually exists.
const user = await User.findByLogin(userLogin);
if (!user) {
res.status(401).json({
code: 401,
message: `user "${userLogin}" could not be found`,
});
return;
}
req.user = user;
} else {
req.user = defaultUser;
}
next();
});
// Routes.
for (const reqpath of Object.keys(routes)) {
const descriptor = routes[reqpath];
for (const [verb, controller] of Object.entries(descriptor)) {
switch (verb) {
case 'param': {
const paramName = reqpath.split('/').pop();
// paramName can never be undefined due to reqpath.split() returning always
// an array with at least one item, but as Array.pop can be undefined,
// TypeScript wants the check.
if (typeof paramName !== 'undefined') {
app.param(paramName, controller);
}
break;
}
case 'put':
app.put(`/${reqpath}`, controller);
break;
case 'post':
app.post(`/${reqpath}`, controller);
break;
case 'delete':
app.delete(`/${reqpath}`, controller);
break;
case 'get':
app.get(`/${reqpath}`, controller);
break;
default:
throw new Error(`unknown API verb used in index.ts: ${verb}`);
}
}
}
const server = app.listen(process.kresus.port, process.kresus.host);
// Raise the timeout limit, since some banking modules can be quite long at fetching new
// transactions. Time is in seconds, so convert it to milliseconds like Express expects it.
server.timeout = process.kresus.serverTimeout * 1000;
await init();
}
module.exports = {
start,
};