从 AWS Lambda 调用 API 的结果不一致
Inconsistent results making API call from AWS Lambda
让我提前为这个糟糕的代码道歉。我几乎没有节点经验,并且在后端使用 React 应用程序和 Elixir 编写我所有的 JS。我正在努力在 NodeJS 中编写正确的 Lambda 函数,并且基本上从 Googling/SO/trial 和错误等
中拼凑了一些东西
我正在做的是:
- 用户想要上传文件,因此他们将一些信息发送到后端。
- 后端生成预签名密钥。
- 前端发送文件到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 use
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);
}
};
S3删除操作在所有区域最终一致。
因此作为 AWS(捕获的相关信息),
- 进程删除现有对象并立即尝试读取它。在删除完全传播之前,Amazon S3 可能 return 删除的数据。
- 进程删除现有对象并立即列出其存储桶中的键。在删除完全传播之前,Amazon S3 可能会列出已删除的对象。
参考:https://docs.aws.amazon.com/AmazonS3/latest/dev/Introduction.html#ConsistencyModel
让我提前为这个糟糕的代码道歉。我几乎没有节点经验,并且在后端使用 React 应用程序和 Elixir 编写我所有的 JS。我正在努力在 NodeJS 中编写正确的 Lambda 函数,并且基本上从 Googling/SO/trial 和错误等
中拼凑了一些东西我正在做的是:
- 用户想要上传文件,因此他们将一些信息发送到后端。
- 后端生成预签名密钥。
- 前端发送文件到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 use
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);
}
};
S3删除操作在所有区域最终一致。
因此作为 AWS(捕获的相关信息),
- 进程删除现有对象并立即尝试读取它。在删除完全传播之前,Amazon S3 可能 return 删除的数据。
- 进程删除现有对象并立即列出其存储桶中的键。在删除完全传播之前,Amazon S3 可能会列出已删除的对象。
参考:https://docs.aws.amazon.com/AmazonS3/latest/dev/Introduction.html#ConsistencyModel