如何从Amazon API Gateway将查询字符串或路由参数传递到AWS Lambda


348

例如,如果我们想使用

GET /user?name=bob

要么

GET /user/bob

您如何将这两个示例作为参数传递给Lambda函数?

我在文档中看到了有关设置“映射自”的信息,但是在API Gateway控制台中找不到该设置。

  • method.request.path.parameter-name代表parameter-name在“方法请求”页面中定义的路径参数。
  • method.request.querystring.parameter-nameparameter-name表示在“方法请求”页面中定义的查询字符串参数。

即使定义了查询字符串,我也看不到这些选项中的任何一个。

Answers:


298

自2017年9月起,您不再需要配置映射来访问请求正文。

您需要做的就是在资源下的“集成请求”下选中“使用Lambda代理集成”。

在此处输入图片说明

然后,您将能够像这样访问查询参数,路径参数和标题

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

23
这是一个很好的提示。但是,请记住,打开Lambda代理集成可能会导致“格式错误的Lambda代理响应”错误。解决方法如下:stackoverflow.com/questions/43708017/…–
AaronBaker

5
在保持实现实现RequestHandler提供的透明反序列化的同时,有没有办法在Java中做到这一点?
鞋子

2
这个设置在哪里?
red888

2
@MattWestlake您可以在API Gateway中创建一个名为user的资源,并在其下创建一个名为{name}的资源。
乔纳森

3
我只想提及,在进行此更改之后,我还必须转到Amazon API Gateway-> Actions-> Deploy API并重新部署到实时环境。
victorvartan

221

使此工作正常的步骤是:

在API网关控制台中...

  1. Resources -> Integration Request
  2. 单击模板下拉菜单旁边的加号或编辑图标(奇怪的是,因为模板字段已经打开,并且此处的按钮显示为灰色)
  3. application/json即使它显示默认值,也要在content-type字段中明确输入(如果不这样做,它将不会保存,并且不会显示错误消息)
  4. 将其放在输入映射中 { "name": "$input.params('name')" }

  5. 单击模板下拉菜单旁边的复选框(我假设这是最终保存它的内容)


9
您是否曾经通过路由中的/ user / {username}之类的/ user / bob之类的URL参数通过URL参数发送该消息?我尝试了各种排列,但无法解决。
卢卡斯

5
有谁知道是否有官方文件?最好只传递所有查询参数或比空字符串更优雅地处理可选值
AxelTheGerman 2015年

6
iOS开发人员的一个技巧:在将每个变量定义为查询字符串(在“方法请求”下)并部署API之前,API Gateway不会传递查询数据。在部署之前,它可以通过控制台测试运行,但是会从应用程序的查询中删除。
AlexeyVMP


6
卢卡斯,我使用/ user / {username}模式使它工作。只要记住,如果您的GET资源路径是/ user / {username},则在步骤4中,输入映射看起来像这样{“ name”:“ $ input.params('username')”}
Gerard

134

我已使用此映射模板为Lambda事件提供主体,标题,方法,路径和URL查询字符串参数。我写了一篇博客文章,更详细地解释了该模板:http : //kennbrodhagen.net/2015/12/06/how-to-create-a-request-object-for-your-lambda-event-from-api-网关/

这是您可以使用的映射模板:

{
  "method": "$context.httpMethod",
  "body" : $input.json('$'),
  "headers": {
    #foreach($param in $input.params().header.keySet())
    "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext),#end

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

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

    #end
  }  
}

惊人!我一直在努力地将事情传递给我的经理。最好的答案在这里。
Venkat D.

我做到了,但是我什么都还没得到。其显示未定义。我们应该如何在URL中发送参数?并且我们是否需要像正常的GET url方案一样在url中指定变量名?这个你能帮我吗。
Parthapratim Neog '16

8
没关系,我得到了结果。问题是,我添加了映射并只是保存了它,没有deploy再次使用api。一旦使用新的映射部署了api,它就可以正常工作。万分感谢。
Parthapratim Neog '16

@ shashu10查看我的回答
matsev '16

1
我无法开始告诉您博客的实用性。我首先找到了“ eturn-html-from-aws-api-gateway”帖子,然后关注它,因为这正是我所需要的。现在,我需要向函数中传递一些参数,并根据该参数修改html-再次,您是唯一拥有真正指南的人!我发现的所有其他指南似乎都忽略了这一点。
user3685427

