javascript - 当调用源自浏览器 AWS SDK 时,AWS Lambda 设置响应 header

标签 javascript amazon-web-services aws-lambda aws-sdk-js

使用具有 AWS Lambda 代理集成的 API Gateway 设置响应 header 非常简单,如下所示:

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 函数时,如何设置类似的 header ? API Gateway 是在之前的设置中实现 header 的服务,AWS Lambda header 前面没有 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);
})();

返回的响应是上面的响应对象,作为带有通用 header 的字符串。浏览器不会解压缩 gzip 压缩的内容,可能是因为未设置内容编码 header 。从浏览器调用时,AWS Lambda 会将整个 Lambda 响应对象视为响应,并且不执行 API Gateway 中发生的转换。例如,API 网关会获取响应对象结构并将响应对象 header 映射到响应,然后再发送到客户端。

如果没有 API Gateway,是否无法设置 AWS Lambda header ?或者是使用类似 https://github.com/nodeca/pako 在客户端上手动解压缩 gzip 内容的唯一选项(叹)。

不使用 API Gateway 的想法来自此处找到的 AWS 文档,例如避免 API Gateway 成本: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 服务不对响应执行任何解释。这就是为什么它对响应中的 header 没有影响,以及为什么 base64 保持未翻译的原因——整个结构是 API 网关特定的。 Lambda 只是返回 JSON。

如果响应足够小,该“某物”也可以是 Application Load Balancer这可能很容易使用,也可能不太容易使用 with Cognito ,尽管身份验证会有所不同。它使用与 API Gateway 基本相同的响应格式,平衡器在将其返回到浏览器之前对 Base64 进行解码。

您还可以使用 CloudFront 的 Lambda@Edge 通过 HTTP(S) 调用 Lambda 函数功能,并设置自定义 header 并自动解码 base64,但该服务没有内置的 Cognito 集成,并且与功能齐全的 Lambda 服务明显不同,仅支持 Node.js 并在任何 AWS 区域运行 Lambda 函数离浏览器最近,而不是在创建它的区域,以获得更好的全局性能。 Lambda@Edge 还期望不同的输出格式 - 这是比 API Gateway 期望的响应结构更加精心设计的设计,但因此它也是不可互换的。

关于javascript - 当调用源自浏览器 AWS SDK 时,AWS Lambda 设置响应 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55859414/

相关文章:

javascript - window.location.href 是否具有服务器特定行为?

javascript - 改变第二轮setInterval的速度

amazon-ec2 - 单实例 Amazon EC2

mysql - Lambda (Python 3.6) PyMySql 查询 EXISTS 查询总是返回 1

java - Clojure AWS Lambda 函数中的 OpenCV 目标大于 250MB,如何减小其大小?

javascript - 通过Javascript中给定的不完整订单数组对对象数组进行排序

javascript - 半圆渐变js

amazon-web-services - 如何创建 aws ec2 公私 key 对

php - 无法在 php 中从 exec 或 shell_exec 执行 aws cli 命令

aws-lambda - 无服务器中一个端点的多种授权方类型