diff --git a/lambda-function.js b/lambda-function.js index 32ce00c..f4067c6 100644 --- a/lambda-function.js +++ b/lambda-function.js @@ -1,22 +1,23 @@ module.exports = lambdaFunction; +const lowercaseKeys = require("lowercase-keys"); + async function lambdaFunction(probot, event, context) { try { // Ends function immediately after callback context.callbackWaitsForEmptyEventLoop = false; + // lowercase all headers to respect headers insensitivity (RFC 7230 $3.2 'Header Fields', see issue #62) + const headersLowerCase = lowercaseKeys(event.headers); + // this will be simpler once we ship `verifyAndParse()` // see https://github.com/octokit/webhooks.js/issues/379 await probot.webhooks.verifyAndReceive({ - id: - event.headers["X-GitHub-Delivery"] || - event.headers["x-github-delivery"], - name: event.headers["X-GitHub-Event"] || event.headers["x-github-event"], + id: headersLowerCase["x-github-delivery"], + name: headersLowerCase["x-github-event"], signature: - event.headers["X-Hub-Signature-256"] || - event.headers["x-hub-signature-256"] || - event.headers["X-Hub-Signature"] || - event.headers["x-hub-signature"], + headersLowerCase["x-hub-signature-256"] || + headersLowerCase["x-hub-signature"], payload: JSON.parse(event.body), }); diff --git a/package-lock.json b/package-lock.json index 90903eb..4615673 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@probot/adapter-aws-lambda-serverless", - "version": "0.6.0", + "version": "0.0.0-development", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3289,6 +3289,13 @@ "p-cancelable": "^1.0.0", "to-readable-stream": "^1.0.0", "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + } } }, "graceful-fs": { @@ -5463,9 +5470,9 @@ "dev": true }, "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" }, "lru-cache": { "version": "6.0.0", @@ -6743,6 +6750,13 @@ "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", "requires": { "lowercase-keys": "^1.0.0" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + } } }, "ret": { diff --git a/package.json b/package.json index bce2b22..c1727a6 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "repository": "https://github.com/probot/adapter-aws-lambda-serverless", "dependencies": { "@probot/get-private-key": "^1.1.0", - "probot": "^11.0.6" + "probot": "^11.0.6", + "lowercase-keys": "^2.0.0" }, "devDependencies": { "@types/jest": "^26.0.20", diff --git a/test/index.test.js b/test/index.test.js index f0ed8d9..1ce880d 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,4 +1,5 @@ const nock = require("nock"); +const path = require("path"); const { createLambdaFunction, Probot, ProbotOctokit } = require("../index"); const app = require("./fixtures/app"); @@ -28,7 +29,7 @@ describe("@probot/adapter-aws-lambda-serverless", () => { "/repos/probot/adapter-adapter-aws-lambda-serverless/commits/headcommitsha123/comments", (requestBody) => { expect(requestBody).toStrictEqual({ - body: "Hello from test/fixtures/app.js", + body: `Hello from test${path.sep}fixtures${path.sep}app.js`, }); return true; @@ -65,7 +66,7 @@ describe("@probot/adapter-aws-lambda-serverless", () => { "/repos/probot/adapter-adapter-aws-lambda-serverless/commits/headcommitsha123/comments", (requestBody) => { expect(requestBody).toStrictEqual({ - body: "Hello from test/fixtures/app.js", + body: `Hello from test${path.sep}fixtures${path.sep}app.js`, }); return true; @@ -93,4 +94,78 @@ describe("@probot/adapter-aws-lambda-serverless", () => { expect(mock.activeMocks()).toStrictEqual([]); }); + + test("GitHub request headers", async () => { + const fn = createLambdaFunction(app, { probot }); + + const mock = nock("https://api.github.com") + .post( + "/repos/probot/adapter-adapter-aws-lambda-serverless/commits/headcommitsha123/comments", + (requestBody) => { + expect(requestBody).toStrictEqual({ + body: `Hello from test${path.sep}fixtures${path.sep}app.js`, + }); + + return true; + } + ) + .reply(201, {}); + + const context = {}; + const payload = JSON.stringify(require("./fixtures/push.json")); + const signature = probot.webhooks.sign(payload); + const event = { + headers: { + "X-Github-Delivery": "eventid123", + "X-Github-Event": "push", + "X-Hub-Signature": signature, + }, + body: payload, + }; + + await fn(event, context); + + expect(context).toStrictEqual({ + callbackWaitsForEmptyEventLoop: false, + }); + + expect(mock.activeMocks()).toStrictEqual([]); + }); + + test("camelcase request headers (#62)", async () => { + const fn = createLambdaFunction(app, { probot }); + + const mock = nock("https://api.github.com") + .post( + "/repos/probot/adapter-adapter-aws-lambda-serverless/commits/headcommitsha123/comments", + (requestBody) => { + expect(requestBody).toStrictEqual({ + body: `Hello from test${path.sep}fixtures${path.sep}app.js`, + }); + + return true; + } + ) + .reply(201, {}); + + const context = {}; + const payload = JSON.stringify(require("./fixtures/push.json")); + const signature = probot.webhooks.sign(payload); + const event = { + headers: { + "X-Github-Delivery": "EventId123", + "X-Github-Event": "push", + "X-Hub-Signature": signature, + }, + body: payload, + }; + + await fn(event, context); + + expect(context).toStrictEqual({ + callbackWaitsForEmptyEventLoop: false, + }); + + expect(mock.activeMocks()).toStrictEqual([]); + }); });