ultimate-express 1.0.7 → 1.0.9

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 CHANGED
@@ -93,7 +93,7 @@ Optimized routes can be up to 10 times faster than normal routes, as they're usi
93
93
 
94
94
  3. Do not set `body methods` to read body of requests with GET method or other methods that don't need a body. Reading body makes server about 10k req/sec slower.
95
95
 
96
- 4. By default, µExpress creates 1 worker thread for reading files (or 0 if your CPU has only 1 core). You can change this number by setting `fsThreads` to a different number in `express()`, or set to 0 to disable thread pool for file reading (`express({ fsThreads: 0 })`). Threads are shared between all express() instances, with largest fsThreads number being used. Using more threads will not necessarily improve performance. Sometimes not using threads at all is faster, please [test](https://github.com/wg/wrk/) both options.
96
+ 4. By default, µExpress creates 1 (or 0 if your CPU has only 1 core) child thread to improve performance of reading files and computing hashes for etag. You can change this number by setting `threads` to a different number in `express()`, or set to 0 to disable thread pool (`express({ threads: 0 })`). Threads are shared between all express() instances, with largest `threads` number being used. Using more threads will not necessarily improve performance. Sometimes not using threads at all is faster, please [test](https://github.com/wg/wrk/) both options.
97
97
 
98
98
  ## Compatibility
99
99
 
@@ -110,6 +110,7 @@ In general, basically all features and options are supported. Use [Express 4.x d
110
110
  - ✅ express.json()
111
111
  - ✅ express.urlencoded()
112
112
  - ✅ express.static()
113
+ - - Additionally you can pass `options.ifModifiedSince` to support If-Modified-Since header (this header is not supported in normal Express, but is supported in µExpress)
113
114
  - ✅ express.text()
114
115
  - ✅ express.raw()
115
116
  - 🚧 express.request (this is not a constructor but a prototype for replacing methods)
@@ -229,7 +230,7 @@ In general, basically all features and options are supported. Use [Express 4.x d
229
230
  - - ✅ Range header
230
231
  - - ✅ Setting ETag header
231
232
  - - ✅ If-Match header
232
- - - ✅ If-Modified-Since header
233
+ - - ✅ If-Modified-Since header (with `options.ifModifiedSince` option)
233
234
  - - ✅ If-Unmodified-Since header
234
235
  - - ✅ If-Range header
235
236
  - ✅ res.sendStatus()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultimate-express",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
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": {
@@ -10,25 +10,25 @@ const { Worker } = require("worker_threads");
10
10
 
11
11
  const cpuCount = os.cpus().length;
12
12
 
13
- let fsWorkers = [];
14
- let fsKey = 0;
15
- const fsCache = {};
13
+ let workers = [];
14
+ let taskKey = 0;
15
+ const workerTasks = {};
16
16
 
17
- function createFsWorker() {
18
- const fsWorker = new Worker(path.join(__dirname, 'workers/fs.js'));
19
- fsWorkers.push(fsWorker);
17
+ function createWorker() {
18
+ const worker = new Worker(path.join(__dirname, 'worker.js'));
19
+ workers.push(worker);
20
20
 
21
- fsWorker.on('message', (message) => {
21
+ worker.on('message', (message) => {
22
22
  if(message.err) {
23
- fsCache[message.key].reject(new Error(message.err));
23
+ workerTasks[message.key].reject(new Error(message.err));
24
24
  } else {
25
- fsCache[message.key].resolve(message.data);
25
+ workerTasks[message.key].resolve(message.data);
26
26
  }
27
- delete fsCache[message.key];
27
+ delete workerTasks[message.key];
28
28
  });
29
- fsWorker.unref();
29
+ worker.unref();
30
30
 
31
- return fsWorker;
31
+ return worker;
32
32
  }
33
33
 
34
34
  class Application extends Router {
@@ -37,8 +37,8 @@ class Application extends Router {
37
37
  if(!settings?.uwsOptions) {
38
38
  settings.uwsOptions = {};
39
39
  }
40
- if(typeof settings.fsThreads !== 'number') {
41
- settings.fsThreads = cpuCount > 1 ? 1 : 0;
40
+ if(typeof settings.threads !== 'number') {
41
+ settings.threads = cpuCount > 1 ? 1 : 0;
42
42
  }
43
43
  if(settings.uwsOptions.key_file_name && settings.uwsOptions.cert_file_name) {
44
44
  this.uwsApp = uWS.SSLApp(settings.uwsOptions);
@@ -53,12 +53,12 @@ class Application extends Router {
53
53
  settings: this.settings
54
54
  };
55
55
  this.listenCalled = false;
56
- this.fsWorkers = [];
57
- for(let i = 0; i < settings.fsThreads; i++) {
58
- if(fsWorkers[i]) {
59
- this.fsWorkers[i] = fsWorkers[i];
56
+ this.workers = [];
57
+ for(let i = 0; i < settings.threads; i++) {
58
+ if(workers[i]) {
59
+ this.workers[i] = workers[i];
60
60
  } else {
61
- this.fsWorkers[i] = createFsWorker();
61
+ this.workers[i] = createWorker();
62
62
  }
63
63
  }
64
64
  this.port = undefined;
@@ -77,12 +77,12 @@ class Application extends Router {
77
77
 
78
78
  readFileWithWorker(path) {
79
79
  return new Promise((resolve, reject) => {
80
- const fsWorker = this.fsWorkers[Math.floor(Math.random() * this.fsWorkers.length)];
81
- const key = fsKey++;
82
- fsWorker.postMessage({ key, type: 'readFile', path });
83
- fsCache[key] = { resolve, reject };
80
+ const worker = this.workers[Math.floor(Math.random() * this.workers.length)];
81
+ const key = taskKey++;
82
+ worker.postMessage({ key, type: 'readFile', path });
83
+ workerTasks[key] = { resolve, reject };
84
84
  if(key > 1000000) {
85
- fsKey = 0;
85
+ taskKey = 0;
86
86
  }
87
87
  });
88
88
  }
@@ -20,7 +20,7 @@ function static(root, options) {
20
20
 
21
21
  return (req, res, next) => {
22
22
  const iq = req.url.indexOf('?');
23
- let url = iq !== -1 ? req.url.substring(0, iq) : req.url;
23
+ let url = decodeURIComponent(iq !== -1 ? req.url.substring(0, iq) : req.url);
24
24
  let _path = url;
25
25
  let fullpath = path.resolve(path.join(options.root, url));
26
26
  if(options.root && !fullpath.startsWith(path.resolve(options.root))) {
package/src/response.js CHANGED
@@ -333,16 +333,18 @@ module.exports = class Response extends Writable {
333
333
  }
334
334
 
335
335
  // if-modified-since
336
- let modifiedSince = this.req.headers['if-modified-since'];
337
- let lastModified = this.headers['last-modified'];
338
- if(options.lastModified && lastModified && modifiedSince) {
339
- modifiedSince = parseHttpDate(modifiedSince);
340
- lastModified = parseHttpDate(lastModified);
341
-
342
- if(!isNaN(lastModified) && !isNaN(modifiedSince) && lastModified <= modifiedSince) {
343
- this.status(304);
344
- return this.end();
345
- };
336
+ if(options.ifModifiedSince) {
337
+ let modifiedSince = this.req.headers['if-modified-since'];
338
+ let lastModified = this.headers['last-modified'];
339
+ if(options.lastModified && lastModified && modifiedSince) {
340
+ modifiedSince = parseHttpDate(modifiedSince);
341
+ lastModified = parseHttpDate(lastModified);
342
+
343
+ if(!isNaN(lastModified) && !isNaN(modifiedSince) && lastModified <= modifiedSince) {
344
+ this.status(304);
345
+ return this.end();
346
+ };
347
+ }
346
348
  }
347
349
 
348
350
  // range requests
@@ -377,7 +379,7 @@ module.exports = class Response extends Writable {
377
379
  }
378
380
 
379
381
  // serve smaller files using workers
380
- if(this.app.fsWorkers.length && stat.size < 1024 * 1024 && !ranged) {
382
+ if(this.app.workers.length && stat.size < 1024 * 1024 && !ranged) {
381
383
  this.app.readFileWithWorker(fullpath).then((data) => {
382
384
  if(this._res.aborted) {
383
385
  return;
File without changes