如何将来自POST的params从Amazon API Gateway传递到AWS Lambda

时间:2015-08-17 18:15:51

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

在这个问题中How to pass a querystring or route parameter to AWS Lambda from Amazon API Gateway

显示了如何使用API​​网关将查询字符串参数映射到AWS lambda。我想做同样的事情,但映射POST值而不是查询字符串。我试过了:

{
    "values": "$input.params()"
}

但没有用,我没有看到实际的表单数据。顺便说一下,我发帖使用:

application/x-www-form-urlencoded

我从lambda函数得到了我的回复,所以我知道它正在调用lambda,但我的问题是我在任何地方都看不到POST参数。我可以弄清楚如何映射它们。我把所有我在Lambda方面的所有内容转移到了这里:

 {"values":"{path={}, querystring={}, header={Accept=*/*, Accept-Encoding=gzip, deflate, Accept-Language=en-US,en;q=0.8, 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=US, Content-Type=application/x-www-form-urlencoded, Origin=chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop, Postman-Token=7ba28698-8753-fcb1-1f48-66750ce12ade, Via=1.1 6ba5553fa41dafcdc0e74d152f3a7a75.cloudfront.net (CloudFront), X-Amz-Cf-Id=sc8C7dLcW0BHYopztNYrnddC0hXyFdBzHv0O9aWU1gKhd1D_J2HF3w==, X-Forwarded-For=50.196.93.57, 54.239.140.62, X-Forwarded-Port=443, X-Forwarded-Proto=https}}"}

11 个答案:

答案 0 :(得分:57)

r7kamura的答案很好。此外,这是application/x-www-form-urlencoded可理解且强大的映射模板示例,适用于所有情况(假设POST):

{
    "data": {
        #foreach( $token in $input.path('$').split('&') )
            #set( $keyVal = $token.split('=') )
            #set( $keyValSize = $keyVal.size() )
            #if( $keyValSize >= 1 )
                #set( $key = $util.urlDecode($keyVal[0]) )
                #if( $keyValSize >= 2 )
                    #set( $val = $util.urlDecode($keyVal[1]) )
                #else
                    #set( $val = '' )
                #end
                "$key": "$val"#if($foreach.hasNext),#end
            #end
        #end
    }
}

它会转换

的输入
name=Marcus&email=email%40example.com&message=

{
    "data": {
                "name": "Marcus",
                "email": "email@example.com",
                "message": ""
    }
}

Lambda处理程序可以像这样使用它(这个返回所有输入数据):

module.exports.handler = function(event, context, cb) {
  return cb(null, {
    data: event.data
  });
};

答案 1 :(得分:20)

您可以通过在集成设置中配置映射模板,将任何请求正文数据转换为有效的JSON格式,以便AWS Lambda可以接收它。

目前似乎亚马逊API网关尚未正式支持application / x-www-form-urlencoded,但是avilewin在AWS论坛上发布了a solution来做这件事。在映射模板中,您可以使用Velocity Template Language (VTL),因此您需要做的是配置将application / x-www-form-urlencoded格式转换为有效JSON格式的映射模板。当然这是一个肮脏的解决方案,但我认为这是目前唯一的方法。

答案 2 :(得分:15)

如果启用Lambda代理集成 enter image description here

POST正文可从以下网址获得:

event['body']['param']

GET参数和标题也可以通过

获得
event['pathParameters']['param1']
event["queryStringParameters"]['queryparam1']
event['requestContext']['identity']['userAgent']
event['requestContext']['identity']['sourceIP']

答案 3 :(得分:11)

您可以使用API​​网关模板将params转换为JSON: https://forums.aws.amazon.com/thread.jspa?messageID=673012&tstart=0#673012

或者您可以使用QueryString解析器pacakge在lambda函数本身中执行此操作:https://www.npmjs.com/package/qs

var qs = require('qs');
var obj = qs.parse('a=c');  // { a: 'c' } 

如果亚马逊为这样的功能添加了内置支持,我会使用它,但在那之前我个人更喜欢第二种方式,因为如果出现问题,它更干净,更容易调试。

2017年7月更新

