I am attempting to read an HTML file into a Lambda Edge function and then return it in the response body, but for some reason, I cannot get it to return the contents of the HTML file correctly.
Here is my code (simplified):
const AWS = require('aws-sdk');
const S3 = new AWS.S3({
signatureVersion: 'v4'
});
const { Body } = await S3.getObject({ Bucket: 'my-bucket', Key: 'index.html' }).promise();
console.log(Body.toString());
Instead of seeing <html...
in the console log, I am seeing the dreaded question mark characters which implies (I think), bad encoding:
��Y�r#��x�`�,b�J�ٲ��NR�yIٮ�!!���"���n�����Is�>}�n4pF�_���de�nq�~�]� f�����v��۔*�㺮Ý� Hdž�<�! �c�5�1B��,#|Ŵ;ֶ�U����z� �Qi��j�0��V ���H���...etc
I have literally tried everything including, but not limited to:
Body.toString('utf-8');
Body.toString('ascii');
Body.toString('base64');
decoder.write(Body.toString('base64'));
I think I must be missing something really obvious here as I cannot find anyone else facing the same issue. I thought it might be to do with the encryption but my other Lambda Edge function reads an image file without issues so I assume it has to be something to do with encoding that I haven't thought of.
I believe the issue may be related to the fact that the file is gzipped.
Here is a print of the response from S3:
{
AcceptRanges: 'bytes',
LastModified: 2023-02-17T19:44:41.000Z,
ContentLength: 1598,
ETag: 'some-key',
CacheControl: 'max-age=31536000',
ContentEncoding: 'gzip',
ContentType: 'text/html; charset=UTF-8',
ServerSideEncryption: 'AES256',
Metadata: { etag: 'some-key' },
Body: <Buffer 1f 8b 08 00 00 00 00 00 00 03 cd 59 db 72 23 b7 11 fd 15 78 f2 60 bb 2c 62 ee b7 8d c8 4a b2 d9 b2 b7 ca 4e 52 bb 79 49 d9 ae 14 06 e8 21 21 cd 0c a6 ... 1548 more bytes>
}
The issue was caused by the fact that the index.html
file was gzipped. The solution to handling this is as follows:
const AWS = require('aws-sdk');
const zlib = require('zlib');
const S3 = new AWS.S3({
signatureVersion: 'v4'
});
const { Body } = await S3.getObject({ Bucket: 'my-bucket', Key: 'index.html' }).promise();
const body = zlib.unzipSync(Body).toString();
console.log(body);
However, given that this code is being deployed within a Lambda Edge function, speed is essential! With that in mind, it would/should be faster to actually utilise https.get
as this will automatically unzip the contents of the file prior to returning the Buffer
stream.