Roselle Ebarle Roselle Ebarle - 23 days ago 14
Node.js Question

Proper request template mapping or process in order to upload a photo to s3 using Serverless Framework

I am using Serverless Version 1.0.0 and Node Version 5.7.1

I have an endpoint for updating a photo of a table in a mysql database. So prior to inserting the said photo, i am uploading the formdata i get from the browser to s3, and then update the photo url using the return image url.

The problem is i don't know what is the proper way to define the request mapping template in serverless.yml so that i could extract the photo, AND the path parameters AND the $context variable for the principal id

Here is my current serverless.yml function definition

updateBoardPhoto:
handler: handler.updateBoardPhoto
events:
- http:
path: boards/{boardId}/photo
method: PUT
integration: lambda
parameters:
headers:
Authorization: false
body:
photo: true
paths:
boardId: true
request:
passThrough: WHEN_NO_TEMPLATES
template:
multipart/form-data: '{"principalId" : "$context.authorizer.principalId", "body" : $input.json("$"), "boardId": "$input.params(''boardId'')"'


Now here is the handler i have:

function updateBoardPhoto(event, context, callback) {
var photo = event.body.photo;
var boardId = event.boardId;
var principal = utils.processPrincipalId(event.principalId);

var s3FileName = randomstring.generate(10) + ".jpg";
var s3 = new AWS.S3();
s3.putObject({
Bucket: config.UPLOAD_BUCKET,
Key: s3FileName,
Body: photo,
ACL: 'public-read',
}, function (err, data) {
if (err) {
throw err;
} else {
console.log(data);
context.succeed(data);
}
});


Attempt 1



I tried to use
WHEN_NO_TEMPLATES
passthrough option, and defined no template but i only get the
photo
buffer input variable, and no
boardId
. BUT i successfully upload the photo to s3.

request:
passThrough: WHEN_NO_TEMPLATES

// event variable i get:
{ photo: <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 02 1c 00 00 00 ac 08 06 00 00 00 30 ab 75 20 00 00 00 19 74 45 58 74 53 6f 66 74 77 61 72 65 00 ... >,


isOffline: true,
stageVariables: {} }

Attempt 2



Using the ff request definition:

request:
passThrough: WHEN_NO_MATCH
template:
multipart/form-data: '{"principalId" : "$context.authorizer.principalId", "body" : $input.json("$"), "boardId": "$input.params(''boardId'')"'

// event variable i get
{ isOffline: true, stageVariables: {} }


I see no variables in my event variable at all! No photo, nor boardId.

Can anyone tell me what i'm doing wrong? I am using postman to test.

Answer

I think you are passing an image as JSON format, so you can use $input.body to access the entire body in the template. Also you should put single single quote around the parameter name instead of double single quote.

Like, multipart/form-data: '{"principalId" : "$context.authorizer.principalId", "body" : "$input.body", "boardId": "$input.params('boardId')"'


FYI:

API Gateway doesn't support binary data currently. I recommend you to send a base64 encoded string of the image to API Gateway, then you base64 decoded before you put into S3 in you Lambda function.