diff --git a/.changeset/popular-laws-draw.md b/.changeset/popular-laws-draw.md new file mode 100644 index 0000000..0011429 --- /dev/null +++ b/.changeset/popular-laws-draw.md @@ -0,0 +1,5 @@ +--- +"@foxify/http": patch +--- + +improve http response performance diff --git a/benchmarks/foxify/README.md b/benchmarks/foxify/README.md index 0ee79b0..3abc0f9 100644 --- a/benchmarks/foxify/README.md +++ b/benchmarks/foxify/README.md @@ -8,48 +8,48 @@ ┌─────────────────────────────┬──────────────┬────────┬───────────┬──────────────┬─────────────────┐ │ * │ Version │ Router │ Req/Sec │ Latency (ms) │ Throughput (MB) │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ foxify-old │ 0.10.20 │ ✓ │ 103,507.2 │ 9.15 │ 16.98 │ +│ foxify-old │ 0.10.20 │ ✓ │ 103,123.2 │ 9.18 │ 16.91 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ fastify │ 4.18.0 │ ✓ │ 99,308.8 │ 9.56 │ 17.80 │ +│ fastify │ 4.18.0 │ ✓ │ 99,680.0 │ 9.52 │ 17.88 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ bare │ 18.16.0 │ ✗ │ 97,555.2 │ 9.76 │ 16.00 │ +│ foxify │ 1.0.0-beta.0 │ ✓ │ 91,321.6 │ 10.43 │ 16.28 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ foxify │ 1.0.0-beta.0 │ ✓ │ 91,680.0 │ 10.40 │ 16.35 │ +│ foxify-old-with-middlewares │ 0.10.20 │ ✓ │ 86,009.6 │ 11.11 │ 30.75 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ foxify-old-with-middlewares │ 0.10.20 │ ✓ │ 85,804.8 │ 11.14 │ 30.68 │ +│ polka │ 0.5.2 │ ✓ │ 85,536.0 │ 11.18 │ 11.42 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ polka │ 0.5.2 │ ✓ │ 85,702.4 │ 11.16 │ 11.44 │ +│ koa │ 2.14.2 │ ✗ │ 85,280.0 │ 11.21 │ 15.21 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ rayo │ 1.4.0 │ ✓ │ 84,742.4 │ 11.29 │ 11.32 │ +│ rayo │ 1.4.0 │ ✓ │ 84,921.6 │ 11.27 │ 11.34 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ koa │ 2.14.2 │ ✗ │ 84,371.2 │ 11.32 │ 15.04 │ +│ micro │ 10.0.1 │ ✗ │ 81,427.2 │ 11.76 │ 14.53 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ micro │ 10.0.1 │ ✗ │ 80,774.4 │ 11.87 │ 14.40 │ +│ foxify-with-middlewares │ 1.0.0-beta.0 │ ✓ │ 80,864.0 │ 11.86 │ 30.08 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ foxify-with-middlewares │ 1.0.0-beta.0 │ ✓ │ 80,697.6 │ 11.88 │ 30.01 │ +│ bare │ 18.16.0 │ ✗ │ 78,624.0 │ 12.22 │ 12.90 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ koa-router │ 12.0.0 │ ✓ │ 76,204.8 │ 12.60 │ 13.59 │ +│ connect │ 3.7.0 │ ✗ │ 75,180.8 │ 12.79 │ 12.33 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ connect │ 3.7.0 │ ✗ │ 75,782.4 │ 12.68 │ 12.43 │ +│ koa-router │ 12.0.0 │ ✓ │ 74,528.0 │ 12.91 │ 13.29 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ hapi │ 21.3.2 │ ✓ │ 73,337.6 │ 13.10 │ 13.08 │ +│ hapi │ 21.3.2 │ ✓ │ 73,760.0 │ 13.03 │ 13.15 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ connect-router │ 1.3.8 │ ✓ │ 71,328.0 │ 13.50 │ 11.70 │ +│ trek-engine-router │ 1.2.0 │ ✓ │ 70,752.0 │ 13.63 │ 11.61 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ trek-engine-router │ 1.2.0 │ ✓ │ 71,046.4 │ 13.57 │ 11.65 │ +│ connect-router │ 1.3.8 │ ✓ │ 70,483.2 │ 13.68 │ 11.56 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ trek-engine │ 1.0.5 │ ✗ │ 70,422.4 │ 13.68 │ 11.55 │ +│ trek-engine │ 1.0.5 │ ✗ │ 69,446.4 │ 13.89 │ 11.39 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ micro-router │ 3.1.3 │ ✓ │ 58,729.6 │ 16.51 │ 10.47 │ +│ micro-router │ 3.1.3 │ ✓ │ 58,819.2 │ 16.47 │ 10.49 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ take-five │ 2.0.0 │ ✓ │ 36,534.4 │ 26.80 │ 13.59 │ +│ take-five │ 2.0.0 │ ✓ │ 37,692.8 │ 25.97 │ 14.02 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ express │ 4.18.2 │ ✓ │ 25,860.8 │ 38.02 │ 4.61 │ +│ express │ 4.18.2 │ ✓ │ 25,755.2 │ 38.20 │ 4.59 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ express-with-middlewares │ 4.18.2 │ ✓ │ 23,844.8 │ 41.27 │ 8.87 │ +│ express-with-middlewares │ 4.18.2 │ ✓ │ 23,115.2 │ 42.58 │ 8.60 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ fastify-with-middlewares │ 4.18.0 │ ✓ │ 22,497.6 │ 43.73 │ 8.39 │ +│ fastify-with-middlewares │ 4.18.0 │ ✓ │ 22,516.8 │ 43.69 │ 8.40 │ ├─────────────────────────────┼──────────────┼────────┼───────────┼──────────────┼─────────────────┤ -│ restify │ 11.1.0 │ ✓ │ 4,783.8 │ 204.87 │ 0.86 │ +│ restify │ 11.1.0 │ ✓ │ 4,730.6 │ 207.20 │ 0.85 │ └─────────────────────────────┴──────────────┴────────┴───────────┴──────────────┴─────────────────┘ ``` diff --git a/packages/http/src/Response.ts b/packages/http/src/Response.ts index 3946e90..005089e 100644 --- a/packages/http/src/Response.ts +++ b/packages/http/src/Response.ts @@ -10,7 +10,7 @@ import escapeHtml from "escape-html"; import onFinished from "on-finished"; import send, { mime as sendMime } from "send"; import Request from "./Request.js"; -import { JsonT, METHOD, STATUS, StatusT, StringifyT } from "./constants/index.js"; +import { ENCODING_UTF8, JsonT, METHOD, STATUS, StatusT, StringifyT } from "./constants/index.js"; import { createETagGenerator, encodeUrl, vary } from "./utils/index.js"; import { CallbackT as EngineCallbackT, Engine } from "./view/index.js"; @@ -416,7 +416,7 @@ class Response extends ServerResponse { public bin(body: Buffer): this { if (!this.hasHeader("content-type")) this.type("bin"); - return this.#send(body); + return this.$end(body); } /** @@ -734,11 +734,10 @@ class Response extends ServerResponse { * res.json({ user: "tj" }); */ public json(body: JsonT): this { - const encoding = "utf-8"; - const type = this.get("content-type"); + const type = this.get("Content-Type"); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - if (typeof type === "string") this.setHeader("Content-Type", setCharset(type, encoding)!); + if (typeof type === "string") this.setHeader("Content-Type", setCharset(type, ENCODING_UTF8)!); else this.setHeader("Content-Type", "application/json; charset=utf-8"); const { @@ -747,7 +746,7 @@ class Response extends ServerResponse { "json.escape": escape, } = SETTINGS; - return this.#send( + return this.$end( stringify( this.stringify[this.statusCode], body, @@ -755,7 +754,7 @@ class Response extends ServerResponse { spaces, escape, ), - encoding, + ENCODING_UTF8, ); } @@ -943,10 +942,10 @@ class Response extends ServerResponse { if (Buffer.isBuffer(body)) return this.bin(body); - if (body === null) return this.#send(""); + if (body === null) return this.$end(""); // eslint-disable-next-line no-undefined - if (body === undefined) return this.#send(); + if (body === undefined) return this.$end(); return this.json(body); } @@ -1069,14 +1068,13 @@ class Response extends ServerResponse { * res.send("

some html

"); */ public text(body: string): this { - const encoding = "utf-8"; const type = this.get("content-type"); // Reflect this in content-type - if (typeof type === "string") this.set("Content-Type", setCharset(type, encoding)); - else this.set("Content-Type", setCharset("text/html", encoding)); + if (typeof type === "string") this.set("Content-Type", setCharset(type, ENCODING_UTF8)); + else this.set("Content-Type", setCharset("text/html", ENCODING_UTF8)); - return this.#send(body); + return this.$end(body); } /** @@ -1095,7 +1093,7 @@ class Response extends ServerResponse { * @param encoding * @private */ - #send(body?: Buffer | string, encoding?: BufferEncoding): this { + private $end(body?: Buffer | string, encoding?: BufferEncoding): this { // eslint-disable-next-line no-undefined if (body !== undefined) { const { etag } = SETTINGS; @@ -1110,18 +1108,18 @@ class Response extends ServerResponse { // Freshness if (this.fresh) this.statusCode = STATUS.NOT_MODIFIED; - const { statusCode } = this; - // Strip irrelevant headers - if ( - STATUS.NO_CONTENT === statusCode - || STATUS.NOT_MODIFIED === statusCode - ) { - this.removeHeader("content-type"); - this.removeHeader("content-length"); - this.removeHeader("transfer-encoding"); - - body = ""; + switch (this.statusCode) { + case STATUS.NO_CONTENT: + case STATUS.NOT_MODIFIED: + this.removeHeader("content-type"); + this.removeHeader("content-length"); + this.removeHeader("transfer-encoding"); + + body = ""; + break; + default: + break; } // Skip body for HEAD diff --git a/packages/http/src/constants/common.ts b/packages/http/src/constants/common.ts index c40b950..f393574 100644 --- a/packages/http/src/constants/common.ts +++ b/packages/http/src/constants/common.ts @@ -1,3 +1,5 @@ +export const ENCODING_UTF8 = "utf-8" as const; + export type JsonT = JsonT[] | boolean | number | string | { [ket: string]: JsonT } | null | undefined;