UNPKG

@octokit/webhooks

Version:

GitHub webhook events toolset for Node.js

104 lines (103 loc) 3.04 kB
import { getMissingHeaders } from "./get-missing-headers.js"; import { getPayload } from "./get-payload.js"; import { onUnhandledRequestDefault } from "./on-unhandled-request-default.js"; async function middleware(webhooks, options, request) { let pathname; try { pathname = new URL(request.url, "http://localhost").pathname; } catch (error) { return new Response( JSON.stringify({ error: `Request URL could not be parsed: ${request.url}` }), { status: 422, headers: { "content-type": "application/json" } } ); } if (pathname !== options.path || request.method !== "POST") { return onUnhandledRequestDefault(request); } if (typeof request.headers.get("content-type") !== "string" || !request.headers.get("content-type").startsWith("application/json")) { return new Response( JSON.stringify({ error: `Unsupported "Content-Type" header value. Must be "application/json"` }), { status: 415, headers: { "content-type": "application/json" } } ); } const missingHeaders = getMissingHeaders(request).join(", "); if (missingHeaders) { return new Response( JSON.stringify({ error: `Required headers missing: ${missingHeaders}` }), { status: 422, headers: { "content-type": "application/json" } } ); } const eventName = request.headers.get("x-github-event"); const signatureSHA256 = request.headers.get("x-hub-signature-256"); const id = request.headers.get("x-github-delivery"); options.log.debug(`${eventName} event received (id: ${id})`); let didTimeout = false; let timeout; const timeoutPromise = new Promise((resolve) => { timeout = setTimeout(() => { didTimeout = true; resolve( new Response("still processing\n", { status: 202, headers: { "Content-Type": "text/plain" } }) ); }, 9e3).unref(); }); const processWebhook = async () => { try { const payload = await getPayload(request); await webhooks.verifyAndReceive({ id, name: eventName, payload, signature: signatureSHA256 }); clearTimeout(timeout); if (didTimeout) return new Response(null); return new Response("ok\n"); } catch (error) { clearTimeout(timeout); if (didTimeout) return new Response(null); const err = Array.from(error.errors)[0]; const errorMessage = err.message ? `${err.name}: ${err.message}` : "Error: An Unspecified error occurred"; options.log.error(error); return new Response( JSON.stringify({ error: errorMessage }), { status: typeof err.status !== "undefined" ? err.status : 500, headers: { "content-type": "application/json" } } ); } }; return await Promise.race([timeoutPromise, processWebhook()]); } export { middleware };