@reldens/server-utils 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,7 +47,13 @@ class AppServerFactory
47
47
  this.corsOrigin = String(process.env.RELDENS_CORS_ORIGIN || '*');
48
48
  this.corsMethods = String(process.env.RELDENS_CORS_METHODS || 'GET,POST').split(',');
49
49
  this.corsHeaders = String(process.env.RELDENS_CORS_HEADERS || 'Content-Type,Authorization').split(',');
50
- this.errorMessage = '';
50
+ this.tooManyRequestsMessage = String(
51
+ process.env.RELDENS_TOO_MANY_REQUESTS_MESSAGE || 'Too many requests, please try again later.'
52
+ );
53
+ this.error = {};
54
+ this.processErrorResponse = function(status, message, req, res) {
55
+ return { status, message, handled: false };
56
+ };
51
57
  }
52
58
 
53
59
  createAppServer(appServerConfig)
@@ -72,7 +78,7 @@ class AppServerFactory
72
78
  max: this.maxRequests,
73
79
  standardHeaders: true,
74
80
  legacyHeaders: false,
75
- message: 'Too many requests from this IP, please try again later'
81
+ message: this.tooManyRequestsMessage
76
82
  };
77
83
  if(this.applyKeyGenerator){
78
84
  limiterParams.keyGenerator = function(req){
@@ -168,13 +174,21 @@ class AppServerFactory
168
174
  app.get('/', async (req, res, next) => {
169
175
  if('/' === req._parsedUrl.pathname){
170
176
  if('function' !== typeof homePageLoadCallback){
171
- return res.send('Homepage contents could not be loaded.');
177
+ let result = this.processErrorResponse(500, 'Homepage contents could not be loaded.', req, res);
178
+ if(result.handled){
179
+ return;
180
+ }
181
+ return res.status(result.status).send(result.message);
172
182
  }
173
183
  try {
174
184
  return res.send(await homePageLoadCallback(req));
175
185
  } catch(error){
176
- this.errorMessage = 'Error loading homepage.';
177
- return res.status(500).send('Error loading homepage.');
186
+ this.error = {message: 'Error loading homepage.', error};
187
+ let result = this.processErrorResponse(500, 'Error loading homepage.', req, res);
188
+ if(result.handled){
189
+ return;
190
+ }
191
+ return res.status(result.status).send(result.message);
178
192
  }
179
193
  }
180
194
  next();
@@ -184,7 +198,7 @@ class AppServerFactory
184
198
  async serveStatics(app, statics)
185
199
  {
186
200
  if(!FileHandler.isValidPath(statics)){
187
- this.errorMessage = 'Invalid statics path.';
201
+ this.error = {message: 'Invalid statics path.'};
188
202
  return;
189
203
  }
190
204
  let staticOptions = {
@@ -202,7 +216,7 @@ class AppServerFactory
202
216
  async serveStaticsPath(app, staticsPath, statics)
203
217
  {
204
218
  if(!FileHandler.isValidPath(staticsPath) || !FileHandler.isValidPath(statics)){
205
- this.errorMessage = 'Invalid statics path to be served.';
219
+ this.error = {message: 'Invalid statics path to be served.'};
206
220
  return;
207
221
  }
208
222
  let staticOptions = {
@@ -18,6 +18,9 @@ class UploaderFactory
18
18
  this.fileLimit = props.fileLimit || 0;
19
19
  this.allowedExtensions = props.allowedExtensions;
20
20
  this.applySecureFileNames = props.applySecureFileNames;
21
+ this.processErrorResponse = props.processErrorResponse || function(status, message, req, res) {
22
+ return { status, message, handled: false };
23
+ };
21
24
  }
22
25
 
23
26
  createUploader(fields, buckets, allowedFileTypes)
@@ -35,16 +38,18 @@ class UploaderFactory
35
38
  cb(null, dest);
36
39
  }
37
40
  };
38
- if(this.applySecureFileNames){
39
- diskStorageConfiguration['filename'] = (req, file, cb) => {
40
- let secureFilename = FileHandler.generateSecureFilename(file.originalname);
41
- if(!req.fileNameMapping){
42
- req.fileNameMapping = {};
43
- }
44
- req.fileNameMapping[secureFilename] = file.originalname;
45
- cb(null, secureFilename);
46
- };
47
- }
41
+ diskStorageConfiguration['filename'] = (req, file, cb) => {
42
+ if(!this.applySecureFileNames) {
43
+ cb(null, file.originalname);
44
+ return;
45
+ }
46
+ let secureFilename = FileHandler.generateSecureFilename(file.originalname);
47
+ if(!req.fileNameMapping){
48
+ req.fileNameMapping = {};
49
+ }
50
+ req.fileNameMapping[secureFilename] = file.originalname;
51
+ cb(null, secureFilename);
52
+ };
48
53
  let storage = multer.diskStorage(diskStorageConfiguration);
49
54
  let limits = {
50
55
  fileSize: this.maxFileSize
@@ -64,14 +69,30 @@ class UploaderFactory
64
69
  if(err){
65
70
  if(err instanceof multer.MulterError){
66
71
  if(err.code === 'LIMIT_FILE_SIZE'){
67
- return res.status(413).send('File too large');
72
+ let result = this.processErrorResponse(413, 'File too large.', req, res);
73
+ if(result.handled){
74
+ return;
75
+ }
76
+ return res.status(result.status).send(result.message);
68
77
  }
69
78
  if(err.code === 'LIMIT_FILE_COUNT'){
70
- return res.status(413).send('Too many files');
79
+ let result = this.processErrorResponse(413, 'Too many files.', req, res);
80
+ if(result.handled){
81
+ return;
82
+ }
83
+ return res.status(result.status).send(result.message);
84
+ }
85
+ let result = this.processErrorResponse(400, 'File upload error: ' + err.message, req, res);
86
+ if(result.handled){
87
+ return;
71
88
  }
72
- return res.status(400).send('File upload error: ' + err.message);
89
+ return res.status(result.status).send(result.message);
90
+ }
91
+ let result = this.processErrorResponse(500, 'Server error during file upload.', req, res);
92
+ if(result.handled){
93
+ return;
73
94
  }
74
- return res.status(500).send('Server error during file upload');
95
+ return res.status(result.status).send(result.message);
75
96
  }
76
97
  if(!req.files){
77
98
  return next();
@@ -83,15 +104,23 @@ class UploaderFactory
83
104
  if(FileHandler.exists(file.path)){
84
105
  FileHandler.remove(file.path);
85
106
  }
86
- return res.status(415).send('File contents do not match declared type');
107
+ let result = this.processErrorResponse(415, 'File contents do not match declared type.', req, res);
108
+ if(result.handled){
109
+ return;
110
+ }
111
+ return res.status(result.status).send(result.message);
87
112
  }
88
113
  }
89
114
  }
90
115
  next();
91
116
  } catch(error){
92
- console.error('File validation error:', error);
117
+ this.error = {message: 'File validation error.', error};
93
118
  this.cleanupFiles(req.files);
94
- return res.status(500).send('Error processing uploaded files');
119
+ let result = this.processErrorResponse(500, 'Error processing uploaded files.', req, res);
120
+ if(result.handled){
121
+ return;
122
+ }
123
+ return res.status(result.status).send(result.message);
95
124
  }
96
125
  });
97
126
  };
