浏览代码

[uWebsockets.js] Upgrade to v20.31.0 (#8332)

* [uWebsockets.js] Upgrade to v20.31.0

* [uWebsockets.js] Upgrade to v20.31.0

* [uWebsockets.js] Refactor(server.js): escape unsafe html using regex

* [uWebsockets.js] Refactor(postgres.js): change database driver from pg to postgres.js

* [uWebsockets.js] Refactor(postgres.js): fix warn invalid date header

* [uwebsockets.js] Update README.md

* [uWebsockets.js] Refactor(server.js): improve fortunes

* [uWebsockets.js] Refactor(server.js): update fortunes

* [uWebsockets.js] Upgrade to v20.31.0

* [uWebsockets.js] Refactor server.js, utils.js, and postgres.js
Imam Fahrur Rofi 2 年之前
父节点
当前提交
aaa328ac46

+ 1 - 1
frameworks/JavaScript/uwebsockets.js/README.md

@@ -9,7 +9,7 @@ uWebSockets is a web server written in C/C++ (https://github.com/uNetworking/uWe
 The tests were run with:
 
 - [uWebSockets.js](https://github.com/uNetworking/uWebSockets.js/)
-- [pg](https://github.com/brianc/node-postgres)
+- [postgres](https://github.com/porsager/postgres/)
 
 ## Database
 

+ 12 - 273
frameworks/JavaScript/uwebsockets.js/package-lock.json

@@ -1,7 +1,7 @@
 {
   "name": "uwebsockets.js",
   "version": "0.0.1",
-  "lockfileVersion": 2,
+  "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
@@ -9,283 +9,22 @@
       "version": "0.0.1",
       "license": "MIT",
       "dependencies": {
-        "html-escaper": "^3.0.3",
-        "pg": "^8.11.0",
-        "pg-pool": "^3.6.0",
-        "uWebSockets.js": "uNetworking/uWebSockets.js#v20.30.0"
+        "postgres": "^3.3.5",
+        "uWebSockets.js": "uNetworking/uWebSockets.js#v20.31.0"
       }
     },
-    "node_modules/buffer-writer": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
-      "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/html-escaper": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
-      "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="
-    },
-    "node_modules/packet-reader": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
-      "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
-    },
-    "node_modules/pg": {
-      "version": "8.11.0",
-      "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.0.tgz",
-      "integrity": "sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==",
-      "dependencies": {
-        "buffer-writer": "2.0.0",
-        "packet-reader": "1.0.0",
-        "pg-connection-string": "^2.6.0",
-        "pg-pool": "^3.6.0",
-        "pg-protocol": "^1.6.0",
-        "pg-types": "^2.1.0",
-        "pgpass": "1.x"
-      },
-      "engines": {
-        "node": ">= 8.0.0"
-      },
-      "optionalDependencies": {
-        "pg-cloudflare": "^1.1.0"
-      },
-      "peerDependencies": {
-        "pg-native": ">=3.0.1"
-      },
-      "peerDependenciesMeta": {
-        "pg-native": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/pg-cloudflare": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.0.tgz",
-      "integrity": "sha512-tGM8/s6frwuAIyRcJ6nWcIvd3+3NmUKIs6OjviIm1HPPFEt5MzQDOTBQyhPWg/m0kCl95M6gA1JaIXtS8KovOA==",
-      "optional": true
-    },
-    "node_modules/pg-connection-string": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.0.tgz",
-      "integrity": "sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg=="
-    },
-    "node_modules/pg-int8": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
-      "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
-      "engines": {
-        "node": ">=4.0.0"
-      }
-    },
-    "node_modules/pg-pool": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.0.tgz",
-      "integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==",
-      "peerDependencies": {
-        "pg": ">=8.0"
-      }
-    },
-    "node_modules/pg-protocol": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz",
-      "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q=="
-    },
-    "node_modules/pg-types": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
-      "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
-      "dependencies": {
-        "pg-int8": "1.0.1",
-        "postgres-array": "~2.0.0",
-        "postgres-bytea": "~1.0.0",
-        "postgres-date": "~1.0.4",
-        "postgres-interval": "^1.1.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/pgpass": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
-      "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
-      "dependencies": {
-        "split2": "^4.1.0"
-      }
-    },
-    "node_modules/postgres-array": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
-      "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/postgres-bytea": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
-      "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/postgres-date": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
-      "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/postgres-interval": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
-      "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
-      "dependencies": {
-        "xtend": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/split2": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
-      "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
-      "engines": {
-        "node": ">= 10.x"
+    "node_modules/postgres": {
+      "version": "3.3.5",
+      "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.3.5.tgz",
+      "integrity": "sha512-+JD93VELV9gHkqpV5gdL5/70HdGtEw4/XE1S4BC8f1mcPmdib3K5XsKVbnR1XcAyC41zOnifJ+9YRKxdIsXiUw==",
+      "funding": {
+        "type": "individual",
+        "url": "https://github.com/sponsors/porsager"
       }
     },
     "node_modules/uWebSockets.js": {
-      "version": "20.30.0",
-      "resolved": "git+ssh://[email protected]/uNetworking/uWebSockets.js.git#d39d4181daf5b670d44cbc1b18f8c28c85fd4142"
-    },
-    "node_modules/xtend": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
-      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
-      "engines": {
-        "node": ">=0.4"
-      }
-    }
-  },
-  "dependencies": {
-    "buffer-writer": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
-      "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
-    },
-    "html-escaper": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
-      "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="
-    },
-    "packet-reader": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
-      "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
-    },
-    "pg": {
-      "version": "8.11.0",
-      "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.0.tgz",
-      "integrity": "sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==",
-      "requires": {
-        "buffer-writer": "2.0.0",
-        "packet-reader": "1.0.0",
-        "pg-cloudflare": "^1.1.0",
-        "pg-connection-string": "^2.6.0",
-        "pg-pool": "^3.6.0",
-        "pg-protocol": "^1.6.0",
-        "pg-types": "^2.1.0",
-        "pgpass": "1.x"
-      }
-    },
-    "pg-cloudflare": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.0.tgz",
-      "integrity": "sha512-tGM8/s6frwuAIyRcJ6nWcIvd3+3NmUKIs6OjviIm1HPPFEt5MzQDOTBQyhPWg/m0kCl95M6gA1JaIXtS8KovOA==",
-      "optional": true
-    },
-    "pg-connection-string": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.0.tgz",
-      "integrity": "sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg=="
-    },
-    "pg-int8": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
-      "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
-    },
-    "pg-pool": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.0.tgz",
-      "integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==",
-      "requires": {}
-    },
-    "pg-protocol": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz",
-      "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q=="
-    },
-    "pg-types": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
-      "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
-      "requires": {
-        "pg-int8": "1.0.1",
-        "postgres-array": "~2.0.0",
-        "postgres-bytea": "~1.0.0",
-        "postgres-date": "~1.0.4",
-        "postgres-interval": "^1.1.0"
-      }
-    },
-    "pgpass": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
-      "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
-      "requires": {
-        "split2": "^4.1.0"
-      }
-    },
-    "postgres-array": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
-      "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="
-    },
-    "postgres-bytea": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
-      "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="
-    },
-    "postgres-date": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
-      "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="
-    },
-    "postgres-interval": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
-      "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
-      "requires": {
-        "xtend": "^4.0.0"
-      }
-    },
-    "split2": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
-      "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="
-    },
-    "uWebSockets.js": {
-      "version": "git+ssh://[email protected]/uNetworking/uWebSockets.js.git#d39d4181daf5b670d44cbc1b18f8c28c85fd4142",
-      "from": "uWebSockets.js@uNetworking/uWebSockets.js#v20.30.0"
-    },
-    "xtend": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
-      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
+      "version": "20.31.0",
+      "resolved": "git+ssh://[email protected]/uNetworking/uWebSockets.js.git#809b99d2d7d12e2cbf89b7135041e9b41ff84084"
     }
   }
 }

