如何在Lambda / API网关中使用param传递

时间:2018-02-24 18:02:19

标签: node.js amazon-web-services aws-lambda aws-api-gateway

我正在尝试使用API​​ Gateway,Lambda和RDS构建API。因此,您键入URL并以JSON格式从RDS获取特定行。

所以这就是我想要实现的目标。

  • / production / myfootballapi?table = football - >表中的所有行 应该退回(不工作)
  • / production / myfootballapi?table = football& id = 2 - >只有id 2行 应该退回(只有这种情况有效)

我遇到的主要问题是我目前无法显示所有行,因为我总是要定义id,否则会发生错误。

我的API网关正文映射模板:

{
"table" : "$input.params('table')",
"id" : $input.params('id')
}

我的Lambda函数

var mysql = require('mysql2');
var config = require('./config.json');

var pool  = mysql.createPool({
host     : config.dbhost,
user     : config.dbuser,
password : config.dbpassword,
database : config.dbname,
});


exports.handler =  (event, context, callback) => {


//prevent timeout from waiting event loop
context.callbackWaitsForEmptyEventLoop = false;

pool.getConnection(function(err, connection) {
if (err) throw err; 
// Use the connection

var table = event.table;
var id = event.id;

// This if-function is just a try to solve this problem but it doesn't work
if (id !== null) { 
  var sql = "SELECT * FROM ?? WHERE id = ?";
  var inserts = [table, id];

} else {
  var sql = "SELECT * FROM ?";
  var inserts = table;
}

sql = mysql.format(sql, inserts);

connection.query(sql, function (error, results, fields) {
  // And done with the connection.
  connection.release();
  // Handle error after the release.
  if (error) callback(error);
  else callback(null,results);
  });
});
};

如果您需要更多信息,请发表评论。

谢谢!

4 个答案:

答案 0 :(得分:0)

我相信您的问题可能是您的if (id !== null)声明。我嘲笑了你的例子,添加了console.log(sql);并发现即使请求中没有发送id,返回的SQL查询也是SELECT * FROM '\"Customer\"' WHERE id = NULL

我将你的if语句更改为以下内容。

if (id) { 
  var sql = "SELECT * FROM ?? WHERE id = ?";
  var inserts = [table, id];

} else {
  var sql = "SELECT * FROM ?";
  var inserts = table;
}

进行此更改后,如果请求中没有ID,则SQL查询为SELECT * FROM '\"Customer\"'

为了完整起见,我做了另一个修改。我根本没有使用Body Mapping Template。我使用了Integration Request配置中的“Use Lambda Proxy Integration”设置。这将消除使用Body Mapping模板的需要。

enter image description here

在方法请求配置中,定义URL查询字符串参数

enter image description here

在您的Lambda函数中,您将能够分别以event.queryStringParameters.tableevent.queryStringParameters.id访问您的表格和ID。然后在Lambda函数中执行您想要的任何操作。

var table = JSON.stringify(event.queryStringParameters.table);
var id = JSON.stringify(event.queryStringParameters.id);

console.log("Table: " + table);
console.log("ID: " +id);

----------- EDITED ---------------

确保Lambda函数中的回调发送一个可由API网关处理的有效响应。这是我如何格式化我模拟的示例代码来测试它。

var response = {
    "statusCode": 200,
    "headers": {
        "my_header": "my_value"
    },
    "body": JSON.stringify(results),
    "isBase64Encoded": false
};
callback(null, response);

希望这有帮助。

答案 1 :(得分:0)

我认为你的映射模板可能太简单了。如果你让它工作,我很想知道如何,因为我的模板需要大量的代码,并且很难做到正确,但我接受了它。我认为如果没有更多的处理,你可能会遇到某些值时的其他问题或者放入你的参数。你将不得不处理逃避等等。

这是我用来将API网关映射到lambda的模板。我把它从我的cloudformation模板中拉出来,如果随机的json或额外的引号仍然存在,请原谅我。如果您更愿意看到cloudformation模板,我可以证明这一点。

#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\
       }
}

答案 2 :(得分:0)

首先,非常感谢大家的帮助。我自己修好了,但如果有人有类似的问题,我也会记录下来。

<强>&GT; API网关&lt;

转到集成请求

go to Integration Request

添加以下正文映射模板

enter image description here

{
#set($queryMap = $input.params().querystring)

#foreach( $key in $queryMap.keySet())
  "$key" : "$queryMap.get($key)"
  #if($foreach.hasNext),#end
#end
}

转到方法请求

enter image description here

添加参数 enter image description here

<强>&GT; Lambda&lt;

var mysql = require('mysql2');
var config = require('./config.json');

var pool  = mysql.createPool({
    host     : config.dbhost,
    user     : config.dbuser,
    password : config.dbpassword,
    database : config.dbname,
  });


exports.handler =  (event, context, callback) => {

  //prevent timeout from waiting event loop
  context.callbackWaitsForEmptyEventLoop = false;

  pool.getConnection(function(err, connection) {
    if (err) throw err; 
    // Use the connection

   var table = event.table;
   var id = event.id;

    if (isNaN(id)) { 
       var sql = "SELECT * FROM ??";
       var inserts = table;
     } else {
       var sql = "SELECT * FROM ?? WHERE id = ?";
       var inserts = [table, id];
     }

    sql = mysql.format(sql, inserts);

  connection.query(sql, function (error, results, fields) {
      // And done with the connection.
      connection.release();
      // Handle error after the release.
      if (error) callback(error);
      else callback(null,results);
    });
  });
};

来源:https://aws.amazon.com/de/blogs/compute/using-api-gateway-mapping-templates-to-handle-changes-in-your-back-end-apis/

我认为,它可能不是lambda中最好的代码,但现在可以使用。我稍后会改进它。 :D

答案 3 :(得分:0)

您应将if-else语句更改为:

if (id !== "") { 
  var sql = "SELECT * FROM ?? WHERE id = ?";
  var inserts = [table, id];
} else {
  var sql = "SELECT * FROM ?";
  var inserts = table;
}

由于已经设置了主体映射模板,因此如果不将其传递为参数,则id将被设置为""。您可以在日志中查看其值,也可以尝试在输入id语句之前记录if-else