Skip to content

Commit

Permalink
fix payload version 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
cnuss committed Apr 23, 2024
1 parent 13338ad commit 5ce03b5
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 43 deletions.
13 changes: 12 additions & 1 deletion src/events/http/lambda-events/LambdaProxyIntegrationEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { env } from "node:process"
import { log } from "@serverless/utils/log.js"
import { decodeJwt } from "jose"
import {
detectEncoding,
formatToClfTime,
nullIfEmpty,
parseHeaders,
Expand Down Expand Up @@ -63,6 +64,7 @@ export default class LambdaProxyIntegrationEvent {
}

let body = this.#request.payload
let isBase64Encoded = false

const { rawHeaders, url } = this.#request.raw.req

Expand All @@ -80,6 +82,15 @@ export default class LambdaProxyIntegrationEvent {
}

if (body) {
if (
this.#request.raw.req.payload &&
detectEncoding(this.#request) === "binary"
) {
body = Buffer.from(this.#request.raw.req.payload).toString("base64")
headers["Content-Length"] = String(Buffer.byteLength(body, "base64"))
isBase64Encoded = true
}

if (typeof body !== "string") {
// this.#request.payload is NOT the same as the rawPayload
body = this.#request.rawPayload
Expand Down Expand Up @@ -155,7 +166,7 @@ export default class LambdaProxyIntegrationEvent {
body,
headers,
httpMethod,
isBase64Encoded: false, // TODO hook up
isBase64Encoded,
multiValueHeaders: parseMultiValueHeaders(
// NOTE FIXME request.raw.req.rawHeaders can only be null for testing (hapi shot inject())
rawHeaders || [],
Expand Down
102 changes: 66 additions & 36 deletions tests/integration/httpApi-headers/httpApi-headers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,60 @@ describe("HttpApi Headers Tests", function desc() {
afterEach(() => teardown())

//
;["GET", "POST"].forEach((method) => {
it(`${method} headers`, async () => {
const url = new URL("/echo-headers", BASE_URL)
;[
{
desiredContentLengthHeader: "Content-Length",
desiredOriginHeader: "Origin",
desiredWebhookSignatureHeder: "X-Webhook-Signature",
payloadVersion: "1.0",
},
{
desiredContentLengthHeader: "content-length",
desiredOriginHeader: "origin",
desiredWebhookSignatureHeder: "x-webhook-signature",
payloadVersion: "2.0",
},
].forEach((t) => {
;["GET", "POST"].forEach((method) => {
it(`${method} headers (payload ${t.payloadVersion})`, async () => {
const url = new URL(`/echo-headers-${t.payloadVersion}`, BASE_URL)
const options = {
headers: {
Origin: "http://www.example.com",
"X-Webhook-Signature": "ABCDEF",
},
method,
}

const response = await fetch(url, options)

assert.equal(response.status, 200)

const body = await response.json()

assert.equal(
body.headersReceived[t.desiredOriginHeader],
"http://www.example.com",
)
assert.equal(
body.headersReceived[t.desiredWebhookSignatureHeder],
"ABCDEF",
)
assert.equal(body.isBase64EncodedReceived, false)
})
})

it(`multipart/form-data headers are base64 encoded (payload ${t.payloadVersion})`, async () => {
const url = new URL(`/echo-headers-${t.payloadVersion}`, BASE_URL)
const options = {
body: `------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name="file"; filename="file.txt"\r\nContent-Type: text/plain\r\n\r\n\u0001content\u0003\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--\r\n`,
headers: {
"Content-Type":
"multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
Origin: "http://www.example.com",
"X-Webhook-Signature": "ABCDEF",
},
method,
method: "POST",
}

const response = await fetch(url, options)
Expand All @@ -31,38 +76,23 @@ describe("HttpApi Headers Tests", function desc() {

const body = await response.json()

assert.equal(body.headersReceived.origin, "http://www.example.com")
assert.equal(body.headersReceived["x-webhook-signature"], "ABCDEF")
assert.equal(body.isBase64Encoded, false)
assert.equal(
body.headersReceived[t.desiredOriginHeader],
"http://www.example.com",
)
assert.equal(
body.headersReceived[t.desiredWebhookSignatureHeder],
"ABCDEF",
)
assert.equal(
Number.parseInt(body.headersReceived[t.desiredContentLengthHeader], 10),
options.body.length,
)
assert.equal(body.isBase64EncodedReceived, true)
assert.equal(
body.bodyReceived,
Buffer.from(options.body).toString("base64"),
)
})
})

it(`multipart/form-data headers are base64 encoded`, async () => {
const url = new URL("/echo-headers", BASE_URL)
const options = {
body: `------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name="file"; filename="file.txt"\r\nContent-Type: text/plain\r\n\r\n\u0001content\u0003\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--\r\n`,
headers: {
"Content-Type":
"multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
Origin: "http://www.example.com",
"X-Webhook-Signature": "ABCDEF",
},
method: "POST",
}

const response = await fetch(url, options)

assert.equal(response.status, 200)

const body = await response.json()

assert.equal(body.headersReceived.origin, "http://www.example.com")
assert.equal(body.headersReceived["x-webhook-signature"], "ABCDEF")
assert.equal(body.isBase64Encoded, true)
assert.equal(body.body, Buffer.from(options.body).toString("base64"))
assert.equal(
Number.parseInt(body.headersReceived["content-length"], 10),
options.body.length,
)
})
})
19 changes: 15 additions & 4 deletions tests/integration/httpApi-headers/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ plugins:
provider:
architecture: arm64
deploymentMethod: direct
httpApi:
payload: "2.0"
memorySize: 1024
name: aws
region: us-east-1
Expand All @@ -19,12 +17,25 @@ provider:
versionFunctions: false

functions:
echoHeadersV1:
httpApi:
payload: "1.0"
events:
- httpApi:
method: get
path: /echo-headers-1.0
- httpApi:
method: post
path: /echo-headers-1.0
handler: src/handler.echoHeaders
echoHeaders:
httpApi:
payload: "2.0"
events:
- httpApi:
method: get
path: /echo-headers
path: /echo-headers-2.0
- httpApi:
method: post
path: /echo-headers
path: /echo-headers-2.0
handler: src/handler.echoHeaders
4 changes: 2 additions & 2 deletions tests/integration/httpApi-headers/src/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ const { stringify } = JSON
export async function echoHeaders(event) {
return {
body: stringify({
body: event.body,
bodyReceived: event.body,
headersReceived: event.headers,
isBase64Encoded: event.isBase64Encoded,
isBase64EncodedReceived: event.isBase64Encoded,
}),
statusCode: 200,
}
Expand Down

0 comments on commit 5ce03b5

Please sign in to comment.