У меня есть лямбда-функция, которую я использую более месяца для создания эскизов из загруженных изображений. Я настроил его так, чтобы он мог запускаться из события или вызываться вручную и / или через вызов gatewayAPI rest. Как уже упоминалось, я уже использовал это постоянно, и сейчас я создаю локальный контент, который будет его использовать.

Он берет изображение в одном сегменте и создает эскиз в другом сегменте. Для этого у меня есть асинхронный водопад node.js, который выполняет следующие шаги:

  1. используйте s3client для получения объекта из первого ведра

  2. используйте "резкое", чтобы создать миниатюру

  3. используйте 'резкий', чтобы получить свойства изображения для метаданных (ширина, высота, тип)

  4. используйте s3client, чтобы поместить объект в корзину эскизов

Внезапно он решил потерпеть неудачу на шаге 4, и я не уверен, почему:

2019-11-20T16:36:49.656Z    8ab486b1-e676-4862-9dec-2264166e8c0f    INFO    putObject failed
 { SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided.
   Check your key and signing method.
    at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/services/s3.js:585:35)
    at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)
    at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
  message:
   'The request signature we calculated does not match the signature you provided. Check your key and signing method.',
  code: 'SignatureDoesNotMatch',
  region: null,
  time: 2019-11-20T16:36:49.656Z,
  requestId: '25F4E6AE39104A62',
  extendedRequestId:
   'n8gPJ8y+bzhv7yHEiYDsNgjxyZqCENiRY0mUrZs/6Mp66DrN/CGBvWUcrKHNYF545k8zqKSMKVg=',
  cfId: undefined,
  statusCode: 403,
  retryable: false,
  retryDelay: 63.05576607189243 }

Насколько мне известно, я не менял ничего, что должно повлиять на его работу (я не менял никаких разрешений на ведро эскизов или, если на то пошло, исходное ведро)

        async.waterfall([
                function download(next) {
                    citScope.getS3client().getObject({
                            Bucket: image-files,
                            Key: key
                        },
                        next)
                },
                function transform(response, next) {
                    metadata.size = response.ContentLength.toString()
                    metadata.mtime = Math.floor(AWS.util.date.unixTimestamp(response.LastModified)).toString()

                    sharpImage = sharp(response.Body)
                        .metadata(next)
                },
                function parseMetadata(md, next) {
                    metadata.imagetype = `image/${md.format}`
                    metadata.width = md.width.toString()
                    metadata.height = md.height.toString()
                    sharpImage.clone()
                        .resize(MAX_WIDTH, MAX_HEIGHT, {fit: sharp.fit.inside})
                        .jpeg()
                        .toBuffer(next)
                },
                function upload(data, info, next) {
                    citScope.getS3client().putObject({
                            "Bucket": image-thumbnails,
                            "Key": thumbKey,
                            "Body": data,
                            "ContentType": "image/jpeg",
                            "Metadata": metadata
                        },
                        next)
                }
            ], function (err) {
                if (err) {
                    let output = {
                        "message": `Unable to resize image-files/${key}`,
                        "error": err
                    }
                    citReject(output)
                } else {
                    let output = {
                        "success":1,
                        "message": `Successfully resized s3://image-files:${key}`,
                        "metadata": metadata
                    }
                    citResolve(output)
                }
            }
        )

Я использую - и использую без проблем - роль выполнения лямбда-выражения, к которой в настоящее время добавлен AmazonS3FullAccess. Очевидно, getObject работает нормально. На более раннем этапе выполняется getHeadObject для проверки существования файла перед запуском процесса создания эскиза. Работает нормально. Я также подтвердил, что другая функция, которая у меня есть, которая выполняет 'putObject' пустого файла для создания заполнителя псевдокаталога, похоже, работает нормально (но в области изображений, а не в области эскизов).

Я просмотрел разрешения, и, похоже, между двумя ведрами нет ничего плохого, но я не совсем уверен, что искать. И, как уже говорилось, я не знаю, что бы я мог изменить, чтобы сделать это внезапно.

Любая помощь в отслеживании, почему это внезапно перестало работать, приветствуется.

0
Scott 20 Ноя 2019 в 19:58

1 ответ

OMFG - лямбда-ошибки бесполезны.

После полуторадневных попыток пробовать все под солнцем, я, наконец, изолировал проблему. У меня есть несколько функций, которые создают метаданные для добавления к новым объектам.

Когда я создавал другую функцию для создания подобных метаданных, я заметил, что у меня есть camelcase для imageType в одной функции и все в нижнем регистре для ImageType в другой. Поэтому я изменил версию с верблюжьим регистром на нижний регистр. По крайней мере, я так думал. Я забыл, что я также инициализировал массив в этой функции версией camelCase, поэтому он вставлял пустую строку для imageType, которая никогда не заменялась значением. Значение было [правильно] вставлено под ключом imagetype.

По какой-то причине amazon в своей бесконечной мудрости решила выбросить ошибку, не совпадающую с подписью, потому что там было imageType = ''. Как только я исправил этот случай (который я только что заметил, когда проходил тестирование кода и не думал, что он действительно что-то решит для проблемы), он начал работать. Поскольку я сделал это мимоходом, мне даже потребовалось несколько минут, чтобы понять, что на самом деле это исправило.

smh

Подробнее о том, почему метаданные:

В случае с миниатюрами у меня нет контроля над всеми способами загрузки изображения (таким образом, сочетание триггера события и возможности ручного триггера для создания миниатюрных изображений). В результате мне не очень хочется копировать и переименовывать файл изображения, чтобы добавить к нему метаданные, которые нужны нашим инструментам пользовательского интерфейса, такие как тип изображения, ширина и высота в пикселях. Вместо этого метаданные в приведенном выше примере извлекаются при создании миниатюры, поскольку эта информация доступна, поэтому я просто помечаю ее на самом миниатюре. Затем, если мне нужно знать ширину и высоту изображения в пикселях, я могу просто вытащить заголовок изображения, чтобы получить эти детали, без необходимости загружать все изображение и заглядывать внутрь него. Мне даже не нужно тянуть весь эскиз таким образом. Время и размер включены для сравнения с фактическим заголовком изображения, чтобы убедиться, что сама миниатюра актуальна с соответствующим изображением в другом сегменте.

0
Scott 20 Ноя 2019 в 21:40