【问题标题】:How to serve binary data from AWS API Gateway with proxy integration?如何通过代理集成从 AWS API Gateway 提供二进制数据?
【发布时间】:2017-03-13 13:34:09
【问题描述】:

我正在使用 AWS API Gateway (APIG) 和 Lambda 函数构建一个无服务器网站。我必须使用代理集成,因为后面的 Lambda 函数必须接收 http 请求标头。同时,需要提供一些二进制数据。就我而言,是 favicon.ico 文件。其他人可能希望提供动态创建的 PDF 或 Excel 文件。 APIG 为此目的提供二进制支持。使用 base64 编码数据并配置该 MIME 内容类型,以便在将其提供给客户端之前对其进行解码。但是,这不适用于代理集成。代理集成只是跳过了集成响应部分。

我尝试将 favicon.ico 的请求重定向到 S3 端点,但浏览器显示奇怪的行为。因为 ico 文件来自不同的重定向域,而不是同一个域。

使用 base64 对其进行编码并让客户端浏览器对其进行解码不是一种选择,因为这不是标准的,并且可能不适用于所有浏览器。

我假设在 AWS 为此添加新功能之前我无法做任何其他事情。有没有人研究过这个问题?有什么想法或建议吗?

【问题讨论】:

    标签: api amazon-web-services lambda proxy gateway


    【解决方案1】:

    在这里回答我自己的问题。您应该前往 AWS 论坛了解 AWS 问题。这里不是我的 AWS 用户。

    答案:代理集成的二进制支持确实有效,它适用于传入和传出响应。

    与此相关的因素有3个:

    1. APIG 二进制支持设置中的 MIME 类型(我在控制台上设置)
    2. 传入和传出 JSON 中的“isBase64Encoded”值
    3. 传出 JSON 中的“Content-type”值

    上面的答案意味着是的,您可以接受文件,并且再次是的,您可以通过代理集成吐出文件。

    当用户使用正文“发布”时,如果您设置的 MIME 类型与之匹配,APIG 会将整个正文部分编码为 base64,并使用“isBase64Encoded”值指示这一点。传出响应也会发生同样的事情。如果您想使用二进制数据进行响应,请将其编码为 base64 并在传出的 JSON 中将该值设置为 true。

    对于传入的请求,它仅取决于一个因素,即您设置的 MIME 类型。对于传出,JSON 中的指示符和 MIME 类型这两个条件必须匹配。

    为简单起见,我只是将 MIME 类型设置为 */*。每当用户在正文中提交任何内容时,让 APIG 编码然后我解码。每当我用二进制响应时,我只需设置指标并在 base64 中编码。我不会对 test/html(未压缩)等其他类型执行此操作。

    【讨论】:

    • 我正在尝试在我的一个端点中返回一个 PDF,并将其编码为 base64 并将“isBase64Encoded”设置为 true。但是,我返回的 PDF 似乎没有正确解码。如果我在文本编辑器中打开文件,手动解码并保存,那么我可以查看 PDF。任何想法为什么会发生这种情况?
    • JPL,检查您的 MIME 设置是否支持二进制。
    • 自从我上次发表评论以来,我添加了对所有类型的二进制支持,/,它可以工作,但它会混淆非二进制类型,例如 JSON。如果我输入 application/pdf 甚至 application/*,API Gateway 将无法识别这些内容并且不会正确处理该类型。不知道是格式不对还是有其他设置。
    • 我也遇到了 API Gateway 的问题,它只是返回 base64 内容而不先解码它。我在回复中设置了Content-Type 标头,并在Binary Support 控制台中设置了 MIME 设置——不幸的是,它仍然无法正常工作。
    • 啊,终于...我在 API 的“设置”部分将application/pdf 设置为“二进制媒体类型”。这需要 Accept 标头。但是将媒体类型更改为*/* 意味着不需要Accept 标头(至少Chrome 如此)。好的。虽然这可能会干扰返回 JSON。一次一件事。
    【解决方案2】:

    在 Lambda 代理集成的情况下,有两个要求:

    • 二进制文件应在函数的响应中进行 base64 编码,包括设置为“true”的“isBase64Encoded”属性和“Content-Type”标头,以向客户端指示它返回的数据类型。请参阅 [1] 中的示例。

    • API 设置上的“binaryMediaTypes”必须支持这样的“Content-Type”,因此有效负载可以作为二进制处理 [2]。

    注意:对于代理集成,API Gateway 将整个请求传递到您的后端,您无法修改传递行为 [3]。

    如果您使用“/”通配符作为二进制媒体类型,并且来自 Lambda 的响应被标记为未经过 base64 编码,则 Lambda 响应将不会被视为二进制,并且响应将以文本格式返回(例如,base64 编码,以防您对文件进行编码)。请注意,如果您的客户端不准备处理文本响应,它可能会看到您的二进制文件已损坏..

    如果后端集成接收到的负载是 base64 编码的,API Gateway 会为注册二进制支持的 mime 类型应用 base64 解码。

    使用映射模板返回二进制文件(一般):

    如果您需要在集成响应中选择“CONVERT_TO_BINARY”,则返回带有映射模板的二进制文件的问题,这将在应用映射模板之前应用,这将导致失败。映射模板仅用于且专门用于应用程序/json 有效负载。将其与其他内容类型和二进制文件一起使用效果不佳,因为映射模板并不适用于这些内容。

    您提到的映射模板不起作用。如果您想要一个二进制文件作为响应,则 CONVERT_TO_BINARY 将在映射模板之前应用,因此这将不起作用。这是映射模板的限制,因此建议使用 Lambda 代理集成,或仅从您的 Lambda 模板重新调整 base64 编码的有效负载,其中没有 JSON 或其他数据。使用 $util.base64Decode 也不会生成有效的二进制文件,因为 API Gateway 仍会尝试将其解释为 application/json,因此有效负载将被破坏。

    以下是您可以考虑的选项:

    1- 从您的 lambda 中将 application/pdf 作为 base64 编码字符串返回,然后在集成响应传递中应用 CONVERT_TO_BINARY。您还需要在集成响应和方法响应中静态指定 Content-Type 响应标头。将响应映射模板留空,以便传递正文并转换为适当的二进制文件。

    2- 使用 Lambda 代理集成并像您一样返回有效负载,标头、正文作为 base64 编码的有效负载和“isBase64Encoded”:true。 API Gateway 将负责设置正确的标头并将文件作为二进制文件返回。

    【讨论】:

      【解决方案3】:

      关于如何解决“application/pdf”标头不起作用并避免使用 */*: 请求中的“Accept”标头必须与网关上的二进制媒体类型完全匹配

      • 如果 Accept 为“*/*”,网关上的 BinaryMediaType 必须为“*/*” (应用程序/pdf 将不起作用)。
      • 如果 Accept 是“application/pdf”(或 image/png...),则 网关上的 BinaryMediaType 必须是“application/pdf”(*/* 不会 工作。)。

      【讨论】:

        【解决方案4】:

        我遇到了类似的情况,Node lambda 函数从服务层返回二进制 blob(PDF)。

        1. 在网关上配置 / 作为二进制媒体类型。 (我尝试使用 application/pdf,但没有用?)
        2. 确保来自服务层的响应正文未转换为字符串(我使用的是请求,默认情况下它为我提供字符串)。我发送 encoding: null 连同请求
        3. 当我从服务层获取 Buffer 数据时,我使用 Buffer 将响应体转换为 base64 编码。
        4. 在 lambda 输出中,我将 isBase64Encoded 设置为 true

        参考:here

        【讨论】:

          猜你喜欢
          • 2018-05-04
          • 1970-01-01
          • 2021-07-29
          • 1970-01-01
          • 2019-06-19
          • 2017-04-07
          • 2017-11-26
          • 1970-01-01
          • 2019-06-05
          相关资源
          最近更新 更多