Lambda - headObject 失败 (NotFound) 尽管 objectCreated 是事件

Lambda - headObject fails (NotFound) though objectCreated is the event

在带有事件的 lambda 函数中:s3:ObjectCreated:*,在创建的对象上调用 head 对象 returns 一个 NotFound 错误。

module.exports.handler = async function(event, context, callback) {
    try {
        const Bucket = event.Records[0].s3.bucket.name;
        const Key = event.Records[0].s3.object.key;
        console.log('Bucket', Bucket);
        console.log('Key', Key);

        const objectHead = await s3.headObject({ Bucket, Key }).promise();
        console.log('Alas! I will never discover that the objectHead is:', objectHead);

        callback();
    } catch(err) {
        console.error('Error', err);
        callback(err);
    }
}

这是我得到的错误:

{ 
    NotFound: null
    message: null,
    code: 'NotFound',
    region: null,
    time: 2018-02-19T11:06:35.894Z,
    requestId: 'XXXXXXXXXXX',
    extendedRequestId: 'XXX.....XXX',
    cfId: undefined,
    statusCode: 404,
    retryable: false,
    retryDelay: 77.24564264820208 
}

我注意到错误中显示 region null。我怀疑这无关紧要,因为我 99% 确定我设置正确:

const s3 = new AWS.S3({
    region: 'us-east-1'
});

下面是 serverless.yml 函数声明,以防有人好奇:

obj_head:
  handler: obj_head.handler
  events:
    - s3:
        bucket: ${self:provider.environment.BUCKET_NAME}
        event: s3:ObjectCreated:*
  role: arn:aws:iam::XXXXXXXXX:role/RoleWithAllS3PermissionsEver

这里是收到事件的示例:

{
    "Records": [
        {
            "eventVersion": "2.0",
            "eventSource": "aws:s3",
            "awsRegion": "us-east-1",
            "eventTime": "2018-02-19T11:03:46.761Z",
            "eventName": "ObjectCreated:Put",
            "userIdentity": {
                "principalId": "AWS:XXX"
            },
            "requestParameters": {
                "sourceIPAddress": "X.X.X.X"
            },
            "responseElements": {
                "x-amz-request-id": "X",
                "x-amz-id-2": "X/X/X"
            },
            "s3": {
                "s3SchemaVersion": "1.0",
                "configurationId": "14122133-28e8-4cd9-907c-af328334c56b",
                "bucket": {
                "name": "BUCKET_NAME",
                "ownerIdentity": {
                    "principalId": "X"
                },
                "arn": "arn:aws:s3:::BUCKET_NAME"
                },
                "object": {
                    "key": "input.key",
                    "size": X,
                    "eTag": "X",
                    "sequencer": "X"
                }
            }
        }
    ]
}

令人费解的是,虽然触发函数的事件是对象的创建,但找不到对象头。

我是不是做错了什么? 关于去哪里看有什么想法吗?

对象键名值是 URL 编码的,这是导致问题的原因。此行为记录在案 here:

The s3 key provides information about the bucket and object involved in the event. Note that the object keyname value is URL encoded. For example "red flower.jpg" becomes "red+flower.jpg".

处理包含 Unicode 字符的文件名时,请参阅 Alastair McCormack 的

You need to convert the URL encoded Unicode string to a bytes str before un-urlparsing it and decoding as UTF-8.