What is the random string of characters?
The "random numbers and characters" are not actually random but a base64 encoding of the HTML page. If you do a base64 decoding of the response you would get a HTML page.
Why am I getting base64 encoding?
module.exports.handler = serverlessExpress({
app,
binarySettings: {
isBinary: ({ headers }) => true,
contentTypes: [],
contentEncodings: [],
},
});
The base64 encoding is due to binarySettings in lambda.js. From the binarySettings section in serverless-express README:
binarySettings
Determine if the response should be base64 encoded before being
returned to the event source, for example, when returning images or
compressed files. This is necessary due to API Gateway and other event
sources not being capable of handling binary responses directly. The
event source is then responsible for turning this back into a binary
format before being returned to the client.
By default, this is determined based on the content-encoding
and
content-type
headers returned by your application. If you need
additional control over this, you can specify binarySettings
.
{
binarySettings: {
isBinary: ({ headers }) => true,
contentTypes: ['image/*'],
contentEncodings: []
}
}
Any value you provide here should also be specified on API Gateway
API. In SAM, this looks like:
ExpressApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
BinaryMediaTypes: ['image/*']
Why is there an option to enable base64 encoding?
The base64 encoding option is mainly used for scenarios where you are sending binary data as response through AWS API Gateway (for example: images, GZip files, etc.). For binary content to work correctly, you need to send the response in base64 encoded format for AWS Lambda proxy integration:
To handle binary payloads for AWS Lambda proxy integrations, you must
base64-encode your function's response. You must also configure the
binaryMediaTypes for your API. Your API's binaryMediaTypes
configuration is a list of content types that your API treats as
binary data. Example binary media types include image/png or
application/octet-stream. You can use the wildcard character (*) to
cover multiple media types. For example, */* includes all content
types.
Fixing the Content-Type header (optional)
By default, the page response has a Content-Type
header of application/json
. You can change this to text/html
in server.ts
and serverless.ts
. This isn't really required for solving the issue, but it is better to configure the correct Content-Type
.
// All regular routes use the Universal engine
server.get('*', (req, res) => {
res.header('Content-Type', 'text/html');
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
Option 1: Disable base64 encoding of response
Comment out binarySettings
in lambda.js
so that the response isn't base64 encoded.
module.exports.handler = serverlessExpress({
app,
// binarySettings: {
// isBinary: ({ headers }) => true,
// contentTypes: [],
// contentEncodings: [],
// },
});
Option 2: Use API Gateway to convert the base64 response
If you set binaryMediaTypes
in API Gateway, it will automatically convert the base64 encoding to a proper response. Use application/json
if you haven't changed the Content-Type
in the optional step.
provider:
name: aws
runtime: nodejs12.x
lambdaHashingVersion: 20201221
memorySize: 192
timeout: 10
apiGateway:
binaryMediaTypes:
- 'text/html'
I created a PR which disables the base64 encoding (Option 1).
Note: I had to do a hard refresh in my browser to correct the response after a new deployment.