diff --git a/lib/util.js b/lib/util.js index a36c4804..daecfd15 100644 --- a/lib/util.js +++ b/lib/util.js @@ -35,15 +35,17 @@ async function validateWebhook(requestData, secret) { const signingSecret = secret || requestData.secret; if (requestData && requestData.headers && requestData.body) { - id = - requestData.headers["webhook-id"] || - requestData.headers.get?.("webhook-id"); - timestamp = - requestData.headers["webhook-timestamp"] || - requestData.headers.get?.("webhook-timestamp"); - signature = - requestData.headers["webhook-signature"] || - requestData.headers.get?.("webhook-signature"); + if (typeof requestData.headers.get === "function") { + // Headers object (e.g. Fetch API Headers) + id = requestData.headers.get("webhook-id"); + timestamp = requestData.headers.get("webhook-timestamp"); + signature = requestData.headers.get("webhook-signature"); + } else { + // Plain object with header key-value pairs + id = requestData.headers["webhook-id"]; + timestamp = requestData.headers["webhook-timestamp"]; + signature = requestData.headers["webhook-signature"]; + } body = requestData.body; } @@ -75,11 +77,18 @@ async function validateWebhook(requestData, secret) { const signedContent = `${id}.${timestamp}.${body}`; - const computedSignature = await createHMACSHA256(signingSecret.split("_").pop(), signedContent); + const computedSignature = await createHMACSHA256( + signingSecret.split("_").pop(), + signedContent + ); - const expectedSignatures = signature.split(" ").map((sig) => sig.split(",")[1]); + const expectedSignatures = signature + .split(" ") + .map((sig) => sig.split(",")[1]); - return expectedSignatures.some((expectedSignature) => expectedSignature === computedSignature); + return expectedSignatures.some( + (expectedSignature) => expectedSignature === computedSignature + ); } /** @@ -106,9 +115,13 @@ async function createHMACSHA256(secret, data) { crypto = require.call(null, "node:crypto").webcrypto; } - const key = await crypto.subtle.importKey("raw", base64ToBytes(secret), { name: "HMAC", hash: "SHA-256" }, false, [ - "sign", - ]); + const key = await crypto.subtle.importKey( + "raw", + base64ToBytes(secret), + { name: "HMAC", hash: "SHA-256" }, + false, + ["sign"] + ); const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(data)); return bytesToBase64(signature); @@ -232,7 +245,11 @@ async function transformFileInputs(client, inputs, strategy) { try { return await transformFileInputsToReplicateFileURLs(client, inputs); } catch (error) { - if (error instanceof ApiError && error.response.status >= 400 && error.response.status < 500) { + if ( + error instanceof ApiError && + error.response.status >= 400 && + error.response.status < 500 + ) { throw error; } return await transformFileInputsToBase64EncodedDataURIs(inputs); @@ -296,7 +313,7 @@ async function transformFileInputsToBase64EncodedDataURIs(inputs) { totalBytes += buffer.byteLength; if (totalBytes > MAX_DATA_URI_SIZE) { throw new Error( - `Combined filesize of prediction ${totalBytes} bytes exceeds 10mb limit for inline encoding, please provide URLs instead`, + `Combined filesize of prediction ${totalBytes} bytes exceeds 10mb limit for inline encoding, please provide URLs instead` ); } @@ -354,11 +371,14 @@ function isPlainObject(value) { if (proto === null) { return true; } - const Ctor = Object.prototype.hasOwnProperty.call(proto, "constructor") && proto.constructor; + const Ctor = + Object.prototype.hasOwnProperty.call(proto, "constructor") && + proto.constructor; return ( typeof Ctor === "function" && Ctor instanceof Ctor && - Function.prototype.toString.call(Ctor) === Function.prototype.toString.call(Object) + Function.prototype.toString.call(Ctor) === + Function.prototype.toString.call(Object) ); }