@@ -116,11 +145,11 @@ class UploaderFactory
116
145
  this.error = {message: 'Field name is invalid'};
117
146
  return false;
118
147
  }
119
- if(!Object.prototype.hasOwnProperty.call(buckets, field.name)){
148
+ if(!buckets[field.name]){
120
149
  this.error = {message: `Missing bucket for field: ${field.name}`};
121
150
  return false;
122
151
  }
123
- if(!Object.prototype.hasOwnProperty.call(allowedFileTypes, field.name)){
152
+ if(!allowedFileTypes[field.name]){
124
153
  this.error = {message: `Missing allowedFileType for field: ${field.name}`};
125
154
  return false;
126
155
  }
@@ -156,11 +185,12 @@ class UploaderFactory
156
185
  {
157
186
  try {
158
187
  if(!FileHandler.isFile(file.path)){
188
+ this.error = {message: 'File path must be provided.', file};
159
189
  return false;
160
190
  }
161
191
  return FileHandler.validateFileType(file.path, allowedFileType, this.allowedExtensions, this.maxFileSize);
162
- } catch(err){
163
- console.error('Error validating file contents:', err);
192
+ } catch(error){
193
+ this.error = {message: 'Error validating file contents.', error};
164
194
  return false;
165
195
  }
166
196
  }
@@ -187,8 +217,8 @@ class UploaderFactory
187
217
  if(FileHandler.exists(file.path)){
188
218
  FileHandler.remove(file.path);
189
219
  }
190
- } catch(err){
191
- console.error('Error cleaning up file:', file.path, err);
220
+ } catch(error){
221
+ this.error = {message: 'Error cleaning up file.', error};
192
222
  }
193
223
  }
