I'm trying to write a Lambda function to upload a file to S3, using AWS SAM... I'm testing it locally but it looks like nothing is happening and the lambda function ends with invalid response. No other errors are logged. What is going on?
This is the execution log:
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 -
Lambda code. The file that will be uploaded to S3 comes from the request body.
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
};
Part of my template.yaml where I defined the lambda function:
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/*'
It looks like you're getting this error because you're not waiting for the async functions to complete. You call async.waterfall, and then you have your return response
line, and because the functions inside the waterfall run async, your return response
gets finished first, hence the Function returned an invalid response
error.
To confirm this, you can change your let response;
line to let response = {'statusCode': 200, 'body': 'not yet completed'};
, and see if you get this response back.