Feature Request - simulate isBase64Encoded.
Feature Request
const body = event.isBase64Encoded ? `${Buffer.from(event.body, 'base64')}` : event.body;
const payload = contentType === 'application/json'
? JSON.parse(body)
: (() => {
const params = new URLSearchParams(body)
const paramData = {} as any;
for (let param of params.entries()) {
paramData[param[0]] = decodeURIComponent(param[1]);
}
return paramData['payload'];
})();
The above code should be familiar - API Gateway may or may not send you "isBase64Encoded: true | false" and you're expected to decode the base64 payload as needed.
It would be good to have caught this in our test suite, as it is currently not possible to simulate this through serverless-offline. I'm not really sure how to accomplish this currently. From source code it appears that isBase64Encoded is always false.
My thought is either through a special header that could be provided such as X-SERVERLESS-OFFLINE-BASE64, or maybe content above a certain size might automatically be converted to base64.
Appreciate the great package 👍
@darylteo thank you for the report.
could you add some minimally needed example code (serverless.yml + handler) or better create a repository which works with serverless but not with serverless-offline?
I'm not sure how I can demonstrate a feature/functionality that is non existent. But I will try.
When using Serverless-Offline, the isBase64Encoded field is always false.
https://github.com/dherault/serverless-offline/search?q=isBase64Encoded
In a production environment, it is true on some occasions, or all occasions. This denotes that the event body is encoded in base64. (I believe this may be only for HTTP Gateway v2, not sure about v1)
So code that I wrote that works in serverless-offline, without taking into account isBase64Encoded, would fail in production.
For example, with this sample event (taking from AWS documentation) https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html#apigateway-example-event
{
"version": "2.0",
"routeKey": "ANY /nodejs-apig-function-1G3XMPLZXVXYI",
"rawPath": "/default/nodejs-apig-function-1G3XMPLZXVXYI",
"rawQueryString": "",
"cookies": [
"s_fid=7AABXMPL1AFD9BBF-0643XMPL09956DE2",
"regStatus=pre-register"
],
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"accept-encoding": "gzip, deflate, br",
...
},
"requestContext": {
"accountId": "123456789012",
"apiId": "r3pmxmplak",
"domainName": "r3pmxmplak.execute-api.us-east-2.amazonaws.com",
"domainPrefix": "r3pmxmplak",
"http": {
"method": "GET",
"path": "/default/nodejs-apig-function-1G3XMPLZXVXYI",
"protocol": "HTTP/1.1",
"sourceIp": "205.255.255.176",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"
},
"requestId": "JKJaXmPLvHcESHA=",
"routeKey": "ANY /nodejs-apig-function-1G3XMPLZXVXYI",
"stage": "default",
"time": "10/Mar/2020:05:16:23 +0000",
"timeEpoch": 1583817383220
},
"body": "<...some base 64 string== >"
"isBase64Encoded": true <!-------
}
If I tried to parse like so:
const body = event.body;
const payload = contentType === 'application/json'
? JSON.parse(body)
: (() => {
const params = new URLSearchParams(body)
const paramData = {} as any;
for (let param of params.entries()) {
paramData[param[0]] = decodeURIComponent(param[1]);
}
return paramData['payload'];
})();
I will get "unrecognised character at position 0" when I'm trying to parse, because it's trying to parse a base64 string without decoding.
The goal here is to simulate base64 for local automated testing to ensure that handlers will work as expected in prod.
I just noticed that this has been marked as a "TODO"
https://github.com/dherault/serverless-offline/blob/466a1e903bbb4df39bd5f972ca151553b0586041/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js#L165
Hope that explains!
thank you @darylteo I thought this was already implemented, but seems like it wasn't (yet).
#1776 fixes this