简体   繁体   English

如何在与 API 网关集成的 AWS Lambda python 中执行 302 重定向?

[英]How to perform 302 Redirect in AWS Lambda python integrated with API Gateway?

I am trying to build a very light weight static website with a form using a serverless architecture:我正在尝试使用无服务器架构构建一个重量非常轻的 static 网站:

  1. User populates the form with login info用户使用登录信息填充表单
  2. Submit action routes to AWS API Gateway which then triggers AWS Lambda Python function which logs the user in to 3rd party site, gets some data and saves it to s3 Submit action routes to AWS API Gateway which then triggers AWS Lambda Python function which logs the user in to 3rd party site, gets some data and saves it to s3
  3. Once the data is saved, I would like to provide a download button for the data back to the user at the client保存数据后,我想在客户端向用户提供数据的下载按钮

I've tried to do this using a 302 redirect in API Gateway both with and without lambda proxy integration so that I could redirect the user to a different webpage that pulls their data from s3.我尝试在 API 网关中使用 302 重定向来执行此操作,无论是否有 lambda 代理集成,以便我可以将用户重定向到从 s3 提取数据的不同网页。

Using proxy integration I get an Internal Server Error every time.使用代理集成我每次都会收到内部服务器错误。

Without it I just get the json response back to the user instead of an actual redirect.没有它,我只会将 json 响应返回给用户,而不是实际重定向。

Here is the python code for the response in my lambda function (this json is what comes back to the user currently instead of taking them to the url https://example.com ): Here is the python code for the response in my lambda function (this json is what comes back to the user currently instead of taking them to the url https://example.com ):

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

I added the "Location" header to the Method Response in API Gateway and mapped it to integration.response.headers.location in the Integration Response (when I tried without lambda proxy).我将“位置”header 添加到 API 网关中的方法响应中,并将其映射到集成响应中的 integration.response.headers.location (当我尝试不使用 Z945F3FC449518A73B9F5F32868CZDB 代理时)

No success with any of this though.不过,这一切都没有成功。

With proxy its an internal server error that only happens from the html form (doesn't happen when testing in api gateway console or lambda console), and without proxy it doesn't redirect to the value in the Location header, just prints the json to the url of the api. With proxy its an internal server error that only happens from the html form (doesn't happen when testing in api gateway console or lambda console), and without proxy it doesn't redirect to the value in the Location header, just prints the json到 api 的 url。

Any help, guidance or suggestions is much appreciated!非常感谢任何帮助、指导或建议!

Thanks for your time.谢谢你的时间。

Sharing how I figured this out in case someone else ever runs into a similar issue.分享我是如何解决这个问题的,以防其他人遇到类似问题。

I was getting an Internal Server error when using Lambda Proxy Integration because of the way I was parsing my event variable from API Gateway.由于我从 API 网关解析event变量的方式,在使用 Lambda 代理集成时出现内部服务器错误。

Assuming your API Gateway is configured to Lambda Proxy Integration and that your Lambda function is written in python, the below code should result in a successful 302 Redirect when triggered from a static s3 http form: Assuming your API Gateway is configured to Lambda Proxy Integration and that your Lambda function is written in python, the below code should result in a successful 302 Redirect when triggered from a static s3 http form:

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": ""
     }

This however is not the design I went with for my use case of providing the data my lambda function downloaded back to the client for the user to download.然而,这不是我为我的用例提供的数据的设计,我的 lambda function 下载回客户端供用户下载。

Instead I configured my lambda response to contain html that automatically rendered at the client as a response to the http form request.相反,我将 lambda 响应配置为包含 html,该响应在客户端自动呈现为对 http 表单请求的响应。 Within the html I include S3 pre-signed URLs that were generated earlier in the lambda:在 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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM