javascript - 当调用源自浏览器 AWS 开发工具包时,AWS Lambda 设置响应标头
问题描述
使用带有 AWS Lambda 代理集成的 API Gateway 设置响应标头非常简单,如下所示:
import zlib from 'zlib';
exports.handler = async (event, context, callback) => {
const body = zlib.gzipSync(JSON.stringify({ data: 'mock' }));
const headers = {};
headers['Content-Type'] = 'application/json';
headers['Content-Encoding'] = 'gzip';
const responseObject = {
statusCode: 200,
headers,
body: body.toString('base64'),
isBase64Encoded: true
};
return callback(null, responseObject);
}
一切都按预期压缩返回。因为我们设置了内容编码,所以浏览器会解压响应。
问题是,当直接使用 AWS SDK JS 从浏览器调用 Lambda 函数时,如何类似地设置标头?API Gateway 是在之前的设置中实现标头的服务,在 AWS Lambda 标头前面没有 API Gateway 将被忽略并通常设置为:
access-control-allow-origin: *
access-control-expose-headers: x-amzn-RequestId,x-amzn-ErrorType,x-amzn-ErrorMessage,Date,x-amz-log-result,x-amz-function-error
content-length: 1242
content-type: application/json
date: Fri, 26 Apr 2019 00:36:35 GMT
status: 200
x-amz-executed-version: $LATEST
x-amzn-remapped-content-length: 0
x-amzn-requestid: <REDACTED>
x-amzn-trace-id: <REDACTED>
AWS SDK JS 浏览器调用代码如下所示:
import AWS from 'aws-sdk';
AWS.config.region = 'us-east-1'; // Region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: '<SOME IDENTITY>',
});
const AWSLambda = new AWS.Lambda({region: REGION, apiVersion: '2015-03-31'});
const parameters = {
FunctionName : 'MyFunctionName',
InvocationType : 'RequestResponse',
LogType : 'None',
Payload: JSON.stringify({msg: 'hello lambda'})
};
(async () => {
const response = await AWSLambda.invoke(shopParameters).promise();
console.log(response);
})();
返回的响应是上面的响应对象,作为带有通用标头的字符串。浏览器不会解压缩 gzip 压缩的内容,可能是因为未设置内容编码标头。从浏览器调用 AWS Lambda 时,将整个 Lambda 响应对象视为响应,并且不执行 API Gateway 发生的任何转换。例如,API 网关将获取响应对象结构并将响应对象标头映射到响应,然后再发送到客户端。
没有 API Gateway 就没有办法设置 AWS Lambda 标头吗?或者是使用https://github.com/nodeca/pako之类的东西在客户端手动解压缩 gzip 内容的唯一选择(叹气)。
不使用 API 网关的想法来自此处找到的 AWS 文档,例如避免 API 网关成本:https ://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/browser-invoke-lambda -function-example.html
非常感谢任何指导、专业知识和想法!
解决方案
不,如果没有Lambda 服务 API(通常是 API 网关)前面的 东西,就无法做到这一点。
您const responseObject
实际上是使用 API Gateway 指定的格式创建响应 - Lambda 服务不执行响应解释。这就是为什么它对您的响应中的标头没有影响,以及为什么 base64 仍未翻译——整个结构是特定于 API 网关的。Lambda 只是返回 JSON。
如果响应足够小,那么“某物”也可以是Application Load Balancer,它可能会或可能不会很容易与 Cognito一起使用,尽管身份验证会有所不同。它使用与 API Gateway 基本相同的响应格式,并且平衡器在将其返回给浏览器之前对 base64 进行解码。
您还可以使用 CloudFront 的Lambda@Edge功能通过 HTTP(S) 调用 Lambda 函数,并设置自定义标头并自动解码 base64,但此服务没有内置的 Cognito 集成,与全功能的明显不同Lambda 服务,仅支持 Node.js 并在距离浏览器最近的任何 AWS 区域运行 Lambda 函数,而不是在创建它的区域以实现更好的全局性能。Lambda@Edge 还需要一种不同的输出格式——它是一种比 API Gateway 所期望的响应结构更精心设计的设计,但因此它也不能互换。
推荐阅读
- java - 单个 java 字段被映射到两个 JSON 字段与杰克逊
- javascript - 如果没有全局变量,函数将无法工作?
- python - Python:字典映射列表
- python - 数字小数舍入在 Pandas 中无法正常工作
- php - 向 sqlsrv_fetch_array 传递了一个无效参数
- java - 从 Android 通知中读取 Google Pay 通知的问题
- sqlite - 是否可以在没有分隔符的情况下将 .txt 文件中的数据加载到 sqlite?
- eclipse - 如何从 Eclipse Neon 连接到 SAP Web IDE Full-Stack?
- react-native - 如何在 Webview 中添加水平加载器
- javascript - 原型中自定义函数和原生函数的区别