-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathapp.js
More file actions
136 lines (123 loc) · 4.11 KB
/
app.js
File metadata and controls
136 lines (123 loc) · 4.11 KB
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
135
136
/*
* This is file of the project ZEROFIT_NODEJS_SERVER
* Licensed under the MIT License.
* Copyright (c) 2024 ZEROFIT_NODEJS_SERVER
* For full license text, see the LICENSE file in the root directory or at
* https://opensource.org/license/mit
* Author: logicallaw
* Latest Updated Date: 2024-12-24
*/
// 1. Import modules
const express = require('express');
const dotenv = require('dotenv');
const nunjucks = require('nunjucks');
const path = require('path');
const morgan = require('morgan');
const cookie_parser = require('cookie-parser');
const session = require('express-session');
const passport = require('passport');
const ratelimit = require('express-rate-limit');
const logger = require('./logs/logger');
const hpp = require('hpp');
const cors = require('cors');
// Import custom modules
const passport_config = require('./passport');
const main_router = require('./routes/main');
const auth_router = require('./routes/auth');
const clothes_router = require('./routes/clothes');
const market_router = require('./routes/market');
const wishlist_router = require('./routes/wishlist');
const db = require('./models');
// 2. Set environment variables
dotenv.config();
// 3. Initialize application
const app = express();
app.set('port', process.env.PORT);
app.set('trust proxy', 1); // Set trust proxy
app.set('view engine', 'html');
nunjucks.configure('views', {
express: app,
watch: true,
});
// 4. Set security and performance (Rate limit, CORS)
const global_limiter = ratelimit({
windowMs: 1 * 60 * 1000, // 1m
max: 60, // 60 times a minute
message: 'Too many requests, please try again later.',
keyGenerator: (req) => req.ip, // Limit based on ip address
});
app.use(global_limiter);
app.use(cors());
// 5. Set middlewares
if (process.env.NODE_ENV == 'production') {
app.use(morgan('combined')); // Production logging
app.use(hpp()); // Prevent HTTP parameter pollution
} else {
app.use(morgan('dev')); // Development logging
}
app.use(express.static(path.join(__dirname, 'public'))); // Static file serving
app.use(cookie_parser(process.env.COOKIE_SECRET)); // Cookie parser with secret
app.use(express.json(
{limit: '10mb'})); // JSON body parsing, JSON request size limit increased
app.use(express.urlencoded({
limit: '10mb',
extended: false
})); // URL-encoded body parsing, URL-encoded request size limit increased
// Set session
const session_options = {
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
sameSite: 'strict', // CSRF Protection
maxAge: 1000 * 60 * 60, // 1 hours
},
};
app.use(session(session_options));
// 6. Set Passport
passport_config();
app.use(passport.initialize());
app.use(passport.session());
// 7. Initialize data bases
db.sequelize.sync({force: process.env.NODE_ENV === 'test'})
.then(() => {
const node_env = process.env.NODE_ENV;
let host = '0.0.0.0';
if (node_env == 'production') {
host = process.env.SEQUELIZE_HOST;
} else if (node_env == 'development') {
host = process.env.SEQUELIZE_DEV_HOST;
} else {
host = process.env.SEQUELIZE_TEST_HOST;
}
console.log(`[MySQL at ${host}] Database & tables connected!`);
})
.catch((error) => {
console.error(`[MySQL] Error creating database tables:`, error);
});
// 8. Set routers
app.use('/', main_router);
app.use('/auth', auth_router);
app.use('/clothes', clothes_router);
app.use('/market', market_router);
app.use('/wishlist', wishlist_router);
// 9. Error Handling Middleware
app.use((req, res, next) => {
const error = new Error(`Not existed ${req.method} ${req.url} routes.`);
error.status = 404;
logger.info(`404 Error: ${req.method} ${req.url} route not found`);
logger.error(error.message);
next(error);
});
app.use((err, req, res, next) => {
res.locals.message = err.message;
res.locals.error = process.env.NODE_ENV !== 'production' ?
err :
{}; // Detailed errors can only be found in a development environment
res.status(err.status || 500);
res.render('error');
});
// 10. Export module
module.exports = app;