无法解决 AWS Lambda 在简单的 HTTP Api Gateway 请求上的 CORS 错误。

huangapple go评论78阅读模式
英文:

Cant get past CORS error for AWS Lambda response on simple HTTP Api Gateway request

问题

我目前有一个非常简单的API请求,用于从MySQL返回数据。当前的设置是网站调用API Gateway > 调用Lambda > 返回MySQL表中的数据 > 在网站上显示。使用Postman,我可以获取返回的数据,但通过我的JavaScript代码执行时,无法解决一些CORS错误。我认为这不是CORS的问题,而是与我的Lambda有关的错误。这些是控制台上的错误:

我的网站代码调用网关的部分如下:

const Http = new XMLHttpRequest();
const url = 'https://nnebmzru3e.execute-api.us-east-2.amazonaws.com/proxy+';

Http.open("OPTIONS", url);
Http.setRequestHeader('Access-Control-Allow-Origin', '*')

Http.send();
console.log(Http.responseText)
Http.onreadystatechange = (e) => {
    console.log(Http.responseText)
}

我的Lambda代码如下:

const mysql = require("mysql");

exports.handler = (event, context, callback) => {
  console.log(event);
  const connection = mysql.createConnection({
    host: process.env.RDS_HOSTNAME,
    user: process.env.RDS_USERNAME,
    password: process.env.RDS_PASSWORD,
    port: process.env.RDS_PORT,
  });

  connection.query(
    "SELECT * FROM pickemss.pickems where Week = 1",
    function (error, results, fields) {
      if (error) {
        console.log("ERROR DESTROYING CONNECTION");
        connection.end();
        throw error;
      } else {
        // connected!
        console.log("CONNECTED");
        connection.end(function (err) {
          callback(err, formatResponse(results));
        });
      }
    }
  );
};

var formatResponse = function (body) {
  console.log("Formatting response");
  var response = {
    statusCode: 200,
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Headers":
        "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
      "Access-Control-Allow-Methods": "*",
    },
  };
  response.body = JSON.stringify(body);
  console.log(response.body);

  return response;
};

我尝试在不同路由上使用GET请求,但在这一点上我完全不知道为什么失败,因为在我的CloudWatch日志中没有错误,我也可以看到来自MySQL查询的数据。

无法解决 AWS Lambda 在简单的 HTTP Api Gateway 请求上的 CORS 错误。

英文:

I currently have a very simple API request that returns data from MySQL. The current setup is Website calls API Gateway > invokes Lambda > returns data from MySQL Table > displays on website. With Postman, I can get the data returned, but when doing it through my JavaScript code I cannot get past some CORS errors. I think its less CORS and something with my lambda causing an error. These are the errors from console:无法解决 AWS Lambda 在简单的 HTTP Api Gateway 请求上的 CORS 错误。My web side code to call the gateway is:

        const Http = new XMLHttpRequest();
        const url = 'https://nnebmzru3e.execute-api.us-east-2.amazonaws.com/proxy+';
    
        Http.open("OPTIONS", url);
        Http.setRequestHeader('Access-Control-Allow-Origin', '*')
    
    
        Http.send();
        console.log(Http.responseText)
        Http.onreadystatechange = (e) => {
            console.log(Http.responseText)
        }

My Lambda code is as follows:

const mysql = require("mysql");

// console.log(connection);
exports.handler = (event, context, callback) => {
  console.log(event);
  const connection = mysql.createConnection({
    host: process.env.RDS_HOSTNAME,
    user: process.env.RDS_USERNAME,
    password: process.env.RDS_PASSWORD,
    port: process.env.RDS_PORT,
  });

  connection.query(
    "SELECT * FROM pickemss.pickems where Week = 1",
    function (error, results, fields) {
      if (error) {
        console.log("ERROR DESTROYING CONNECTION");
        connection.end();
        throw error;
      } else {
        // connected!
        console.log("CONNECTED");
        connection.end(function (err) {
          callback(err, formatResponse(results));
        });
        // return formatResponse(results);
      }
    }
  );
};

var formatResponse = function (body) {
  console.log("Formatting response");
  var response = {
    statusCode: 200,
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Headers":
        "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
      "Access-Control-Allow-Methods": "*",
    },
  };
  response.body = JSON.stringify(body);
  console.log(response.body);

  return response;
};

Ive tried using a GET request on a different route, but have no clue at this point why its failing as in my cloudwatch logs there are no errors and i can see the data from the mysql query aswell.

答案1

得分: 1

似乎您的函数未按预期工作,并且未正确返回CORS标头。老实说,阅读代码也有点困难,尽管AWS Lambda提供了函数处理程序的第三个参数(callback),但通常不建议再使用它,因为回调模式容易陷入回调地狱,更容易出现错误,并且难以阅读。为了改善您的情况,您可以使用以下代码:

const mysql = require("mysql");

function getData(conn, query) {
  return new Promise((resolve, reject) => {
    conn.query(query, function (error, results) {
      if (error) {
        console.log("ERROR DESTROYING CONNECTION");
        conn.end();
        reject(error);
        return;
      }

      console.log("CONNECTED");
      conn.end();
      resolve(results);
    });
  });
}

function formatResponse(body) {
  const response = {
    statusCode: 200,
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Headers":
        "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
      "Access-Control-Allow-Methods": "*",
      body: JSON.stringify(body),
    },
  };

  return response;
}

exports.handler = async (event) => {
  console.log(event);
  const connection = mysql.createConnection({
    host: process.env.RDS_HOSTNAME,
    user: process.env.RDS_USERNAME,
    password: process.env.RDS_PASSWORD,
    port: process.env.RDS_PORT,
  });
  const query = "SELECT * FROM pickemss.pickems where Week = 1";
  const results = await getData(connection, query);

  return formatResponse({ results });
};
英文:

It seems like your function is not working as intended and it doesn't return the CORS headers properly. To be honest, it was kind of hard to read the code too and although AWS lambda provides the 3rd parameter for function handlers (callback), it is generally not recommended to use it anymore as callback pattern is susceptible to callback hell, more prone to bugs and harder to read. To improve your situation, you can use the following code:

const mysql = require("mysql");

function getData(conn, query) {
  return new Promise((resolve, reject) => {
    conn.query(query, function (error, results) {
      if (error) {
        console.log("ERROR DESTROYING CONNECTION");
        conn.end();
        reject(error);
        return;
      }

      console.log("CONNECTED");
      conn.end();
      resolve(results);
    });
  });
}

function formatResponse(body) {
  const response = {
    statusCode: 200,
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Headers":
        "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
      "Access-Control-Allow-Methods": "*",
      body: JSON.stringify(body),
    },
  };

  return response;
}

exports.handler = async (event) => {
  console.log(event);
  const connection = mysql.createConnection({
    host: process.env.RDS_HOSTNAME,
    user: process.env.RDS_USERNAME,
    password: process.env.RDS_PASSWORD,
    port: process.env.RDS_PORT,
  });
  const query = "SELECT * FROM pickemss.pickems where Week = 1";
  const results = await getData(connection, query);

  return formatResponse({ results });
};

huangapple
  • 本文由 发表于 2023年7月12日 22:30:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76671690.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定