41

如今,AWS的API网关控制台中包含一个下拉模板。

对于您的API,单击资源名称...然后单击GET。

展开“身体映射模板”

输入

应用程序/ json

对于Content-Type(必须明确输入),然后单击对勾

将打开一个新窗口,其中显示“ Generate template”字样和一个下拉菜单(参见图片)。

选择

方法请求传递

在此处输入图片说明

然后点击保存

要访问任何变量,只需使用以下语法(这是Python),例如URL:

https://yourURL.execute-api.us-west-2.amazonaws.com/prod/confirmReg?token=12345&uid=5

您可以按以下方式获取变量:

from __future__ import print_function

import boto3
import json

print('Loading function')


def lambda_handler(event, context):
    print(event['params']['querystring']['token'])
    print(event['params']['querystring']['uid'])

因此,无需显式命名或映射所需的每个变量。


优秀的!该功能就在服务中,但是错过了!
hnvasa

25

为了将参数传递给lambda函数,您需要在API Gateway请求和lambda函数之间创建映射。映射在所选API网关资源的Integration Request-> Mapping templates部分中完成。

创建一个类型的映射application/json,然后在右侧编辑(单击铅笔)模板。

映射模板实际上是Velocity模板,您可以在其中使用ifs,loops,当然还可以在其上打印变量。模板中注入了这些变量,您可以在其中分别访问查询字符串参数,请求标头等。使用以下代码,您可以重新创建整个查询字符串:

{
    "querystring" : "#foreach($key in $input.params().querystring.keySet())#if($foreach.index > 0)&#end$util.urlEncode($key)=$util.urlEncode($input.params().querystring.get($key))#end",
    "body" : $input.json('$')
}

注意:单击对勾符号以保存模板。您可以使用资源中的“测试”按钮来测试更改。但是,为了在AWS控制台中测试querystring参数,您需要在Method Request资源部分中定义参数名称。

注意:有关Velocity模板语言的更多信息,请参见《 Velocity用户指南》

然后,在lambda模板中,您可以执行以下操作以解析查询字符串:

var query = require('querystring').parse(event.querystring)
// access parameters with query['foo'] or query.foo

9
这是最好的解决方案。请记住要这样做Actions>Deploy API(我浪费了时间忘记了这一点...)。关联的lambda arn将在部署后立即进行更改。您可以在中签入Stages > #stage (like: prod) > Deployment History
loretoparisi

24

可接受的答案对我来说很好用,但是扩展了gimenete的答案,我想要一个通用模板,我可以使用它来传递所有查询/路径/标头参数(现在只是字符串),然后我提出了以下模板。我将其张贴在这里,以防有人觉得有用:

#set($keys = [])
#foreach($key in $input.params().querystring.keySet())
  #set($success = $keys.add($key))
#end

#foreach($key in $input.params().headers.keySet())
  #if(!$keys.contains($key))
    #set($success = $keys.add($key))
  #end
#end

#foreach($key in $input.params().path.keySet())
  #if(!$keys.contains($key))
    #set($success = $keys.add($key))
  #end
#end

{
#foreach($key in $keys)
  "$key": "$util.escapeJavaScript($input.params($key))"#if($foreach.hasNext),#end
#end
}

1
Fab,我希望能够对POST(带有JSON正文)请求和带有查询字符串的GET使用相同的功能。梦想成真。谢谢!
马特·弗莱彻

@benv这是完整模板吗?
nxmohamad

17

由于试图回答我自己的问题,一部分在这里,我遇到了这一招。

在API网关映射模板中,使用以下命令为您提供HTTP客户端发送的完整查询字符串:

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

好处是您不必将自己限制为查询字符串中的一组预定义映射键。现在,如果您要使用这种方式,则可以接受查询字符串中的任何键值对。

注意:根据,仅$input.params(x)列出为VTL模板可用的变量。内部可能会更改,并且querystring可能不再可用。


1
自2017年5月起,它仍然有效,但是它返回API Gateway为您创建的JS对象,而不是实际的查询字符串。这对我来说很烦,因为我试图解析查询字符串以将重复的参数转换为数组。
汤姆·萨利巴

11

现在,您应该能够对Lambda使用新的代理集成类型,以自动获取标准形状的完整请求,而不是配置映射。

请参阅:http : //docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-set-up-lambda-proxy-integration-on-代理资源


