首页 > 解决方案 > 如何在与 API Gateway 集成的 AWS Lambda python 中执行 302 重定向?

问题描述

我正在尝试使用无服务器架构构建一个非常轻量级的静态网站:

  1. 用户使用登录信息填充表单
  2. 向 AWS API Gateway 提交操作路由,然后触发 AWS Lambda Python 函数,该函数将用户登录到 3rd 方站点,获取一些数据并将其保存到 s3
  3. 保存数据后,我想在客户端向用户提供数据的下载按钮

我尝试在 API Gateway 中使用 302 重定向来执行此操作,无论是否集成 lambda 代理集成,以便我可以将用户重定向到从 s3 提取数据的不同网页。

使用代理集成我每次都会收到内部服务器错误。

没有它,我只是将 json 响应返回给用户,而不是实际的重定向。

这是我的 lambda 函数中响应的 python 代码(这个 json 是当前返回给用户的内容,而不是将它们带到 url https://example.com):

return {
        "isBase64Encoded": False,
        "statusCode": 302,
        "headers": {
            "Location": "https://example.com"
        },
        "multiValueHeaders": {},
        "body": "Success!!!"
    }

我将“Location”标头添加到 API Gateway 中的方法响应中,并将其映射到集成响应中的 integration.response.headers.location(当我尝试不使用 lambda 代理时)。

不过,这一切都没有成功。

使用代理它的内部服务器错误仅发生在 html 表单中(在 api 网关控制台或 lambda 控制台中测试时不会发生),并且没有代理它不会重定向到 Location 标头中的值,只是打印 json到 api 的 url。

非常感谢任何帮助、指导或建议!

谢谢你的时间。

标签: pythonredirectaws-lambdaaws-api-gateway

解决方案


分享我是如何解决这个问题的,以防其他人遇到类似问题。

event由于我从 API Gateway解析变量的方式,我在使用 Lambda 代理集成时遇到了内部服务器错误。

假设您的 API Gateway 配置为Lambda 代理集成并且您的 Lambda 函数是用 python 编写的,那么当从静态 s3 http 表单触发时,以下代码应该会导致成功的 302 重定向:

import urllib.parse
from furl import furl

def lambda_handler(event, context):

     body = urllib.parse.unquote(event["body"])
     furledBody = furl("/abc?" + body)
     
     parameter1 = furledBody.args["parameter1"]
     parameter2 = furledBody.args["parameter2"]
     parameter3 = furledBody.args["parameter3"]

     #Do stuff with body parameters

     return {
          "isBase64Encoded": False,
          "statusCode": 302,
          "headers": {
               "Location": "https://example.com"
          }
          "multiValueHeaders": {},
          "body": ""
     }

然而,这不是我为我的用例提供的设计,我的 lambda 函数下载回客户端供用户下载的数据。

相反,我将我的 lambda 响应配置为包含在客户端自动呈现为对 http 表单请求的响应的 html。在 html 中,我包含了之前在 lambda 中生成的 S3 预签名 URL:

import boto3
s3 = boto3.client('s3')

presignedURL = s3.generate_presigned_url('get_object',{'Bucket': '[insert bucket name]', 'Key': '[insert key aka file name including the full path]'}, 500, 'GET'}

responseBody = (
    "<html>"
        "<head></head>"
        "<body>"
            "<a href=\"" + presignedURL + "\"download><button>Download</button></a>"
        "</body>"
    "</html>")
    
return {
     "isBase64Encoded": False,
     "statusCode": 200,
     "headers": {
         "Content-Type": "text/html"
     }
     "multiValueHeaders": {},
     "body": responseBody
}

推荐阅读