AWS无服务器lambda上的角度SSR返回随机数和字符



我正在尝试使用无服务器和lambda将Angular SSR应用程序部署到AWS。作为一个完全的初学者,我使用这个入门项目来做到这一点。我没有更改任何代码,只是将项目名称更改为";公开";。自述文件中有一个专门的部分解释了如何做到这一点("查找并将单词"ngx serverless starter"替换为您的项目名称"(。

之后,我将该项目上传到AWS。这是日志:

Serverless: Stack update finished...
Service Information
service: public
stage: dev
region: us-east-1
stack: public-dev
resources: 12
api keys:
None
endpoints:
GET - https://u3vc0nd65k.execute-api.us-east-1.amazonaws.com/dev
GET - https://u3vc0nd65k.execute-api.us-east-1.amazonaws.com/dev/{proxy+}
functions:
api: public-dev-api
layers:
None

所以我认为它有效。如果我点击提供的URL,尽管我看到了随机数字和字符(由于堆栈溢出的字符限制,我不得不将其截断(:

PCFET0NUWVBFIGh0bWw+PGh0bWwgbGFuZz0iZW4iPjxoZWFkPgogIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KICA8dGl0bGU+Tmd4U2VydmVybGVzc1N0YXJ0ZXI8L3RpdGxlPgogIDxiYXNlIGhyZWY9Ii8iPgogIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MSI+CiAgPGxpbmsgcmVsPSJpY29uIiB0eXBlPSJpbWFnZS94LWljb24iIGhyZWY9ImZhdmljb24uaWNvIj4KPGxpbmsgcmVsPSJzdHlsZXNo

在我看来,可能有一些错误的内容类型被返回,但我真的无法理解

什么是随机字符串

";随机数和字符";实际上不是随机的,而是HTML页面的base64编码。如果你对响应进行base64解码,你会得到一个HTML页面。

为什么我要使用base64编码

module.exports.handler = serverlessExpress({
app,
binarySettings: {
isBinary: ({ headers }) => true,
contentTypes: [],
contentEncodings: [],
},
});

base64编码是由lambda.js中的binarySettings引起的

二进制设置

确定响应在被返回到事件源,例如,当返回图像或压缩文件。由于API网关和其他事件,这是必要的源不能直接处理二进制响应。这个事件源负责将其转换回二进制文件格式,然后返回给客户端。

默认情况下,这是基于content-encoding和应用程序返回的content-type标头。如果您需要可以指定binarySettings作为对此的附加控制。

{   
binarySettings: {
isBinary: ({ headers }) => true,
contentTypes: ['image/*'],
contentEncodings: []   
}
}

您在此处提供的任何值也应在API网关上指定API在SAM中,这看起来像:

ExpressApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
BinaryMediaTypes: ['image/*']

为什么有启用base64编码的选项

base64编码选项主要用于通过AWS API网关发送二进制数据作为响应的场景(例如:图像、GZip文件等(。为了使二进制内容正常工作,您需要以base64编码格式发送响应以进行AWS Lambda代理集成:

要为AWS Lambda代理集成处理二进制有效载荷,您必须base64对函数的响应进行编码。您还必须配置API的二进制媒体类型。API的二进制媒体类型配置是API将其视为的内容类型的列表二进制数据。示例二进制媒体类型包括image/png或应用程序/八位字节流。您可以使用通配符(*(涵盖多种媒体类型。例如,*/*包括所有内容类型。

修复内容类型标头(可选(

默认情况下,页面响应的Content-Type标头为application/json。您可以在server.tsserverless.ts中将其更改为text/html。这并不是解决问题所必需的,但最好配置正确的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 }] });
});

选项1:禁用响应的base64编码

lambda.js中注释掉binarySettings,使响应不是base64编码的。

module.exports.handler = serverlessExpress({
app,
// binarySettings: {
//   isBinary: ({ headers }) => true,
//   contentTypes: [],
//   contentEncodings: [],
// },
});

选项2:使用API网关转换base64响应

如果在API网关中设置binaryMediaTypes,它将自动将base64编码转换为正确的响应。如果在可选步骤中未更改Content-Type,请使用application/json

provider:
name: aws
runtime: nodejs12.x
lambdaHashingVersion: 20201221
memorySize: 192
timeout: 10
apiGateway:
binaryMediaTypes:
- 'text/html'

我创建了一个禁用base64编码的PR(选项1(。

注意:在新部署后,我不得不在浏览器中进行硬刷新以更正响应。

接受的答案似乎解决了我的问题,但结果是图像没有渲染。奇怪的是,没有错误(状态代码200(,但它们不会出现。

这条线索把我引向了正确的方向:

我在lambda.js:中再次添加了二进制设置

module.exports.handler = serverlessExpress({
app,
binarySettings: {
isBinary: ({ headers }) => true,
contentTypes: [],
contentEncodings: [],
},
});

之后,我更改了API网关设置,并在Binary Media Types中添加了*/*。这就成功了。

相关内容

  • 没有找到相关文章

最新更新