Функция AWS SAM Lambda для загрузки в S3 возвращает неверный ответ

Я пытаюсь написать лямбда-функцию для загрузки файла на S3, используя AWS SAM... Я тестирую ее локально, но похоже, что ничего не происходит, и лямбда-функция завершается недопустимым ответом. Других ошибок не регистрируется. Что происходит?

Это журнал выполнения:

START RequestId: 71030098-0dd5-1137-0e78-43f1b1671b9c Version: $LATEST
END RequestId: 71030098-0dd5-1137-0e78-43f1b1671b9c
REPORT RequestId: 71030098-0dd5-1137-0e78-43f1b1671b9c  Duration: 2118.53 ms    Billed Duration: 2200 ms    Memory Size: 128 MB Max Memory Used: 46 MB  
2019-03-27 10:59:00 Function returned an invalid response (must include one of: body, headers or statusCode in the response object). Response received: null
2019-03-27 10:59:00 127.0.0.1 - - [27/Mar/2019 10:59:00] "POST /myfunction HTTP/1.1" 502 -

Лямбда-код. Файл, который будет загружен на S3, исходит из тела запроса.

const async = require('async');
const axios = require('axios');
const AWS = require('aws-sdk');
const s3 = new AWS.S3();

const bucketName = process.env.STRINGS_BUCKET_NAME;

exports.lambdaHandler = async (event, context) => {
    let response;

    try {
        const body = JSON.parse(event.body);
        const jsonFilename = new Date().getTime() + '.json';

        async.waterfall([
            function uploadToS3(done) {
                const base64data = new Buffer(body.strings, 'binary');
                s3.putObject({
                        Bucket: bucketName,
                        Key: jsonFilename,
                        Body: base64data,
                    }, (err, success) => {
                        if (err) {
                            console.error(err);
                            throw Error(err);
                        }
                        console.log(success);
                        console.info('File uploaded to S3: ' + jsonFilename);
                        done(null);
                    });
            },
            function doOtherStuff(done) {
                console.log('doOtherStuff');
                done(null);
            }
        ],
            (error) => {
                if (error) {
                    console.error(error);
                    response = {
                        'statusCode': 500,
                        'body': JSON.stringify({
                            statusCode: 500
                        })
                    };
                } else {
                    response = {
                        'statusCode': 200,
                        'body': JSON.stringify({
                            statusCode: 200
                        })
                    };
                }
            });
    } catch (err) {
        console.error(err);
        return err;
    }

    return response
};

Часть моего template.yaml, где я определил лямбда-функцию:

Resources:
  UserStringsBucket:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName: 'mybucket'

  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: my-function/
      Handler: app.lambdaHandler
      Runtime: nodejs8.10
      Events:
        MyFunction:
          Type: Api
          Properties:
            Path: /myfunction
            Method: post
      Environment:
        Variables:
          STRINGS_BUCKET_NAME: 'mybucket'
      Policies:
        - AWSLambdaExecute
        - Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action:
                - s3:PutObject
                - s3:PutObjectACL
              Resource: 'arn:aws:s3:::mybucket/*' 

person June    schedule 27.03.2019    source источник


Ответы (2)


Похоже, вы получаете эту ошибку, потому что не ждете завершения асинхронных функций. Вы вызываете async.waterfall, а затем у вас есть строка return response, и поскольку функции внутри водопада выполняются асинхронно, ваша return response завершается первой, отсюда и ошибка Function returned an invalid response.

Чтобы подтвердить это, вы можете изменить свою строку let response; на let response = {'statusCode': 200, 'body': 'not yet completed'}; и посмотреть, получите ли вы этот ответ обратно.

person Deiv    schedule 27.03.2019

@Deiv указал мне правильное направление.

Мне пришлось изменить подпись функции на:

exports.lambdaHandler = (event, context, callback) 

И вернул ответ внутри водопада с:

callback(null, response);

Мне также пришлось вручную создать корзину на AWS... Я думал, что SAM сделает это автоматически, но подумай.

person June    schedule 27.03.2019
comment
Рад, что вы решили эту проблему, я все же хочу спросить, вы уверены, что ваше ведро не создается? Ваш ресурс AWS::S3::Bucket кажется правильным, и он должен создавать ведро автоматически... мне не приходит в голову, я думаю, что он может создавать его в другом регионе (он будет развернут в регионе ваша облачная формация развернута в) - person Deiv; 27.03.2019