@reldens/server-utils 0.33.0 → 0.35.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.
- package/README.md +40 -0
- package/lib/app-server-factory.js +46 -9
- package/package.json +11 -10
package/README.md
CHANGED
|
@@ -9,6 +9,8 @@ A Node.js server toolkit providing secure application server creation, file hand
|
|
|
9
9
|
### AppServerFactory
|
|
10
10
|
- Complete Express.js server configuration with modular security
|
|
11
11
|
- HTTPS/HTTP server creation with SSL certificate management
|
|
12
|
+
- HTTP/2 support via spdy with automatic HTTP/1.1 fallback
|
|
13
|
+
- Optimized static asset caching for CSS, JS, fonts, and images
|
|
12
14
|
- SNI (Server Name Indication) support for multi-domain hosting
|
|
13
15
|
- Virtual host management with domain mapping
|
|
14
16
|
- Development mode detection with appropriate configurations
|
|
@@ -99,6 +101,40 @@ if(serverResult){
|
|
|
99
101
|
}
|
|
100
102
|
```
|
|
101
103
|
|
|
104
|
+
### HTTP/2 Server with Optimized Caching
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
let appServerFactory = new AppServerFactory();
|
|
108
|
+
let serverResult = appServerFactory.createAppServer({
|
|
109
|
+
port: 443,
|
|
110
|
+
useHttps: true,
|
|
111
|
+
useHttp2: true,
|
|
112
|
+
keyPath: '/ssl/server.key',
|
|
113
|
+
certPath: '/ssl/server.crt',
|
|
114
|
+
autoListen: true
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Cache configuration is automatic with defaults:
|
|
119
|
+
- CSS/JS: 1 year
|
|
120
|
+
- Fonts: 1 year
|
|
121
|
+
- Images: 30 days
|
|
122
|
+
|
|
123
|
+
Override cache settings if needed:
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
let appServerFactory = new AppServerFactory();
|
|
127
|
+
appServerFactory.cacheConfig = {
|
|
128
|
+
'.css': 86400,
|
|
129
|
+
'.js': 86400,
|
|
130
|
+
'.png': 604800
|
|
131
|
+
};
|
|
132
|
+
let serverResult = appServerFactory.createAppServer({
|
|
133
|
+
useHttps: true,
|
|
134
|
+
useHttp2: true
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
102
138
|
### File Operations
|
|
103
139
|
|
|
104
140
|
```javascript
|
|
@@ -193,6 +229,7 @@ appServerFactory.addDomain({
|
|
|
193
229
|
|
|
194
230
|
let serverResult = appServerFactory.createAppServer({
|
|
195
231
|
useHttps: true,
|
|
232
|
+
useHttp2: true,
|
|
196
233
|
useVirtualHosts: true,
|
|
197
234
|
keyPath: '/ssl/default.key',
|
|
198
235
|
certPath: '/ssl/default.crt',
|
|
@@ -328,6 +365,9 @@ Configurable rate limiting with development mode detection for appropriate thres
|
|
|
328
365
|
### HTTPS Support
|
|
329
366
|
Full SSL/TLS support with SNI for multi-domain hosting and automatic certificate management.
|
|
330
367
|
|
|
368
|
+
### HTTP/2 Support
|
|
369
|
+
HTTP/2 support via spdy with multiplexing for improved performance and automatic HTTP/1.1 fallback for older clients.
|
|
370
|
+
|
|
331
371
|
### Input Validation
|
|
332
372
|
Built-in validators for common input types including email, username, strong passwords, alphanumeric strings, and IP addresses.
|
|
333
373
|
|
|
@@ -61,15 +61,28 @@ class AppServerFactory
|
|
|
61
61
|
this.defaultDomain = '';
|
|
62
62
|
this.maxRequestSize = '10mb';
|
|
63
63
|
this.sanitizeOptions = {allowedTags: [], allowedAttributes: {}};
|
|
64
|
+
this.cacheConfig = {
|
|
65
|
+
'.css': 31536000,
|
|
66
|
+
'.js': 31536000,
|
|
67
|
+
'.woff': 31536000,
|
|
68
|
+
'.woff2': 31536000,
|
|
69
|
+
'.ttf': 31536000,
|
|
70
|
+
'.eot': 31536000,
|
|
71
|
+
'.jpg': 2592000,
|
|
72
|
+
'.jpeg': 2592000,
|
|
73
|
+
'.png': 2592000,
|
|
74
|
+
'.gif': 2592000,
|
|
75
|
+
'.webp': 2592000,
|
|
76
|
+
'.svg': 2592000,
|
|
77
|
+
'.ico': 2592000
|
|
78
|
+
};
|
|
64
79
|
this.staticOptions = {
|
|
65
80
|
maxAge: '1d',
|
|
81
|
+
immutable: false,
|
|
66
82
|
etag: true,
|
|
67
83
|
lastModified: true,
|
|
68
84
|
index: false,
|
|
69
|
-
setHeaders:
|
|
70
|
-
res.set('X-Content-Type-Options', 'nosniff');
|
|
71
|
-
res.set('X-Frame-Options', 'DENY');
|
|
72
|
-
}
|
|
85
|
+
setHeaders: this.buildStaticHeaders.bind(this)
|
|
73
86
|
};
|
|
74
87
|
this.isDevelopmentMode = false;
|
|
75
88
|
this.developmentDomains = [];
|
|
@@ -98,6 +111,28 @@ class AppServerFactory
|
|
|
98
111
|
};
|
|
99
112
|
}
|
|
100
113
|
|
|
114
|
+
buildStaticHeaders(res, path)
|
|
115
|
+
{
|
|
116
|
+
res.set('X-Content-Type-Options', 'nosniff');
|
|
117
|
+
res.set('X-Frame-Options', 'DENY');
|
|
118
|
+
res.set('Vary', 'Accept-Encoding');
|
|
119
|
+
let cacheMaxAge = this.getCacheConfigForPath(path);
|
|
120
|
+
if(cacheMaxAge){
|
|
121
|
+
res.set('Cache-Control', 'public, max-age='+cacheMaxAge+', immutable');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
getCacheConfigForPath(path)
|
|
126
|
+
{
|
|
127
|
+
let cacheKeys = Object.keys(this.cacheConfig);
|
|
128
|
+
for(let ext of cacheKeys){
|
|
129
|
+
if(path.endsWith(ext)){
|
|
130
|
+
return this.cacheConfig[ext];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
101
136
|
createAppServer(appServerConfig)
|
|
102
137
|
{
|
|
103
138
|
if(appServerConfig){
|
|
@@ -117,7 +152,7 @@ class AppServerFactory
|
|
|
117
152
|
try {
|
|
118
153
|
this.appServer = this.createServer();
|
|
119
154
|
} catch (error) {
|
|
120
|
-
this.error = {message: 'Server creation exception: '
|
|
155
|
+
this.error = {message: 'Server creation exception: '+error.message};
|
|
121
156
|
return false;
|
|
122
157
|
}
|
|
123
158
|
if(!this.appServer){
|
|
@@ -172,12 +207,14 @@ class AppServerFactory
|
|
|
172
207
|
if(!this.isDevelopmentMode){
|
|
173
208
|
return;
|
|
174
209
|
}
|
|
175
|
-
this.staticOptions.
|
|
210
|
+
this.staticOptions.immutable = false;
|
|
211
|
+
this.staticOptions.setHeaders = (res, path) => {
|
|
176
212
|
res.set('X-Content-Type-Options', 'nosniff');
|
|
177
213
|
res.set('X-Frame-Options', 'SAMEORIGIN');
|
|
178
214
|
res.set('Cache-Control', 'no-cache, no-store, must-revalidate');
|
|
179
215
|
res.set('Pragma', 'no-cache');
|
|
180
216
|
res.set('Expires', '0');
|
|
217
|
+
res.set('Vary', 'Accept-Encoding');
|
|
181
218
|
};
|
|
182
219
|
}
|
|
183
220
|
|
|
@@ -313,7 +350,7 @@ class AppServerFactory
|
|
|
313
350
|
req.domain = this.defaultDomain;
|
|
314
351
|
return next();
|
|
315
352
|
}
|
|
316
|
-
this.error = {message: 'Unknown domain: '
|
|
353
|
+
this.error = {message: 'Unknown domain: '+hostname};
|
|
317
354
|
return res.status(404).send('Domain not found');
|
|
318
355
|
}
|
|
319
356
|
req.domain = domain;
|
|
@@ -355,12 +392,12 @@ class AppServerFactory
|
|
|
355
392
|
{
|
|
356
393
|
let key = FileHandler.readFile(this.keyPath, 'Key');
|
|
357
394
|
if(!key){
|
|
358
|
-
this.error = {message: 'Could not read SSL key file: '
|
|
395
|
+
this.error = {message: 'Could not read SSL key file: '+this.keyPath};
|
|
359
396
|
return false;
|
|
360
397
|
}
|
|
361
398
|
let cert = FileHandler.readFile(this.certPath, 'Cert');
|
|
362
399
|
if(!cert){
|
|
363
|
-
this.error = {message: 'Could not read SSL certificate file: '
|
|
400
|
+
this.error = {message: 'Could not read SSL certificate file: '+this.certPath};
|
|
364
401
|
return false;
|
|
365
402
|
}
|
|
366
403
|
let credentials = {key, cert, passphrase: this.passphrase};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reldens/server-utils",
|
|
3
3
|
"scope": "@reldens",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.35.0",
|
|
5
5
|
"description": "Reldens - Server Utils",
|
|
6
6
|
"author": "Damian A. Pastorini",
|
|
7
7
|
"license": "MIT",
|
|
@@ -17,17 +17,18 @@
|
|
|
17
17
|
"utils",
|
|
18
18
|
"shortcuts",
|
|
19
19
|
"system",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
20
|
+
"server",
|
|
21
|
+
"http",
|
|
22
|
+
"https",
|
|
23
23
|
"dwd",
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
24
|
+
"http2",
|
|
25
|
+
"file",
|
|
26
|
+
"encrypt",
|
|
27
|
+
"uploader",
|
|
28
|
+
"upload",
|
|
29
|
+
"cors",
|
|
27
30
|
"nodejs",
|
|
28
|
-
"
|
|
29
|
-
"multiplayer",
|
|
30
|
-
"rol",
|
|
31
|
+
"protocol",
|
|
31
32
|
"platform",
|
|
32
33
|
"framework"
|
|
33
34
|
],
|