From 5355c3525cf1c9160da1c45eae475d9549e8cc1a Mon Sep 17 00:00:00 2001 From: uzlopak Date: Sun, 21 Jul 2024 14:11:25 +0200 Subject: [PATCH] improve performance of headers check --- src/middleware/node/get-missing-headers.ts | 15 -------- src/middleware/node/handler.ts | 22 +++-------- src/middleware/node/validate-headers.ts | 45 ++++++++++++++++++++++ test/integration/node-handler.test.ts | 2 +- test/integration/node-middleware.test.ts | 2 +- 5 files changed, 52 insertions(+), 34 deletions(-) delete mode 100644 src/middleware/node/get-missing-headers.ts create mode 100644 src/middleware/node/validate-headers.ts diff --git a/src/middleware/node/get-missing-headers.ts b/src/middleware/node/get-missing-headers.ts deleted file mode 100644 index 8e4b0c32..00000000 --- a/src/middleware/node/get-missing-headers.ts +++ /dev/null @@ -1,15 +0,0 @@ -// remove type imports from http for Deno compatibility -// see https://github.com/octokit/octokit.js/issues/24#issuecomment-817361886 -// import type { IncomingMessage } from "node:http"; -type IncomingMessage = any; - -const WEBHOOK_HEADERS = [ - "x-github-event", - "x-hub-signature-256", - "x-github-delivery", -]; - -// https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#delivery-headers -export function getMissingHeaders(request: IncomingMessage) { - return WEBHOOK_HEADERS.filter((header) => !(header in request.headers)); -} diff --git a/src/middleware/node/handler.ts b/src/middleware/node/handler.ts index 7fd5caf8..ecc58c52 100644 --- a/src/middleware/node/handler.ts +++ b/src/middleware/node/handler.ts @@ -9,7 +9,7 @@ import type { WebhookEventName } from "../../generated/webhook-identifiers.js"; import type { Webhooks } from "../../index.js"; import type { WebhookEventHandlerError } from "../../types.js"; import type { MiddlewareOptions } from "./types.js"; -import { getMissingHeaders } from "./get-missing-headers.js"; +import { validateHeaders } from "./validate-headers.js"; import { getPayload } from "./get-payload.js"; type Handler = ( @@ -44,18 +44,7 @@ export function createNodeHandler( return true; } - const missingHeaders = getMissingHeaders(request).join(", "); - - if (missingHeaders) { - response.writeHead(400, { - "content-type": "application/json", - }); - response.end( - JSON.stringify({ - error: `Required headers missing: ${missingHeaders}`, - }), - ); - + if (validateHeaders(request, response)) { return true; } @@ -98,14 +87,13 @@ export function createNodeHandler( const errorMessage = err.message ? `${err.name}: ${err.message}` : "Error: An Unspecified error occurred"; - - const statusCode = - typeof err.status !== "undefined" ? err.status : 500; + + const statusCode = typeof err.status !== "undefined" ? err.status : 500; logger.error(error); response.writeHead(statusCode, { - "content-type": "application/json" + "content-type": "application/json", }); response.end( diff --git a/src/middleware/node/validate-headers.ts b/src/middleware/node/validate-headers.ts new file mode 100644 index 00000000..819c016c --- /dev/null +++ b/src/middleware/node/validate-headers.ts @@ -0,0 +1,45 @@ +// remove type imports from http for Deno compatibility +// see https://github.com/octokit/octokit.js/issues/24#issuecomment-817361886 +// import type { IncomingMessage } from "node:http"; +type IncomingMessage = any; +type OutgoingMessage = any; + +const webhookHeadersMissingMessage = { + "x-github-event": JSON.stringify({ + error: `Required header missing: x-github-event`, + }), + "x-hub-signature-256": JSON.stringify({ + error: `Required header missing: x-github-signature-256`, + }), + "x-github-delivery": JSON.stringify({ + error: `Required header missing: x-github-delivery`, + }), +}; + +function sendMissindHeaderResponse( + response: OutgoingMessage, + missingHeader: keyof typeof webhookHeadersMissingMessage, +) { + response.writeHead(400, { + "content-type": "application/json", + }); + response.end(webhookHeadersMissingMessage[missingHeader]); +} + +// https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#delivery-headers +export function validateHeaders( + request: IncomingMessage, + response: OutgoingMessage, +) { + if ("x-github-event" in request.headers === false) { + sendMissindHeaderResponse(response, "x-github-event"); + } else if ("x-hub-signature-256" in request.headers === false) { + sendMissindHeaderResponse(response, "x-hub-signature-256"); + } else if ("x-github-delivery" in request.headers === false) { + sendMissindHeaderResponse(response, "x-github-delivery"); + } else { + return false; + } + + return true; +} diff --git a/test/integration/node-handler.test.ts b/test/integration/node-handler.test.ts index 8d36b333..020da548 100644 --- a/test/integration/node-handler.test.ts +++ b/test/integration/node-handler.test.ts @@ -250,7 +250,7 @@ describe("createNodeHandler(webhooks)", () => { expect(response.status).toEqual(400); await expect(response.text()).resolves.toMatch( - /Required headers missing: x-github-event/, + /Required header missing: x-github-event/, ); server.close(); diff --git a/test/integration/node-middleware.test.ts b/test/integration/node-middleware.test.ts index 3014241e..8c6eb369 100644 --- a/test/integration/node-middleware.test.ts +++ b/test/integration/node-middleware.test.ts @@ -287,7 +287,7 @@ describe("createNodeMiddleware(webhooks)", () => { expect(response.status).toEqual(400); await expect(response.text()).resolves.toMatch( - /Required headers missing: x-github-event/, + /Required header missing: x-github-event/, ); server.close();