Deprecated AWS 3rd Party Services

@Jason_Tulloch1

I had to move my own application over this weekend. It was a long weekend here in NZ and I figured it was a good time to do it before the August cut off. The one I moved previously was for a client.

As AWS v3 SDK is now recommended over v2, I thought I would try this as it was likely to be much lighter than the v2 package as every service is its own package.

Here are some examples from code I have put together which should give you a good idea of how you can use v3. It seems to be working really well.

The one thing I would avoid is trying to pull data into the function’s memory. That is where you will get bad performance. So no uploading and downloading from S3. Instead, use presigned URLs and do the downloading/uploading in the browser from the client side.

functions/package.json

{
  "name": "functions",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "@aws-sdk/client-lambda": "^3.369.0",
    "@aws-sdk/client-s3": "^3.369.0",
    "@aws-sdk/s3-request-presigner": "^3.369.0",
    "@aws-sdk/client-ses": "^3.369.0"
  },
  "author": "",
  "license": "ISC"
}

functions/aws_getConfig.js

exports = async function () {
  const AWS_CONFIG = {
    credentials: {
      accessKeyId: context.values.get('AWS_ACCESS_ID'),
      secretAccessKey: context.values.get('AWS_SECRET_KEY'),
    },
    region: 'ap-southeast-2',
  }
  return AWS_CONFIG
}

functions/s3_put.js

exports = async function (key) {
  const AWS_CONFIG = await context.functions.execute('aws_getConfig')
  const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3')
  const { getSignedUrl } = require('@aws-sdk/s3-request-presigner')
  const s3Service = new S3Client(AWS_CONFIG)

  const presignedUrl = await getSignedUrl(
    s3Service,
    new PutObjectCommand({
      Bucket: 'BUCKET_NAME',
      Key: key,
      Method: 'PUT',
      ExpirationMS: 120000,
    })
  )
  return presignedUrl
}

Then you can use something like this in your client code.

const preSigned = await s3.uploadFile(fileName) // This is calling your mongo app function
await axios.put(presignedUrl, file, {
  headers: {
    'Content-Type': file.type
  },
})

functions/s3_get.js

exports = async function (key) {
  const AWS_CONFIG = await context.functions.execute('aws_getConfig')
  const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3')
  const { getSignedUrl } = require('@aws-sdk/s3-request-presigner')
  const s3Service = new S3Client(AWS_CONFIG)
  
  const presignedUrl = await getSignedUrl(
    s3Service,
    new GetObjectCommand({
      Bucket: 'BUCKET',
      Key: key,
      Method: 'GET',
      ExpirationMS: 120000,
    })
  )

  return presignedUrl
}

Run Lambda in a function

const AWS_CONFIG = await context.functions.execute('aws_getConfig')
const { InvokeCommand, LambdaClient } = require('@aws-sdk/client-lambda')
const lambda = new LambdaClient(AWS_CONFIG)

const lambdaPayload = {
  foo: 'bar',
}

const lambdaCommand = new InvokeCommand({
  FunctionName: 'FUNC_NAME',
  Payload: JSON.stringify(lambdaPayload)
})

const lambdaResult = await lambda.send(lambdaCommand)
const result = EJSON.parse(Buffer.from(lambdaResult.Payload).toString())
return result

Send an email via SES

const AWS_CONFIG = await context.functions.execute('aws_getConfig')
const { SESClient, SendEmailCommand } = require('@aws-sdk/client-ses')
const ses = new SESClient(AWS_CONFIG)
const sendEmailCommand = new SendEmailCommand({
  Source: `${settings.CompanyName}<noreply@rapido.co.nz>`,
  Destination: {
    ToAddresses: [user.email],
    CcAddresses: [settings.Orders_EmailCC]
  },
  Message: {
    Body: {
      Html: {
        Charset: 'UTF-8',
        Data: email,
      },
    },
    Subject: {
      Charset: 'UTF-8',
      Data: subject,
    },
  },
})
const send = await ses.send(sendEmailCommand)
1 Like