node.js - 从 AWS Lambda 进行 API 调用结果不一致

标签 node.js amazon-web-services amazon-s3 aws-lambda apache-phoenix

让我提前为这个糟糕的代码道歉。我的 Node 经验几乎为零,并且在后端使用 React 应用程序和 Elixir 编写所有 JS。我正在努力在 NodeJS 中编写一个正确的 Lambda 函数,并且基本上已经从 Google/SO/试验和错误等中拼凑了一些东西。

我正在做的事情如下:

  • 用户想要上传文件,以便向后端发送一些信息。
  • 后端生成预签名 key 。
  • 前端将文件发送到 S3。
  • S3 触发事件并执行 Lambda
  • Lambda 现在会检查 mimetype,如果文件错误,则会从 S3 存储桶中删除该文件,并向我的后端发出 DELETE API 调用,告诉它删除上传照片所属的行。

我遇到的困难是,当我在 s3.deleteObject 调用中对后端进行 API 调用时,我得到的结果非常不一致。很多时候,它会在同一个 Lambda 执行中连续发送两个删除请求。有时,它甚至从未调用后端,只是运行并显示完整内容,而没有真正将任何内容记录到 Cloudwatch。

我的代码如下:

    const aws = require('aws-sdk');

    const s3 = new aws.S3({apiVersion: '2006-03-01'});

    const fileType = require('file-type');

    const imageTypes = ['image/gif', 'image/jpeg', 'image/png'];

    const request = require('request-promise');

    exports.handler = async (event, context) => {
      // Get the object from the event and show its content type
      const bucket = event.Records[0].s3.bucket.name;
      const key = decodeURIComponent(
        event.Records[0].s3.object.key.replace(/\+/g, ' ')
      );

      const params = {
        Bucket: bucket,
        Key: key,
      };

      try {
        const {Body} = await s3.getObject(params).promise();

        const fileBuffer = new Buffer(Body, 'base64');
        const fileTypeInfo = fileType(fileBuffer);

        if (
          typeof fileTypeInfo !== 'undefined' &&
          fileTypeInfo &&
          imageTypes.includes(fileTypeInfo.mime)
        ) {
          console.log('FILE IS OKAY.');
        } else {
          await s3
            .deleteObject(params, function(err, data) {
              console.log('FILE IS NOT AN IMAGE.');
              if (err) {
                console.log('FAILED TO DELETE.');
              } else {
                console.log('DELETED ON S3.  ATTEMPTING TO DELETE ON SERVER.');

                const url =
                  `http://MYSERVERHERE:4000/api/event/${params.Key.split('.')[0]}`;

                const options = {
                  method: 'DELETE',
                  uri: url,
                };

                request(options)
                  .then(function(response) {
                    console.log('RESPONSE: ', response);
                  })
                  .catch(function(err) {
                    console.log('ERROR: ', err);
                  });
              }
            })
            .promise();
        }
        return Body;
      } catch (err) {
        const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
        console.log(message);
        throw new Error(message);
      }
    };

这几天来一直让我发疯。感谢任何帮助来解释为什么我会从这样的 Lambda 函数中得到意外的结果。

最佳答案

更新您的else部分后请检查是否正确使用await

Please try below code.

exports.handler = async (event, context) => {
  // Get the object from the event and show its content type
  const bucket = event.Records[0].s3.bucket.name;
  const key = decodeURIComponent(
    event.Records[0].s3.object.key.replace(/\+/g, ' ')
  );

  const params = {
    Bucket: bucket,
    Key: key,
  };

  try {
    const {Body} = await s3.getObject(params).promise();

    const fileBuffer = new Buffer(Body, 'base64');
    const fileTypeInfo = fileType(fileBuffer);

    if (
      typeof fileTypeInfo !== 'undefined' &&
      fileTypeInfo &&
      imageTypes.includes(fileTypeInfo.mime)
    ) {
      console.log('FILE IS OKAY.');
    } else {
      await s3.deleteObject(params).promise(); //fail then catch block execute
        console.log('DELETED ON S3.  ATTEMPTING TO DELETE ON SERVER.');

        const url =
          `http://MYSERVERHERE:4000/api/event/${params.Key.split('.')[0]}`;

        const options = {
          method: 'DELETE',
          uri: url,
        };

        let response = await request(options); ////fail then catch block execute
        console.log(response);
      }
    return Body;
  } catch (err) {
    console.log(err);
    const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
    console.log(message);
    throw new Error(message);
  }
};

关于node.js - 从 AWS Lambda 进行 API 调用结果不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52982051/

相关文章:

node.js - 将环境变量从 Gitlab docker 执行器传递到镜像

apache - 如何使用域地址直接访问部署在 AWS tomcat 中的 Web 应用程序?

ios - 使用 Mobile Hub 配置时 swift iOS S3 访问被拒绝

amazon-web-services - 堆栈处于 UPDATE_COMPLETE_CLEANUP_IN_PROGRESS 状态并且无法更新

amazon-web-services - 无法在 AWS Lambda 中使用 OpenCV-Python

amazon-s3 - AWS Glue 使用 AWS KMS 读取 S3 文件客户端加密

java - 尝试将 InputStream 放入 Amazon S3 时进程终止

javascript - AngularJS 无法上传文件 Express

node.js - 如果重点关注建模数据,那么哪个(内存中)图形数据库

javascript - 将JSON对象转换为javascript中的数组数组