如何配置serverless.yml或AWS API网关或AWS Lambda处理程序以从POST请求读取request.header

时间:2018-12-20 05:08:39

标签: python amazon-web-services aws-lambda aws-api-gateway serverless-framework

我试图将使用flaskserverless framework创建的API部署到AWS lambda和API网关,但是我无法读取正确的标头。

我确实从https://stackoverflow.com/a/43830950/2806237阅读了一些帖子,这表明请求详细信息将在处理程序函数的event中可用。

但是,我使用wsgi.handler作为处理程序,所以我应该如何读取event中存在的wsgi.hander变量?我应该创建自己的处理程序,还是可以从某处获取event的请求详细信息?

仅供参考,我正在使用AWS V4签名对客户端和服务器端的每个请求进行签名,然后比较每个签名以确保请求得到保护。这将生成如下标题:

Host: 10.0.0.48:9998
Connection: keep-alive
Content-Length: 37
Origin: xxxxxxxxxxxxxxxxxxxx
Authorization: AWS4-HMAC-SHA256 Credential=usernameHere/20181220///aws4_request, SignedHeaders=content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target, Signature=c57780866a6380b92678e8a9d52d8220d3ecc836f4475b8334c553cf4dbb9ad4
Content-Type: application/json;charset=UTF-8
X-Amz-Content-Sha256: 615d42718684ea2b59442a6ce3dc6302404839b0875bca365a6e07e0d65f577c
Accept: application/json, text/javascript, */*; q=0.01
X-Amz-Target: SchoolLearnMeter_1980121.GetPassword
X-Amz-Date: 20181220T021132Z
User-Agent: Mozilla/5.0 (X11; CrOS x86_64 11210.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3593.0 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9.

但是,标题如下:

Content-Length: 36
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Cloudfront-Forwarded-Proto: https
Cloudfront-Is-Desktop-Viewer: true
Cloudfront-Is-Mobile-Viewer: false
Cloudfront-Is-Smarttv-Viewer: false
Cloudfront-Is-Tablet-Viewer: false
Cloudfront-Viewer-Country: AU
Host: XXXXX.execute-api.ap-southeast-2.amazonaws.com
Postman-Token: 8742a77d-4e1a-4d0c-ba6a-6df15795e7c8
User-Agent: PostmanRuntime/7.4.0
Via: 1.1 098fddbcdf00e65b8479d1d17b41d28a.cloudfront.net (CloudFront)
X-Amz-Cf-Id: HafOPHJfXOungGylHkX4Y3klvdBR-kzoC-xz1aqNXo-4K2KbbsD_lg==
X-Amz-Date: 20181220T034409Z
X-Amzn-Trace-Id: Root=1-5c1b100a-7a69d8e08c9ee3e0e6b799e0
X-Forwarded-For: 115.187.209.206, 70.132.29.75
X-Forwarded-Port: 443
X-Forwarded-Proto: https 

这是application.py代码

from flask import Flask, request, jsonify
import os, sys
import hashlib
import json
from dbConnection import DBConncetion
from awssigner import AWSSigner

application = Flask(__name__)
db_conn_str = os.environ["Chrome_DB"]
responseMessage = {"ResponseMessage":""}

@application.route("/u", methods=["POST"])
def getUserPasswordByUsername():
    try:
        serverSignature = AWSSigner(request).getSignature(json.dumps(request.get_json(Force=true)).replace(": ",":"))
        agentSignature = request.headers.get("Authorization").split("Signature=",1)[1]
        if(serverSignature == agentSignature):
            #Do something here
        else:
            raise Exception
    except:
        responseMessage["ResponseMessage"] = "There are some errors occured, please try again later"
        response = application.response_class(
            response= json.dumps(responseMessage),
            status=500,
            mimetype = "application/json"
        )
        return response

if __name__ == "__main__":
    application.run()
    #application.run("0.0.0.0", 9998, debug = True)

这是serverless.yml文件

service: testapiservices

plugins:
 - serverless-python-requirements
 - serverless-wsgi

custom:
 wsgi:
   app: application.application
   packRequirements: false
 pythonRequirements:
   dockerizePip: non-linux

provider:
 name: aws
 runtime: python3.7
 stage: dev
 region: ap-southeast-2

functions:
 app:
   handler: wsgi.handler
   environment:
     AppId: XXX
     Chrome_DB: XXX
   events:
     - http:
         cors: true
         method: post
         path: /
     - https: 'ANY{proxy+}'
   vpc:
     securityGroupIds:
       - XXX
     subnetIds:
       - XXX
       - XXX

1 个答案:

答案 0 :(得分:0)

serverless-wsgi提供了一个烧瓶包装器供您使用,因此它实际上在后台处理event变量并将其映射到Flask request

导入烧瓶请求对象,并在代码中使用它:

from flask import Flask, request

阅读request周围的Flask文档,但是它将包含所有在lambda event中期望的标头,等等

此外,您正在使用代理User-Agent: PostmanRuntime/7.4.0发送具有第二个标头集的请求。您实际上是作为开发人员设置这些标头的,所以我很困惑为什么您希望它们匹配,除非您将它们设置为匹配。

您要具体检查哪个标头?