194
224
  }
package/package.json CHANGED
@@ -1,47 +1,47 @@
1
- {
2
- "name": "@reldens/server-utils",
3
- "scope": "@reldens",
4
- "version": "0.9.0",
5
- "description": "Reldens - Server Utils",
6
- "author": "Damian A. Pastorini",
7
- "license": "MIT",
8
- "homepage": "https://github.com/damian-pastorini/reldens-server-utils",
9
- "source": true,
10
- "main": "index.js",
11
- "repository": {
12
- "type": "git",
13
- "url": "https://github.com/damian-pastorini/reldens-server-utils.git"
14
- },
15
- "keywords": [
16
- "reldens",
17
- "utils",
18
- "shortcuts",
19
- "system",
20
- "game",
21
- "mmorpg",
22
- "rpg",
23
- "dwd",
24
- "colyseus",
25
- "phaser",
26
- "parcel",
27
- "nodejs",
28
- "mmo",
29
- "multiplayer",
30
- "rol",
31
- "platform",
32
- "framework"
33
- ],
34
- "bugs": {
35
- "url": "https://github.com/damian-pastorini/reldens-server-utils/issues"
36
- },
37
- "dependencies": {
38
- "body-parser": "2.2.0",
39
- "cors": "2.8.5",
40
- "express": "4.21.2",
41
- "express-rate-limit": "7.5.0",
42
- "express-session": "1.18.1",
43
- "helmet": "8.1.0",
44
- "multer": "^1.4.5-lts.2",
45
- "xss-clean": "^0.1.4"
46
- }
47
- }
1
+ {
2
+ "name": "@reldens/server-utils",
3
+ "scope": "@reldens",
4
+ "version": "0.11.0",
5
+ "description": "Reldens - Server Utils",
6
+ "author": "Damian A. Pastorini",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/damian-pastorini/reldens-server-utils",
9
+ "source": true,
10
+ "main": "index.js",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/damian-pastorini/reldens-server-utils.git"
14
+ },
15
+ "keywords": [
16
+ "reldens",
17
+ "utils",
18
+ "shortcuts",
19
+ "system",
20
+ "game",
21
+ "mmorpg",
22
+ "rpg",
23
+ "dwd",
24
+ "colyseus",
25
+ "phaser",
26
+ "parcel",
27
+ "nodejs",
28
+ "mmo",
29
+ "multiplayer",
30
+ "rol",
31
+ "platform",
32
+ "framework"
33
+ ],
34
+ "bugs": {
35
+ "url": "https://github.com/damian-pastorini/reldens-server-utils/issues"
36
+ },
37
+ "dependencies": {
38
+ "body-parser": "2.2.0",
39
+ "cors": "2.8.5",
40
+ "express": "4.21.2",
41
+ "express-rate-limit": "7.5.0",
42
+ "express-session": "1.18.1",
43
+ "helmet": "8.1.0",
44
+ "multer": "^1.4.5-lts.2",
45
+ "xss-clean": "0.1.4"
46
+ }
47
+ }