From 84c488008dd9edcb135f63abefd163fb3f155bb4 Mon Sep 17 00:00:00 2001 From: Armin Kunkel Date: Sun, 10 Sep 2023 02:13:00 +0200 Subject: [PATCH] test: http2 support --- test/index.test.ts | 88 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/test/index.test.ts b/test/index.test.ts index 3cf2142..dd0ec62 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,5 +1,8 @@ import { resolve } from "node:path"; import type { IncomingMessage, ServerResponse } from "node:http"; +import { request } from "node:http"; +import { request as httpsRequest } from "node:https"; +import { connect } from "node:http2"; import { describe, afterEach, test, expect } from "vitest"; import { listen, Listener } from "../src"; @@ -7,7 +10,57 @@ import { listen, Listener } from "../src"; // console.log = fn() function handle(request: IncomingMessage, response: ServerResponse) { - response.end(request.url); + response.end( + JSON.stringify({ + path: request.url, + httpVersion: request.httpVersion, + }), + ); +} + +// disable TLS certificate checks +process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + +function sendRequest(url: string, https = false) { + return new Promise((resolve) => { + (https ? httpsRequest : request)(url, (res) => { + const data: any[] = []; + res.on("data", (chunk) => { + data.push(chunk); + }); + res.on("end", () => { + resolve(data.join("")); + }); + }).end(); + }); +} + +function sendHttp2Request(url: string) { + // eslint-disable-next-line promise/param-names + return new Promise((resolve1, reject) => { + const client = connect(url); + + client.on("error", (err: Error) => { + reject(err); + client.close(); + }); + + const req = client.request({ + ":path": "/", + }); + + let data = ""; + req.on("data", (chunk) => { + data += chunk; + }); + + req.on("end", () => { + resolve1(data); + client.close(); + }); + + req.end(); + }); } describe("listhen", () => { @@ -45,9 +98,42 @@ describe("listhen", () => { expect(listener.url.endsWith("/foo/bar")).toBe(true); // eslint-disable-next-line no-console // expect(console.log).toHaveBeenCalledWith(expect.stringMatching('\n > Local: http://localhost:3000/foo/bar')) + const response = (await sendRequest(listener.url)) as string; + expect(JSON.parse(response)).toEqual({ + path: "/foo/bar", + httpVersion: "1.1", + }); + }); + + // see https://http2.github.io/faq/#does-http2-require-encryption + test("listen (http2)", async () => { + listener = await listen(handle); + expect(listener.url.startsWith("http://")).toBeTruthy(); + await expect(sendHttp2Request(listener.url)).rejects.toThrowError( + "Protocol error", + ); }); describe("https", () => { + test("listen (http2)", async () => { + listener = await listen(handle, { + https: true, + }); + expect(listener.url.startsWith("https:")).toBeTruthy(); + + let response = (await sendRequest(listener.url, true)) as string; + expect(JSON.parse(response)).toEqual({ + path: "/", + httpVersion: "1.1", + }); + + response = (await sendHttp2Request(listener.url)) as string; + expect(JSON.parse(response)).toEqual({ + path: "/", + httpVersion: "2.0", + }); + }); + test("listen (https - selfsigned)", async () => { listener = await listen(handle, { https: true, hostname: "localhost" }); expect(listener.url.startsWith("https://")).toBe(true);