Save File to S3
As you saw in the last exercise, taking screenshots is a slow process. You wouldn't want to do that every time a user wants to see your picture.
And API Gateway isn't the happiest about serving images. You'll get high bandwidth bills.
A better solution is to store your screenshot to S3 - a service made specifically for static file storage.
Exercise
Copy your solution from exercise-4 to exercise-5, or start from mine in the repository.
Create a new YAML file to specify a new S3 bucket. This is where infrastructure as code shines.
# s3.ymlResources:ScreenshotsBucket:Type: AWS::S3::Bucket
Then include this file as a resource in your serverless config. And install the serverless-resources-env
plugin.
# serverless.ymlresources:- ${file(s3.yml)}plugins:- serverless-resources-env
You can now access your new S3 bucket's name as process.env.CF_ScreenshotsBucket
You'll need to grant access to this bucket from your Lambda .
# serverless.ymlprovider:iamRoleStatements:- Effect: "Allow"Action:- "s3:*"Resource: "arn:aws:s3:::*/*"
This grants full permissions on all S3 buckets in your account. You can limit to a specific bucket and specific permissions with tricky incantations. The biggest pain point of AWS if you ask me.
To upload your screenshot to S3, use code like this:
// dont forget to import util and fsconst readFile = util.promisify(fs.readFile)const buffer = await readFile(path)// aws comes from importing aws-sdkconst s3 = new aws.S3({apiVersion: "2006-03-01",})const { Location } = await s3.upload({Bucket: process.env.CF_ScreenshotsBucket,Key: "<filename>.png",Body: buffer,ACL: "public-read", // grant public read access}).promise()
Return the Location from your function.
Try your function
Leave payload empty for GET requests, valid JSON for POST.
Solution
https://github.com/Swizec/serverless-workshop-exercises/tree/exercise-5-solution