-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
143 lines (124 loc) · 4.79 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
135
136
137
138
139
140
141
142
143
// Import dependencies
require('dotenv').config();
const express = require('express');
const rateLimit = require('express-rate-limit');
const helmet = require('helmet');
const cors = require('cors');
const { retryApiCall, accessSecret } = require('./utils/apiutils.js');
const { closeConnection } = require('./database/database.js'); // Import closeConnection function
const router = require('./routes/markers.js');
const fs = require('fs');
const https = require('https');
const path = require('path');
const jwt = require('jsonwebtoken')
async function startServer() {
const app = express();
app.use(helmet());
// Content Security Policy
app.use(
helmet.contentSecurityPolicy({
directives: {
'default-src': ["'self'"],
'script-src': ["'self'", "https://api.mapbox.com"], // Allow Mapbox GL script
'style-src': ["'self'", "'unsafe-inline'", "https://api.mapbox.com"], // Allow Mapbox GL stylesheet
'img-src': ["'self'", 'data:', 'blob:'], // Allow images from self, data URIs, and blob URIs
'connect-src': [
"'self'",
"https://optimism.io",
"https://*.tiles.mapbox.com",
"https://api.mapbox.com",
"https://events.mapbox.com",
"https://static.optimism.io",
"https://dune.com",
"http://localhost:3000",
"https://www.foamcaster.xyz",
"https://foamcaster.xyz"
],
'worker-src': ["'self'", 'blob:'],
'child-src': ["'self'", 'blob:']
}
})
);
// Rate Limiting
const limiterForRootEndpoint = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP, please try again later.',
});
app.use('/', limiterForRootEndpoint);
app.set('trust proxy', 1);
let jwtSecretToken;
try{
jwtSecretToken = await retryApiCall(() => accessSecret('JWT_SECRET'))
} catch (error) {
console.error('Failed to access JWT secret token:', error);
process.exit(1); // Exit process if the token cannot be retrieved
}
let mapboxToken;
try {
mapboxToken = await retryApiCall(() => accessSecret('MAPBOX_API'));
} catch (error) {
console.error('Failed to access Mapbox token:', error);
process.exit(1); // Exit process if the token cannot be retrieved
}
// Middleware setup
const allowedOrigins = [
'http://localhost:3000',
'https://www.foamcaster.xyz',
'https://foamcaster.xyz'
];
app.use(cors({
origin: function (origin, callback) {
// allow requests with no origin (like mobile apps or curl requests)
if (!origin) return callback(null, true);
if (allowedOrigins.indexOf(origin) === -1) {
const msg = 'The CORS policy for this site does not allow access from the specified Origin.';
return callback(new Error(msg), false);
}
return callback(null, true);
}
}));
app.use(express.static(path.join(__dirname, 'public')));
app.get('/token', (req, res) => {
const authHeader = req.headers['authorization'];
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(403).send('Forbidden');
}
const token = authHeader.split(' ')[1];
jwt.verify(token, jwtSecretToken, (err) => {
if (err) {
return res.status(403).send('Forbidden');
}
res.json({ token: mapboxToken });
});
});
app.use('/api', router);
app.use((err, req, res, next) => {
console.error('Error occurred:', err.message);
res.status(500).send('Internal Server Error');
});
const PORT = process.env.PORT || 3000;
// Start the server and assign it to a variable
const server = app.listen(PORT, () => {
console.log(`Node.js server is running on http://localhost:${PORT}`);
});
// Handle process termination and cleanup
process.on('SIGINT', async () => {
console.log('Received SIGINT. Closing MongoDB connection...');
await closeConnection();
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});
process.on('SIGTERM', async () => {
console.log('Received SIGTERM. Closing MongoDB connection...');
await closeConnection();
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});
}
// Call the function to start the server
startServer();