-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
134 lines (102 loc) · 3.77 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import express from 'express';
import stoppable from 'stoppable';
import mongoSanitize from 'express-mongo-sanitize';
import helmet from 'helmet';
import xss from 'xss-clean';
import hpp from 'hpp';
import cors from 'cors';
import dotenv from 'dotenv';
import path from 'path';
import { createServer } from 'http';
import { readdir } from 'fs/promises';
import { fileURLToPath } from 'url';
import errorHandler from './middleware/error.js';
import connectDB from './db.js';
import { createLogger } from './utils/logger.js';
import getIPAddr from './utils/network.js';
dotenv.config({ path: '.env' });
const {APP_NAME, NODE_ENV, TZ, LOGGER} = process.env;
const ipAddr = getIPAddr('IPv4');
const PORT = process.env.PORT || 3000;
const APP_URI = `${ipAddr}:${PORT}`;
// Connect to database
connectDB();
// Route files
import kubernetes from './routes/kubernetes.js';
const app = express();
const server = stoppable(createServer(app));
const ts = () => new Date().toISOString();
createLogger(app, LOGGER); // Should we use the await ?
app.use(errorHandler);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// Load security related dependencies
app.use(mongoSanitize());
app.use(helmet());
app.use(xss());
app.use(hpp());
app.use(cors());
app.use((_req, res, next) => {
res.set(generateResponseHeaders());
next();
});
// Create route aliases
app.use('/', kubernetes);
// Dynamically load route files
loadRoutes(app).catch(console.error);
// Initialize Server
app.listen(PORT, () => outputServerInfo());
// Signal handling for graceful shutdowns
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('unhandledRejection', (err, promise) => shutdown(null, err, promise));
function shutdown(signal, error = null, promise = null) {
const ts = () => new Date().toISOString();
if (signal) console.log(`${ts()} Received ${signal}. Graceful shutdown…`);
// Handle unhandled rejection if error is provided
if (error) {
console.error(`Unhandled Error: ${error.message}`);
if (promise) console.log('Promise that was rejected:', promise);
}
server.close((err) => {
// Checks for error when trying to close the server.
// An error here indicates the server did not close cleanly.
if (err) {
console.error(err); // Log the error encountered during server closure
process.exit(1); // Exit with error status due closing server failure
} else if (error) {
process.exit(1); // Shutdown was triggered by an unhandled rejection
}
process.exit(0); // If 0 errors occured, successful graceful shutdown
});
}
function generateResponseHeaders(){
const allow = 'Authorization,Content-Type,Cache-Control,X-Requested-With';
return {
'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Headers': allow,
'Access-Control-Allow-Methods': 'GET, HEAD, POST, OPTIONS',
'Access-Control-Allow-Origin': '*',
Vary: 'Origin',
}
}
async function loadRoutes(app) {
const getFileExtension = (filename) => filename.split('.').pop();
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const files = await readdir(path.join(__dirname, 'routes'));
const validExtensions = ['js', 'mjs'];
for (const file of files) {
const ext = getFileExtension(file);
if(validExtensions.includes(ext)) {
const extensionLength = ext && ext.length ? Number(ext.length + 1) : 3;
const rtName = file.slice(0, -extensionLength);
// Async import route using filename of route for root endpoint
const routeModule = await import(`./routes/${file}`);
app.use(`/${rtName}`, routeModule.default);
}
}
}
function outputServerInfo(){
console.log(`[${NODE_ENV}] ${APP_NAME} running on ${APP_URI}`)
console.log(`[${NODE_ENV}]`, ts(), TZ);
}