summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2024-03-16 06:55:20 -0300
committerEuAndreh <eu@euandre.org>2024-03-16 06:55:20 -0300
commitafe9d6f77ea2386732e6d7646c298584321d44cf (patch)
treedbb80c84f3158c7b6591057e16525c2fa6a5678f
parentsrc/hero.mjs: Remove current makeUpgradeListener() and its helpers (diff)
downloadpapod-afe9d6f77ea2386732e6d7646c298584321d44cf.tar.gz
papod-afe9d6f77ea2386732e6d7646c298584321d44cf.tar.xz
src/hero.mjs: Add writeHead() and its helper functions
-rw-r--r--src/hero.mjs17
-rw-r--r--tests/js/hero.mjs76
2 files changed, 93 insertions, 0 deletions
diff --git a/src/hero.mjs b/src/hero.mjs
index b47d459..75c9a88 100644
--- a/src/hero.mjs
+++ b/src/hero.mjs
@@ -380,6 +380,23 @@ export const extractQueryParams = s => {
return ret;
};
+export const renderStatus = code =>
+ `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}`
+
+export const renderHeaders = obj =>
+ Object.keys(obj)
+ .sort(u.strSortFn)
+ .map(name => `${name}: ${obj[name]}`);
+
+export const buildHeader = (status, headers) =>
+ [renderStatus(status)]
+ .concat(renderHeaders(headers))
+ .concat(["\r\n"])
+ .join("\r\n");
+
+export const writeHead = (socket, status, headers) =>
+ socket.write(buildHeader(status, headers));
+
export const handle404 = _req => ({
status: 404,
body: "Not Found\n",
diff --git a/tests/js/hero.mjs b/tests/js/hero.mjs
index 468f4a8..33403d0 100644
--- a/tests/js/hero.mjs
+++ b/tests/js/hero.mjs
@@ -33,6 +33,10 @@ import {
findDynamicHandler,
findHandler,
extractQueryParams,
+ renderStatus,
+ renderHeaders,
+ buildHeader,
+ writeHead,
handle404,
make404Handler,
handleRequest,
@@ -1331,6 +1335,74 @@ const test_extractQueryParams = async t => {
});
};
+const test_renderStatus = async t => {
+ t.start("renderStatus()");
+
+ await t.test("good statuses", () => {
+ assert.equal(renderStatus(101), "HTTP/1.1 101 Switching Protocols");
+ assert.equal(renderStatus(202), "HTTP/1.1 202 Accepted");
+ assert.equal(renderStatus(409), "HTTP/1.1 409 Conflict");
+ });
+};
+
+const test_renderHeaders = async t => {
+ t.start("renderHeaders()");
+
+ await t.test("empty values", () => {
+ assert.deepEqual(renderHeaders({}), []);
+ })
+
+ await t.test("values are rendered and sorted", () => {
+ assert.deepEqual(renderHeaders({ a: "one", Z: "two" }), [
+ "a: one",
+ "Z: two",
+ ]);
+ });
+
+ await t.test("GIGO for newlines", () => {
+ assert.deepEqual(renderHeaders({ a: "\nx: 1\r\n", }), [
+ "a: \nx: 1\r\n",
+ ]);
+ });
+};
+
+const test_buildHeader = async t => {
+ t.start("buildHeader()");
+
+ await t.test("empty values", () => {
+ assert.equal(
+ buildHeader(200, {}),
+ "HTTP/1.1 200 OK\r\n" +
+ "\r\n",
+ );
+ });
+
+ await t.test("we compose the status line and the headers", () => {
+ assert.equal(
+ buildHeader(201, { a: "1", b: "2" }),
+ "HTTP/1.1 201 Created\r\n" +
+ "a: 1\r\n" +
+ "b: 2\r\n" +
+ "\r\n",
+ );
+ });
+};
+
+const test_writeHead = async t => {
+ t.start("writeHead()");
+
+ await t.test("we simply write what buildHeader() gives us", () => {
+ const contents = [];
+ const socket = { write: x => contents.push(x) };
+ writeHead(socket, 202, { "Key": "Value" });
+ assert.deepEqual(contents, [
+ "HTTP/1.1 202 Accepted\r\n" +
+ "Key: Value\r\n" +
+ "\r\n",
+ ]);
+ });
+};
+
const test_make404Handler = async t => {
t.start("make404Handler");
@@ -2146,6 +2218,10 @@ await runner.runTests([
test_findDynamicHandler,
test_findHandler,
test_extractQueryParams,
+ test_renderStatus,
+ test_renderHeaders,
+ test_buildHeader,
+ test_writeHead,
test_make404Handler,
test_handleRequest,
test_makeRequestListener,