+ 2 - 4
frameworks/JavaScript/uwebsockets.js/package.json

@@ -1,9 +1,7 @@
 {
   "dependencies": {
-    "html-escaper": "^3.0.3",
-    "pg": "^8.11.0",
-    "pg-pool": "^3.6.0",
-    "uWebSockets.js": "uNetworking/uWebSockets.js#v20.30.0"
+    "postgres": "^3.3.5",
+    "uWebSockets.js": "uNetworking/uWebSockets.js#v20.31.0"
   },
   "license": "MIT",
   "main": "src/server.js",

+ 6 - 15
frameworks/JavaScript/uwebsockets.js/src/database/postgres.js

@@ -1,24 +1,15 @@
-import Pool from "pg-pool";
+import postgres from "postgres";
 
-const pool = new Pool({
+const sql = postgres({
   host: "tfb-database",
   user: "benchmarkdbuser",
   password: "benchmarkdbpass",
   database: "hello_world",
+  max: 1
 });
 
-await pool.connect();
+export const fortunes = async () => await sql`SELECT id, message FROM fortune`;
 
-const query = (text, values) =>
-  pool.query(text, values || []).then((r) => r.rows);
+export const find = async (id) => await sql`SELECT id, randomNumber FROM world WHERE id = ${id}`.then((arr) => arr[0]);
 
-export const fortunes = () => query("SELECT * FROM fortune");
-
-export const find = (id) =>
-  query("SELECT * FROM world WHERE id = $1", [id]).then((arr) => arr[0]);
-
-export const update = (obj) =>
-  query("UPDATE world SET randomNumber = $1 WHERE id = $2", [
-    obj.randomNumber,
-    obj.id,
-  ]);
+export const update = async (obj) => await sql`UPDATE world SET randomNumber = ${obj.randomNumber} WHERE id = ${obj.id}`;

+ 25 - 35
frameworks/JavaScript/uwebsockets.js/src/server.js

@@ -1,10 +1,10 @@
-import { escape } from "html-escaper";
 import uWebSockets from "uWebSockets.js";
 import {
   addBenchmarkHeaders,
   generateRandomNumber,
   getQueriesCount,
   handleError,
+  escape,
 } from "./utils.js";
 
 let db;
@@ -14,15 +14,19 @@ if (DATABASE) db = await import(`./database/${DATABASE}.js`);
 const webserver = uWebSockets.App();
 
 webserver.get("/plaintext", (response) => {
-  addBenchmarkHeaders(response);
-  response.writeHeader("Content-Type", "text/plain");
-  response.end("Hello, World!");
+  response.cork(() => {
+    addBenchmarkHeaders(response);
+    response.writeHeader("Content-Type", "text/plain");
+    response.end("Hello, World!");
+  });
 });
 
 webserver.get("/json", (response) => {
-  addBenchmarkHeaders(response);
-  response.writeHeader("Content-Type", "application/json");
-  response.end(JSON.stringify({ message: "Hello, World!" }));
+  response.cork(() => {
+    addBenchmarkHeaders(response);
+    response.writeHeader("Content-Type", "application/json");
+    response.end(JSON.stringify({ message: "Hello, World!" }));
+  });
 });
 
 if (db) {
@@ -38,10 +42,6 @@ if (db) {
         return;
       }
 
-      if (rows.length < 1) {
-        return handleError(new Error("Row not found"), response);
-      }
-
       response.cork(() => {
         addBenchmarkHeaders(response);
         response.writeHeader("Content-Type", "application/json");
@@ -64,10 +64,10 @@ if (db) {
     try {
       const queriesCount = getQueriesCount(request);
 
-      const databaseJobs = [];
+      const databaseJobs = new Array(queriesCount);
 
       for (let i = 0; i < queriesCount; i++) {
-        databaseJobs.push(db.find(generateRandomNumber()));
+        databaseJobs[i] = db.find(generateRandomNumber());
       }
 
       const worldObjects = await Promise.all(databaseJobs);
@@ -102,32 +102,24 @@ if (db) {
         return;
       }
 
-      if (rows.length < 1) {
-        return handleError(new Error("Row not found"), response);
-      }
-
       rows.push({
         id: 0,
         message: "Additional fortune added at request time.",
       });
 
-      rows.sort((a, b) => a.message.localeCompare(b.message));
+      rows.sort((a, b) => (a.message < b.message) ? -1 : 1);
 
-      let html =
-        "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>";
+      const n = rows.length
 
-      for (let i = 0; i < rows.length; i++) {
-        html += `<tr><td>${rows[i].id}</td><td>${escape(
-          rows[i].message
-        )}</td></tr>`;
+      let html = "", i = 0;
+      for (; i < n; i++) {
+        html += `<tr><td>${rows[i].id}</td><td>${escape(rows[i].message)}</td></tr>`;
       }
 
-      html += "</table></body></html>";
-
       response.cork(() => {
         addBenchmarkHeaders(response);
         response.writeHeader("Content-Type", "text/html; charset=utf-8");
-        response.end(html);
+        response.end(`<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>${html}</table></body></html>`);
       });
     } catch (error) {
       if (response.aborted) {
@@ -146,30 +138,28 @@ if (db) {
     try {
       const queriesCount = getQueriesCount(request);
 
-      const databaseReadJobs = [];
+      const databaseJobs = new Array(queriesCount);
 
       for (let i = 0; i < queriesCount; i++) {
-        databaseReadJobs.push(db.find(generateRandomNumber()));
+        databaseJobs[i] = db.find(generateRandomNumber());
       }
 
-      const worldObjects = await Promise.all(databaseReadJobs);
+      const worldObjects = await Promise.all(databaseJobs);
 
       if (response.aborted) {
         return;
       }
 
-      const databaseWriteJobs = [];
-
-      for (let i = 0; i < worldObjects.length; i++) {
+      for (let i = 0; i < queriesCount; i++) {
         worldObjects[i].randomNumber = generateRandomNumber();
-        databaseWriteJobs.push(db.update(worldObjects[i]));
+        databaseJobs[i] = db.update(worldObjects[i]);
       }
 
       if (response.aborted) {
         return;
       }
 
-      await Promise.all(databaseWriteJobs);
+      await Promise.all(databaseJobs);
 
       response.cork(() => {
         addBenchmarkHeaders(response);

+ 19 - 17
frameworks/JavaScript/uwebsockets.js/src/utils.js

@@ -1,14 +1,16 @@
 /**
  * Add Benchmark HTTP response headers.
  *
- * Add HTTP response headers `Server` and `Date` which are required by the test suite.
+ * Add HTTP response headers `Server` which is required by the test suite.
+ * Header `Date` is automatically added by uWebsockets
+ * https://github.com/uNetworking/uWebSockets/blob/master/src/HttpResponse.h#L78
+ * 
  * https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview
  *
  * @param {import('uWebSockets.js').HttpResponse} response
  */
 export function addBenchmarkHeaders(response) {
   response.writeHeader("Server", "uWebSockets.js");
-  response.writeHeader("Date", new Date().toUTCString());
 }
 
 /**
@@ -32,20 +34,7 @@ export function handleError(error, response) {
  * @param {import('uWebSockets.js').HttpRequest} request
  */
 export function getQueriesCount(request) {
-  let queriesCount = 1;
-
-  if (request.getQuery("queries")) {
-    try {
-      const queries = parseInt(request.getQuery("queries"));
-      if (queries <= 500 && queries >= 1) {
-        queriesCount = queries;
-      } else if (queries > 500) {
-        queriesCount = 500;
-      }
-    } catch {}
-  }
-
-  return queriesCount;
+  return Math.min(parseInt(request.getQuery("queries")) || 1, 500);
 }
 
 /**
@@ -53,5 +42,18 @@ export function getQueriesCount(request) {
  *
  */
 export function generateRandomNumber() {
-  return Math.floor(Math.random() * 9999) + 1;
+  return Math.floor(Math.random() * 10000) + 1;
+}
+
+/**
+ * Escape unsafe HTML Code
+ *
+ */
+const escapeHTMLRules = { '&': '&#38;', '<': '&#60;', '>': '&#62;', '"': '&#34;', "'": '&#39;', '/': '&#47;' }
+
+const unsafeHTMLMatcher = /[&<>"'\/]/g
+
+export function escape(text) {
+  if (unsafeHTMLMatcher.test(text) === false) return text;
+  return text.replace(unsafeHTMLMatcher, function (m) { return escapeHTMLRules[m] || m; });
 }