【问题标题】:How to pass a querystring or route parameter to AWS Lambda from Amazon API Gateway如何将查询字符串或路由参数从 Amazon API Gateway 传递到 AWS Lambda
【发布时间】:2015-09-28 13:33:14
【问题描述】:

例如,如果我们想使用

GET /user?name=bob

GET /user/bob

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

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

  • method.request.path.parameter-name 用于在方法请求页面中定义的名为 parameter-name 的路径参数。
  • method.request.querystring.parameter-name 用于在方法请求页面中定义的名为 parameter-name 的查询字符串参数。

即使我定义了查询字符串,我也看不到这两个选项。

【问题讨论】:

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


    【解决方案1】:

    完成这项工作的步骤是:

    在 API Gateway 控制台内 ...

    1. 转至Resources -> Integration Request
    2. 单击模板下拉菜单旁边的加号或编辑图标(我知道,因为模板字段已经打开,并且此处的按钮看起来是灰色的)
    3. 在内容类型字段中显式键入 application/json,即使它显示为默认值(如果您不这样做,它将不会保存并且不会给您错误消息)
    4. 把这个放到输入映射{ "name": "$input.params('name')" }

    5. 单击模板下拉列表旁边的复选框(我假设这是最终保存它的原因)

    【讨论】:

    • 你有没有得到这个通过 URL 中的 URL 参数发送,比如 /user/bob,其中路由是 /user/{username}?我尝试了各种排列,但都无法解决。
    • 有谁知道有没有官方文档?只传递所有查询参数或比空字符串更优雅地处理可选值会很好
    • 给 iOS 开发者的一个提示:在您将每个变量定义为查询字符串(在“方法请求”下)并部署 API 之前,API 网关不会传递查询数据。在部署之前,它可以通过控制台测试工作,但会减少应用程序的查询。
    • Lucas,我​​使用 /user/{username} 模式让它工作。请记住,如果您的 GET 资源路径是 /user/{username},在第 4 步中,输入映射看起来像这样 { "name": "$input.params('username')" }
    【解决方案2】:

    在尝试回答我自己的一个问题here 时,我遇到了这个技巧。

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

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

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

    注意:根据this,只有$input.params(x) 被列为可用于VTL 模板的变量。内部结构可能会发生变化,querystring 可能不再可用。

    【讨论】:

    • 这在 2017 年 5 月仍然有效,但它返回 API Gateway 为您创建的 JS 对象,而不是实际的查询字符串。这对我来说很烦人,因为我正在尝试解析查询字符串以将重复的参数转换为数组。
    【解决方案3】:

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

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

    映射模板实际上是一个 Velocity 模板,您可以在其中使用 ifs、循环,当然还可以在其上打印变量。该模板具有these variables injected,您可以在其中单独访问查询字符串参数、请求标头等。使用以下代码,您可以重新创建整个查询字符串:

    {
        "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 控制台中测试查询字符串参数,您需要在资源的 Method Request 部分定义参数名称。

    注意:查看Velocity User Guide 了解有关 Velocity 模板语言的更多信息。

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

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

    【讨论】:

    • 这是最好的解决方案。请记得做Actions>Deploy API然后(我浪费了我的时间忘记这个......)。相关的 lambda arn 将在部署后立即进行更改。你可以在Stages > #stage (like: prod) > Deployment History查看。
    【解决方案4】:

    接受的答案对我来说很好,但扩展了 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
    }
    

    【讨论】:

    • Fab,我希望能够对 POST(带有 JSON 正文)请求和带有查询字符串的 GET 使用相同的函数。做梦。谢谢!
    • @benv 这是完整的模板吗?
    【解决方案5】:

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

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

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

    【讨论】:

    • 太棒了!我一直在努力将事情一般地传递​​给我的处理程序。最佳答案在这里。
    • 我这样做了,但我还没有得到任何东西。它显示未定义。我们应该如何在 URL 中发送参数?我们是否需要像在普通的 GET url 场景中一样在 url 中指定变量名?请帮我解决这个问题。
    • 没关系,我得到了结果。问题是,我添加了映射并保存了它,并没有再次deploy api。一旦我使用新映射部署了 api,它就可以正常工作了。非常感谢。
    • @shashu10 看我的回答
    • 我无法告诉您您的博客有多大用处。我首先找到了“eturn-html-from-aws-api-gateway”帖子并关注了它,因为这正是我所需要的。现在我需要将一些参数传递给函数并根据这些参数修改 html - 再说一次,你是唯一一个有真正指南的人!我发现的所有其他指南似乎都没有抓住重点。
    【解决方案6】:

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

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

    展开“身体映射模板”

    输入

    应用程序/json

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

    将打开一个新窗口,其中包含“生成模板”字样和一个下拉菜单(见图)。

    选择

    方法请求传递

    然后点击保存

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

    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'])
    

    因此无需显式命名或映射您想要的每个变量。

    【讨论】:

    • 太棒了!该功能就在服务中,但错过了!
    【解决方案7】:

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

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

    我认为在构建真实的东西时,最佳答案会产生更有用的东西,但是对于使用 AWS 的模板运行快速的 hello world 来说效果很好。

    【讨论】:

    • 我来这里是为了寻找这条评论。谢谢你,先生!
    【解决方案8】:

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

    对于 GET /user?name=bob

     var name = event.queryStringParameters.name;
    

    但这并不能解决 GET 用户/鲍勃问题。

    【讨论】:

    • 它的 event.queryStringParameters.name
    • 我不得不做event.queryStringParameters.name
    【解决方案9】:

    以下参数映射示例通过 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 Developer Guide

    【讨论】:

      【解决方案10】:

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

      见:http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-set-up-lambda-proxy-integration-on-proxy-resource

      【讨论】:

      • 我不知道为什么,但代理集成通常对我不起作用。我必须从我创建的最新 API 中删除它。
      • same ^ 此外,我在 API 网关方面遇到了 CORS 问题。跟随 AWS 文档,我无法让 CORS 工作。但是,我发现了一篇 2015 年中后期的旧 Medium 文章,其中有手动设置 CORS 的方法,并且有效。
      【解决方案11】:

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

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

      然后您就可以像这样访问查询参数、路径参数和标题

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

      【讨论】:

      • 这是一个很棒的提示。但是,请记住,打开 Lambda 代理集成可能会导致“格式错误的 Lambda 代理响应”错误。以下是解决方法:stackoverflow.com/questions/43708017/…
      • 有没有办法在 java 中做到这一点,同时保持实现 RequestHandler 提供的透明反序列化?
      • 这个设置在哪里?
      • 我只想提一下,在此更改之后,我还必须转到 Amazon API Gateway -> 操作 -> 部署 API 并重新部署到实时环境。
      • 如果使用 C#.NET Core 编写 lambda 函数,event 对象是什么?
      【解决方案12】:

      GET /user?name=bob

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

      GET /user/bob

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

      【讨论】:

        【解决方案13】:

        您可以将 Lambda 用作 “Lambda 代理集成”,参考此 [https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html#api-gateway-proxy-integration-lambda-function-python],此 lambda 可用的选项是

        对于 Nodejs Lambda 'event.headers','event.pathParameters','event.body','event.stageVariables', 和'event.requestContext'

        对于 Python Lambda event['headers']['parametername'] 等等

        【讨论】:

          【解决方案14】:

          在阅读了其中几个答案后,我在 2018 年 8 月结合使用了几个通过 lambda for python 3.6 检索查询字符串参数。

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

          接下来,选择 Amazon 提供的 Method Request Passthrough 模板,然后选择 save and deploy your API。

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

          【讨论】:

            【解决方案15】:

            作为@Jonathan 的回答,在 Integration Request 中标记 Use Lambda Proxy integration 之后,在您的源代码中,您应该按照以下格式实现以绕过 502 Bad网关错误。

            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 只返回 body 中设置的正确。 因此,您可以从事件中获取路径、参数、标题、正文值

            const { path, queryStringParameters, headers, body } = event;

            【讨论】:

              【解决方案16】:

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

              1. 打开您的 API Gateway 资源的映射模板并添加新的application/json content-tyap:

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

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

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

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

              【讨论】:

                【解决方案17】:
                【解决方案18】:
                exports.handler = async (event) => {
                    let query = event.queryStringParameters;
                    console.log(`id: ${query.id}`);
                    const response = {
                        statusCode: 200,
                        body: "Hi",
                    };
                    return response;
                };
                

                【讨论】:

                  【解决方案19】:

                  我的目标是传递类似于以下内容的查询字符串:

                   protodb?sql=select * from protodb.prototab
                  

                  通过来自 API 网关的 URL 到 Node.js 12 Lambda 函数。我尝试了其他答案中的一些想法,但真的想以最原生的 API 网关 UI 方式做一些事情,所以我想出了这个对我有用的方法(截至 2020 年 12 月的 API 网关 UI) :

                  在给定 API 的 API Gateway 控制台的资源下,选择 get 方法。然后选择它的集成请求,并在页面顶部为 lambda 函数填写数据。

                  滚动到底部并打开映射模板部分。未定义模板时选择 Request Body Passthrough(推荐)。

                  点击添加映射模板并创建一个内容类型为 application/json 的模板,然后点击复选标记按钮。

                  对于该映射模板,在下拉列表中选择 Method Request passthrough 以生成模板,该模板将使用 AWS 传递所有内容的一般方式填充其下的文本框。

                  点击保存按钮。

                  现在当我测试它时,我无法在 Lambda 函数中的节点 JS 下获取作为 event.sql 的参数。事实证明,当 API 网关将 URL sql 查询参数发送到 Lambda 函数时,它对于 Node.js 来说是这样的:

                   var insql = event.params.querystring.sql;
                  

                  因此,我花了一些时间的技巧是使用 JSON.stringify 来显示完整的事件堆栈,然后通过这些部分向下工作,以便能够从查询字符串中提取 sql 参数。

                  所以基本上你可以在 API 网关中使用默认的直通功能,诀窍是当你在 Lambda 函数中时如何传递参数。

                  【讨论】:

                    【解决方案20】:

                    对我有用的方法是

                    1. 转到集成请求
                    2. 点击网址查询字符串参数
                    3. 点击添加查询字符串
                    4. 在名称字段中输入查询名称,此处为“名称”
                    5. 在 Mapped From 字段中,输入“method.request.querystring.name”

                    【讨论】:

                      【解决方案21】:

                      带有 boto3 v1.16v 的 Python 3.8 - 2020 年 12 月

                      要配置路由,您必须配置 API Gateway 以接受路由。否则,除了基本路线之外,其他一切都会以 {missing auth token} 或其他东西结束......

                      一旦您将 API 网关配置为接受路由,请确保您启用了 lambda 代理,以便更好地工作,

                      访问路线,

                      new_route = event['path'] # /{some_url}
                      

                      访问查询参数

                      query_param = event['queryStringParameters'][{query_key}]
                      

                      【讨论】:

                      • 请不要碰旧问题
                      【解决方案22】:

                      要获取查询参数,您可以像这样在 queryStringParameters 对象中获取它们

                      const name = event.queryStringParameters.name;
                      

                      第二个是干净的 URL。如果您的路径是/user/{name},则要从pathParameters 对象中获取值,如下所示

                      const name = event.pathParameters.name;
                      

                      【讨论】:

                      • 对我来说都未定义
                      • pathParameters 对象或本例中的 name 未定义哪个?还是queryStringParameters
                      猜你喜欢
                      • 2017-11-14
                      • 2015-11-10
                      • 2023-04-02
                      • 2021-01-13
                      • 1970-01-01
                      • 2020-03-28
                      • 2017-05-08
                      • 2016-11-18
                      相关资源
                      最近更新 更多