您可以使用默认支持它的代理集成: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html

答案 4 :(得分:4)

扩展@ markus-hybrow答案:

{
        #foreach( $token in $input.path('$').split('&') )
            #set( $keyVal = $token.split('=') )
            #set( $keyValSize = $keyVal.size() )
            #if( $keyValSize >= 1 )
                #set( $key = $util.urlDecode($keyVal[0]) )
                #if( $keyValSize >= 2 )
                    #set( $val = $util.urlDecode($keyVal[1]) )
                #else
                    #set( $val = '' )
                #end
                "$key": "$util.escapeJavaScript($val)"#if($foreach.hasNext),#end
            #end
        #end
    }

这消除了“数据”,并且还解决了如果您在其中一个值中使用双引号引起的情况。

答案 5 :(得分:2)

我在Content-Typeapplication/x-www-form-urlencoded的情况下实施了一个带有POST请求的API。如果您只想获得类似于GET请求的长查询字符串,那么请使用此映射语法。

{
    "body": "$input.body"
}

注意,您也可以添加其他映射...我将其留下来解决原始问题。

我最初在实施API时使用的 {strong> Here's a blog tutorial 。我的lambda函数然后解析查询字符串将数据传递到其他进程。

答案 6 :(得分:1)

这适用于lambda集成。 假设您的POST请求正文是例如

{
   "name" : "Hello",
   "address" : "Cool place" 
}

你可以像这样访问它:

if (event.body !== null && event.body !== undefined) {
   let body = JSON.parse(event.body)
   let name = body.name;
   let address = body.address;
}

此处有更多信息:http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html

答案 7 :(得分:1)

我发现一个非常简单的解决方案,我认为值得分享,因为我花了一些时间来找到这个最小的工作代码。

如果您有一个通用表单,发送内容类型为application / x-www-form-urlencoded的数据,只需标记" Lambda代理集成",那么您将在event.body中找到编码的表单数据可以使用Node.js查询字符串本机模块进行解析。

const querystring = require('querystring')

function handler (event, context, callback) {
  // Read form data.
  const { user, pass } = querystring.parse(event.body)

  // Follows your code to handle request.
}

答案 8 :(得分:0)

一个简单的函数,用于返回发布值的有序字典:

import urllib
from collections import OrderedDict
postdata = ''

def GetPostData(body):
    #postdata = OrderedDict()
    postdata = {}
    for items in body.split('&'):
        vals = items.split('=')
        postdata[vals[0]] = urllib.parse.unquote(vals[1])
    return postdata

#Testing it out:
#Assume you get body from event['body'] or body = event.get['body']
body = 'text=This%20works%20really%20well%21%245123%21%403%2146t5%40%2341&anotherkey=isawesome23412%201%21%403%21%40312'

postdata = GetPostData(body)
print(postdata['text'])
#returns 'This works really well!$5123!@3!46t5@#41'
print(postdata['anotherkey'])
#returns 'isawesome23412 1!@3!@312'

为避免在缺少已发布项目时出现关键错误, 您应该改用value = postdata.get(''),因为如果不存在该键,则值将为None。

答案 9 :(得分:0)

如果您想通过POST将所有正文发送到Lambda函数,请在Integration Request处写上:

{
    "values": $input.json('$')
}

如果要从身体构建自己的结构,请执行以下操作:

{
    "values": {
        "body-param1": $input.json('body-param1'),
        "others": {
            "body-param2": "$input.json('body-param2')",
        }
    }
}

其中body-param1是数字,而body-param2是字符串。

如果要发送标题,请执行以下操作:

{
    "headers": {
        #foreach($param in $input.params().header.keySet())
            "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext), #end
        #end
    }
}

答案 10 :(得分:0)

2021 年 6 月

用于 POST 的 application/x-www-form-urlencoded 映射模板: (Python)

from base64 import b64decode
from urllib.parse import parse_qs

def lambda_handler(event, context):
    params = parse_qs(b64decode(event.get('body')).decode('utf-8'))
    print(params.get('name')[0])
    print(params.get('email')[0])

同样,使用 params 字典和任何参数名称执行您想要执行的任何操作。