Функция AWS SAM Lambda для загрузки на S3 возвращает неверный ответ - PullRequest
0 голосов
/ 27 марта 2019

Я пытаюсь написать лямбда-функцию для загрузки файла в 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/*' 

Ответы [ 2 ]

1 голос
/ 27 марта 2019

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

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

0 голосов
/ 27 марта 2019

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

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

exports.lambdaHandler = (event, context, callback) 

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

callback(null, response);

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

...