Opa, espero que esteja tudo bem com você que está lendo esse artigo no momento.
Passei por situações interessantes, no período em que desenvolvia uma feature na atual empresa em que me encontro.
Tive a necessidade de utilizar recursos da AWS, seja para aprender o que eu iria manusear, como implementar no ambiente corporativo de forma correta.
Durante meus estudos, para evitar gastos, procurei soluções que me permitiriam usar as funções de armazenamento e envio de e-mail da AWS de forma gratuita. Até que finalmente encontro um recurso, que simula o ambiente cloud da AWS dentro da sua máquina local.
O Localstack: https://localstack.cloud/
, é um recurso que possibilita simular diversos recursos AWS (dynamoDB, s3, iam, cognito, ses), dentro da sua máquina, utilizando o docker.
Pré-requisitos
- Docker & Docker-compose
- Node (Minimo na versão 16)
- Aws-cli instalada na máquina
Para ativar, basta criar um docker compose no seu projeto com os seguintes comandos:
version: "3.8"
services:
localstack:
container_name: "localstack"
image: localstack/localstack:1.0.4
ports:
- "4566:4566" # LocalStack Gateway
environment:
- DOCKER_HOST=unix:///var/run/docker.sock
- DEFAULT_REGION=us-east-1
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
Rode o comando docker-compose up
para inicializar o funcionamento do localstack
Para validar se está realmente funcionando, abra o seu navegador na seguinte url => http://localhost:4566/health
Iniciando um projeto Node
Não iremos nos preocupar com padrão de projetos, apenas queremos criar uma aplicação, para: criar um arquivo num bucket S3, remover o arquivo, receber a url assinada, enviar um e-mail pelo SES
crie uma pasta e abra no editor de texto da sua preferencia
Inicie o seu projeto node com o seguinte comando:
yarn init -y
Instalando as dependencias
yarn add aws-sdk@2.1438 axios@1.4
yarn add @types/node@20.5 @types/axios@0.14 localstack@1 ts-node-dev@2 typescript@5.1.6 -D
Inicializando o Typescript
yarn tsc --init
dentro do package.json, adicione o script para rodar o projeto
"scripts": {
"dev": "ts-node-dev --respawn --transpile-only index.ts"
},
crie um arquivo chamado index.ts
O projeto terá a seguinte estrutura
Codificando o projeto
Dentro do index.ts, iremos realizar as configurações dos serviços S3 e SES
import AWS from 'aws-sdk'
import axios from 'axios'
const s3config = {
s3ForcePathStyle: true
}
const sesConfig = {
apiVersion: '2010-12-01'
}
const isLocal = true
if(isLocal) {
AWS.config.update({
credentials: {
accessKeyId: 'test',
secretAccessKey: 'test'
},
region: 'us-east-1'
})
const host = 'localhost'
const awsEndpoint = new AWS.Endpoint(`http://${host}:4566`);
//@ts-ignore
s3config.endpoint = awsEndpoint
//@ts-ignore
sesConfig.endpoint = awsEndpoint
}
const s3 = new AWS.S3(s3config);
const ses = new AWS.SES(sesConfig)
const bucketName = 'local-data-files'
OBSERVAÇÕES: Dentro da constante isLocal, poderemos inserir esse valor em uma variável de ambiente, para que quando for enviado para ambientes de homologação e Produção, utilizemos os reais valores da AWS e não do Localstack
Para definir que o ambiente utilizado será o localstack, é necessário configurar as chaves da AWS e alterar o endpoint que as classes irão realizar as requisições
AWS.config.update({
credentials: {
accessKeyId: 'test',
secretAccessKey: 'test'
},
region: 'us-east-1'
})
const host = 'localhost'
const awsEndpoint = new AWS.Endpoint(`http://${host}:4566`);
Para realizar a codificação dos demais serviços, iremos criar duas classes
class StorageManagement {
}
class SendEmail {
}
Para as funções de gerenciamento no S3, adicionaremos os seguintes comandos:
class StorageManagement {
public async execute() {
const image = 'https://www.purina.co.uk/sites/default/files/2020-12/Dog_1098119012_Teaser.jpg'
const buffer = await this.downloadImage(image);
const upload = await this.upload(buffer);
await this.remove(upload.Key);
}
private async downloadImage(imageUrl: string) {
const response = await axios.get(imageUrl, {
responseType: 'arraybuffer'
})
const buffer = Buffer.from(response.data, 'base64');
return buffer
}
private async upload(buffer: Buffer) {
const s3Upload = await s3.upload({
Bucket: bucketName,
Key: `FILE_${(new Date()).getTime()}`,
Body: buffer
}).promise();
return s3Upload
}
private async remove(key: string) {
await s3.deleteObject({
Bucket: bucketName,
Key: key
})
}
}
E para o envio de e-mail, temos o seguinte código:
class SendEmail {
public async execute() {
var params = {
Destination: {
ToAddresses: [
'envio@teste.com',
]
},
Message: {
Body: {
Html: {
Charset: "UTF-8",
Data: "This message body contains HTML formatting. It can, for example, contain links like this one: <a class=\"ulink\" href=\"http://docs.aws.amazon.com/ses/latest/DeveloperGuide\" target=\"_blank\">Amazon SES Developer Guide</a>."
},
Text: {
Charset: "UTF-8",
Data: "This is the message body in text format."
}
},
Subject: {
Charset: "UTF-8",
Data: "Test email"
}
},
Source: "teste@mailinator.com",
};
const emailSend = ses.sendEmail(params).promise()
}
}
Antes de rodar nossa aplicação e ver o funcionamento, precisamos realizar alguns comandos via script para que o código funcione
crie um arquivo script.sh e adicione os seguintes comandos
# Nome do Bucket
BUCKET_NAME=local-data-files
# Comando AWS para criar um bucket no S3
# o Endpoint é para definir que iremos criar dentro do localstack
aws \
s3 mb s3://$BUCKET_NAME \
--endpoint http://localhost:4566
# Comando para validar o e-mail que iremos utilizar para teste no Localstack
aws ses verify-email-identity \
--email-address teste@mailinator.com \
--endpoint-url=http://localhost:4566
Para executar digite no terminal
sh script.sh
Testando
Para Testar cada uma das funcionalidades, instancie as classes e chame a função execute
const test = new StorageManagement()
const testSES = new SendEmail()
testSES.execute()
test.execute()
Validando
Para Validar se o arquivo está presente no s3, deve-se executar o seguinte comando sh
BUCKET_NAME=local-data-files
aws \
s3 ls s3://$BUCKET_NAME\
--endpoint http://localhost:4566
Para visualizar se o email foi enviado, entre na seguinte url
http://localhost:4566/_localstack/ses
Espero que esse artigo tenha sido útil para você. Deixe seu comentário e sugestão de próximo tema.
Até mais! ❤️
Repositório GitHub do artigo
https://github.com/DEVinicius/use-s3-ses-localstack
Top comments (0)