繁体   English   中英

使用 Lambda、API 网关和 HTTP 请求将来自 AWS RDS 的查询结果显示到公共网页

[英]Surfacing query results from AWS RDS to public web page using Lambda, API Gateway and HTTP requests

我正在尝试在公共网页中为 AWS RDS MySQL 数据库实现 SQL 查询接口。 理想情况下,用户将在搜索字段中键入 SQL 查询,按下“查询”按钮,API 网关请求将触发 Lambda 函数从数据库中提取、返回并打印到网页上的相关数据。

到目前为止,我有以下 Lambda 函数(我能够成功测试):

const AWS = require('aws-sdk')
const RDS = new AWS.RDSDataService()

exports.handler = async (event, context) => {
    console.log(JSON.stringify(event, null, 2))  // Log the entire event passed in

    // Get the sqlStatement string value
    // TODO: Implement a more secure way (e.g. "escaping") the string to avoid SQL injection
    var sqlStatement = event.sqlStatement;

    // The Lambda environment variables for the Aurora Cluster Arn, Database Name, and the AWS Secrets Arn hosting the master credentials of the serverless db
    var DBSecretsStoreArn = process.env.DBSecretsStoreArn;
    var DBAuroraClusterArn = process.env.DBAuroraClusterArn;
    var DatabaseName = process.env.DatabaseName;

    const params = {
      awsSecretStoreArn: DBSecretsStoreArn,
      dbClusterOrInstanceArn: DBAuroraClusterArn,
      sqlStatements: sqlStatement,
      database: DatabaseName
    }

    try {
      let dbResponse = await RDS.executeSql(params).promise()
      console.log(JSON.stringify(dbResponse, null, 2))

      var json_response = JSON.stringify(dbResponse)
      return json_response

    } catch (error) {
        console.log(error)
      return error
    }
}

这个函数,当用下面的测试格式测试时,返回一个我认为的 JSON blob。

测试事件格式:

{
  "sqlStatement": "SELECT * FROM Table WHERE Name='JOHN DOE'"
}

测试事件结果:

..., {\"stringValue\":\"JOHN DOE\"},{\"stringValue\":\"2019-11-15\"},{\"stringValue\":\"AL\"},{\"stringValue\":\"1\"},{\"stringValue\":\"130\"},{\"stringValue\":\"Washington Co. Jail\"},{\"stringValue\":\"2019-10-31\"}, ...

我配置了以下 API 触发器详细信息:

API endpoint: https://****************.amazonaws.com/prod/query
API Type: rest
Authorization: NONE
Method: POST
Resource path: /query
Stage: prod

我还有以下 Lambda 角色配置策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue",
                "rds:*",
                "rds-data:*"
            ],
            "Resource": "*"
        }
    ]
}

同时,API 具有以下方法/配置:

在此处输入图像描述

在此处输入图像描述

除了此设置中的任何潜在问题(即 Lambda 和 API 触发器之间的链接以及传递/查询/返回的数据格式),我需要弄清楚如何通过单击查询按钮实际调用整个过程. 因此,例如,用户将在页面上,将 SELECT * FROM Table WHERE Name="JOHN DOE" 键入 HTML 元素,单击 HTML 按钮“查询”,然后该过程将执行; 然后,查询结果将以任何格式填充到另一个 HTML 元素中(简单地说,现在是一个混乱的字符串,但理想情况下最终会在引导数据表中)。

我目前有一个 config.js 文件,其中包含:

window._config = {
    api: {
        invokeUrl: 'https://******************.amazonaws.com/prod',
    }
};

我还有一个 query.js 文件,其中包含基于在线零碎教程的函数(可能不正确)尝试:

(function DisplayQuery($) {

    var query = document.getElementById("sql-placeholder").value;

    function passQuery(query) {
        $.ajax({
            method: 'POST',
            url: _config.api.invokeUrl + '/query',
            data: JSON.stringify({
                sqlStatement: query
                }),
            contentType: 'application/json',
            success: document.getElementById("text-box").innerHTML = result.value,
            error: function ajaxError() {
                console.error('Error requesting ride');
            }
        })
    }
}(jQuery));

在我的 index.html 文件中,我有这些搜索字段和按钮元素:

<div class="active-cyan-4 mb-4">
   <input id="sql-placeholder" class="form-control" type="text" placeholder="Write SQL here..." aria-label="Search">
</div>
<div class="col-md-1">
   <button type="button" class="btn btn-primary" onclick="DisplayQuery()">Query</button>
</div>

最后,这将是测试元素,一旦 RDS --> Lambda --> API Gateway 返回我的字符串格式 SQL 查询结果,它们就会出现在该元素中:

<div class="container-fluid">
   <p class= "test-box-class" id="test-box"><i>This is a test box for database query connection</i></p>
</div>

这可能很多,但我想知道是否有人对如何运行此过程有任何见解,至少运行得足够好,以便点击“查询”按钮可以将某些内容返回到网页。

发出 ajax 请求的代码存在一些问题。

  • 单击按钮时会调用DisplayQuery ,但是此名称用于在初始页面加载时立即调用的函数。 而不是单击按钮,您需要调用发送 ajax 请求的函数。

  • 也不需要JSON.stringify输入值,因为它已经是一个字符串。

  • 此外,对于success键,需要提供接受响应的函数。

以下列方式更改query.js应该可以解决这些问题:

var DisplayQuery;
(function($) {
  DisplayQuery = function() {
    $.ajax({
      method: 'POST',
      url: _config.api.invokeUrl + '/query',
      data: $('#sql-placeholder').val(),
      contentType: 'application/json',
      success: function(response) {
        $('#test-box').text(JSON.stringify(response))
      },
      error: function ajaxError() {
        console.error('Error requesting ride');
      }
    })
  }
}(jQuery));

按照@antonku 的回答,“缺少身份验证令牌”错误的原因是,您正试图在浏览器中访问“POST”http 方法,浏览器使用“GET”http 方法请求 URL。

当 URL 不正确时,您也可能会收到相同的错误消息。

添加一些console.log语句,在前端查看api响应

var DisplayQuery;
(function($) {
  DisplayQuery = function() {
    $.ajax({
      method: 'POST',
      url: _config.api.invokeUrl + '/query',
      data: $('#sql-placeholder').val(),
      contentType: 'application/json',
      success: function(response) {
        console.log('response: ', response);
        $('#test-box').text(JSON.stringify(response))
      },
      error: function ajaxError(error) {
        console.error('Error requesting ride');
      }
    })
  }
}(jQuery));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM