ultimate-express 1.1.0 → 1.1.2

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/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "ultimate-express",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "The Ultimate Express. Fastest http server with full Express compatibility, based on uWebSockets.",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
7
7
  "test": "node tests/index.js"
8
8
  },
9
+ "engines": {
10
+ "node": ">=16"
11
+ },
9
12
  "files": [
10
13
  "src",
11
14
  "EXPRESS_LICENSE"
@@ -65,7 +65,7 @@ class Application extends Router {
65
65
  for(const key in defaultSettings) {
66
66
  if(typeof this.settings[key] === 'undefined') {
67
67
  if(typeof defaultSettings[key] === 'function') {
68
- this.settings[key] = defaultSettings[key]();
68
+ this.settings[key] = defaultSettings[key](this);
69
69
  } else {
70
70
  this.settings[key] = defaultSettings[key];
71
71
  }
@@ -75,19 +75,23 @@ class Application extends Router {
75
75
  this.set('views', path.resolve('views'));
76
76
  }
77
77
 
78
+ createWorkerTask(resolve, reject) {
79
+ const key = taskKey++;
80
+ workerTasks[key] = { resolve, reject };
81
+ if(key > 1000000) {
82
+ taskKey = 0;
83
+ }
84
+ return key;
85
+ }
86
+
78
87
  readFileWithWorker(path) {
79
88
  return new Promise((resolve, reject) => {
80
89
  const worker = this.workers[Math.floor(Math.random() * this.workers.length)];
81
- const key = taskKey++;
90
+ const key = this.createWorkerTask(resolve, reject);
82
91
  worker.postMessage({ key, type: 'readFile', path });
83
- workerTasks[key] = { resolve, reject };
84
- if(key > 1000000) {
85
- taskKey = 0;
86
- }
87
92
  });
88
93
  }
89
94
 
90
-
91
95
  set(key, value) {
92
96
  if(key === 'trust proxy') {
93
97
  if(!value) {
package/src/response.js CHANGED
@@ -96,7 +96,7 @@ module.exports = class Response extends Writable {
96
96
  this._res.writeHeader(header, this.headers[header]);
97
97
  }
98
98
  if(!this.headers['content-type']) {
99
- this._res.writeHeader('content-type', 'text/html');
99
+ this._res.writeHeader('content-type', 'text/html' + (typeof chunk === 'string' ? `; charset=utf-8` : ''));
100
100
  }
101
101
  this.headersSent = true;
102
102
  }
@@ -139,7 +139,7 @@ module.exports = class Response extends Writable {
139
139
  if(!this.headersSent) {
140
140
  const etagFn = this.app.get('etag fn');
141
141
  if(data && !this.headers['etag'] && etagFn && !this.req.noEtag) {
142
- this.set('etag', etagFn(data, this.req));
142
+ this.set('etag', etagFn(data));
143
143
  }
144
144
  if(this.req.fresh) {
145
145
  if(!this.headersSent) {
@@ -157,13 +157,16 @@ module.exports = class Response extends Writable {
157
157
  this._res.writeHeader(header, this.headers[header]);
158
158
  }
159
159
  if(!this.headers['content-type']) {
160
- this._res.writeHeader('content-type', 'text/html');
160
+ this._res.writeHeader('content-type', 'text/html' + (typeof data === 'string' ? `; charset=utf-8` : ''));
161
161
  }
162
162
  this.headersSent = true;
163
163
  }
164
164
  if(!data && this.headers['content-length']) {
165
165
  this._res.endWithoutBody(this.headers['content-length'].toString());
166
166
  } else {
167
+ if(data instanceof Buffer) {
168
+ data = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
169
+ }
167
170
  if(this.req.method === 'HEAD') {
168
171
  const length = Buffer.byteLength(data ?? '');
169
172
  this._res.endWithoutBody(length.toString());
@@ -180,14 +183,10 @@ module.exports = class Response extends Writable {
180
183
  if(this.headersSent) {
181
184
  throw new Error('Can\'t write body: Response was already sent');
182
185
  }
183
- if(Buffer.isBuffer(body)) {
184
- body = body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength);
185
- } else if(body === null || body === undefined) {
186
+ if(body === null || body === undefined) {
186
187
  body = '';
187
- } else if(typeof body === 'object') {
188
- if(!(body instanceof ArrayBuffer)) {
189
- return this.json(body);
190
- }
188
+ } else if(typeof body === 'object' && !Buffer.isBuffer(body)) {
189
+ return this.json(body);
191
190
  } else if(typeof body === 'number') {
192
191
  if(arguments[1]) {
193
192
  deprecated('res.send(status, body)', 'res.status(status).send(body)');
@@ -199,6 +198,12 @@ module.exports = class Response extends Writable {
199
198
  } else {
200
199
  body = String(body);
201
200
  }
201
+ if(typeof body === 'string') {
202
+ const contentType = this.headers['content-type'];
203
+ if(contentType && !contentType.includes(';')) {
204
+ this.headers['content-type'] += '; charset=utf-8';
205
+ }
206
+ }
202
207
  this.writeHead(this.statusCode);
203
208
  return this.end(body);
204
209
  }
@@ -390,7 +395,7 @@ module.exports = class Response extends Writable {
390
395
  if(this._res.aborted) {
391
396
  return;
392
397
  }
393
- this.send(data);
398
+ this.end(data);
394
399
  if(callback) callback();
395
400
  }).catch((err) => {
396
401
  if(callback) callback(err);
@@ -446,10 +451,15 @@ module.exports = class Response extends Writable {
446
451
  this.set(header, field[header]);
447
452
  }
448
453
  } else {
454
+ field = field.toLowerCase();
449
455
  if(field === 'set-cookie' && Array.isArray(value)) {
450
456
  value = value.join('; ');
457
+ } else if(field === 'content-type') {
458
+ if(value.startsWith('text/') || value === 'application/json' || value === 'application/javascript') {
459
+ value += '; charset=utf-8';
460
+ }
451
461
  }
452
- this.headers[field.toLowerCase()] = String(value);
462
+ this.headers[field] = String(value);
453
463
  }
454
464
  return this;
455
465
  }
@@ -557,7 +567,7 @@ module.exports = class Response extends Writable {
557
567
  }
558
568
  json(body) {
559
569
  if(!this.get('Content-Type')) {
560
- this.set('Content-Type', 'application/json');
570
+ this.set('Content-Type', 'application/json; charset=utf-8');
561
571
  }
562
572
  const escape = this.app.get('json escape');
563
573
  const replacer = this.app.get('json replacer');
@@ -569,7 +579,7 @@ module.exports = class Response extends Writable {
569
579
  let body = stringify(object, this.app.get('json replacer'), this.app.get('json spaces'), this.app.get('json escape'));
570
580
 
571
581
  if(!this.get('Content-Type')) {
572
- this.set('Content-Type', 'application/javascript');
582
+ this.set('Content-Type', 'application/javascript; charset=utf-8');
573
583
  this.set('X-Content-Type-Options', 'nosniff');
574
584
  }
575
585
 
@@ -578,7 +588,7 @@ module.exports = class Response extends Writable {
578
588
  }
579
589
 
580
590
  if(typeof callback === 'string' && callback.length !== 0) {
581
- this.set('Content-Type', 'application/javascript');
591
+ this.set('Content-Type', 'application/javascript; charset=utf-8');
582
592
  this.set('X-Content-Type-Options', 'nosniff');
583
593
  callback = callback.replace(/[^\[\]\w$.]/g, '');
584
594
 
@@ -614,14 +624,17 @@ module.exports = class Response extends Writable {
614
624
  }
615
625
  this.location(url);
616
626
  this.status(status);
617
- this.set('Content-Type', 'text/plain');
627
+ this.set('Content-Type', 'text/plain; charset=utf-8');
618
628
  return this.send(`${statuses.message[status] ?? status}. Redirecting to ${url}`);
619
629
  }
620
630
 
621
631
  type(type) {
622
- const ct = type.indexOf('/') === -1
632
+ let ct = type.indexOf('/') === -1
623
633
  ? (mime.contentType(type) || 'application/octet-stream')
624
634
  : type;
635
+ if(ct.startsWith('text/') || ct === 'application/json' || ct === 'application/javascript') {
636
+ ct += '; charset=UTF-8';
637
+ }
625
638
  return this.set('Content-Type', ct);
626
639
  }
627
640
  contentType(type) {
@@ -658,7 +671,7 @@ function pipeStreamOverResponse(res, readStream, totalSize, callback) {
658
671
  res._res.writeHeader(header, res.headers[header]);
659
672
  }
660
673
  if(!res.headers['content-type']) {
661
- res._res.writeHeader('content-type', 'text/html');
674
+ res._res.writeHeader('content-type', 'text/html; charset=utf-8');
662
675
  }
663
676
  res.headersSent = true;
664
677
  }