1
我不确定为什么,但是代理集成通常对我不起作用。我必须将其从我创建的最新API中删除。
Gustavo Straube

同样,我在API网关中遇到了CORS问题。跟着AWS文档一起,我无法使CORS工作。但是,我发现2015年中后期有一篇中型的老文章,它具有手动设置CORS的方式,并且有效。
Stephen Tetreault,

7

GET / user?name = bob

{
    "name": "$input.params().querystring.get('name')"
}

GET /用户/鲍勃

{
    "name": "$input.params('name')"
}

5

这里的很多答案都很棒。但是我想要一些简单的东西。我想要一些可以免费使用“ Hello World”示例的东西。这意味着我想要一个简单的产生与查询字符串匹配的请求主体:

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

我认为,在构建真实的东西时,最佳答案会产生更多有用的信息,但是使用AWS的模板来快速运行世界时,效果很好。


4

以下参数映射示例通过JSON有效负载将所有参数(包括路径,查询字符串和标头)传递到集成端点

#set($allParams = $input.params())
{
  "params" : {
    #foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
    "$type" : {
      #foreach($paramName in $params.keySet())
      "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
      #if($foreach.hasNext),#end
      #end
    }
    #if($foreach.hasNext),#end
    #end
  }
}

实际上,此映射模板在有效负载中输出所有请求参数,如下所示:

{
  "parameters" : {
     "path" : {    
       "path_name" : "path_value", 
       ...
     }
     "header" : {  
       "header_name" : "header_value",
       ...
     }
     'querystring" : {
       "querystring_name" : "querystring_value",
       ...
     }
   }
}

复制自Amazon API Gateway开发人员指南


2

查询字符串可以直接在lambda中的javascript中解析

对于GET / user?name = bob

 var name = event.params.querystring.name;

但是,这不能解决GET用户/鲍勃的问题。


其event.queryStringParameters.name

我必须做event.queryStringParameters.name
Anders Kitson

2

作为@Jonathan的答案,在Integration Request中标记Use Lambda Proxy集成后,在您的源代码中,您应将以下格式实现为通过502 Bad Gateway错误。

NodeJS 8.10:

exports.handler = async (event, context, callback) => {
  // TODO: You could get path, parameter, headers, body value from this
  const { path, queryStringParameters, headers, body } = event;

  const response = {
    "statusCode": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "body": JSON.stringify({
      path, 
      query: queryStringParameters,
      headers,
      body: JSON.parse(body)
    }),
    "isBase64Encoded": false
  };

  return response;
};

重新运行API之前,请不要忘记在API Gateway上部署资源。响应JSON仅返回正文中的正确设置。因此,您可以从事件获取路径,参数,标题,正文值

const {path,queryStringParameters,headers,body} =事件;


1

Lambda函数需要JSON输入,因此需要解析查询字符串。解决方案是使用映射模板将查询字符串更改为JSON。
我将其用于C#.NET Core,因此预期的输入应为带有“ queryStringParameters”参数的JSON。
请按照以下4个步骤来实现:

  1. 打开API网关资源的映射模板,然后添加新的application/json内容类型:

API网关映射模板

  1. 复制下面的模板,该模板将查询字符串解析为JSON,并将其粘贴到映射模板中:

    {
    "queryStringParameters": {#foreach($key in $input.params().querystring.keySet())#if($foreach.index > 0),#end"$key":"$input.params().querystring.get($key)"#end}
    }
    
  2. 在API网关中,调用您的Lambda函数并添加以下查询字符串(例如): param1=111&param2=222&param3=333

  3. 映射模板应在下面创建JSON输出,这是Lambda函数的输入

    {
    "queryStringParameters": {"param3":"333","param1":"111","param2":"222"}
    }
    
  4. 你完成了。至此,您的Lambda函数的逻辑可以使用查询字符串参数。
    祝好运!




-1

在阅读了这些答案中的几个之后,我在2018年8月使用了几个答案的组合,通过lambda为python 3.6检索了查询字符串参数。

首先,我去了API网关->我的API->资源(在左侧)->集成请求。在底部下方,选择“映射模板”,然后输入内容类型application/json

接下来,选择Amazon提供的方法请求传递模板,然后选择保存并部署您的API。

然后,lambda event['params']是您访问所有参数的方式。对于查询字符串:event['params']['querystring']

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.