🚧 Em reestruturação... 🚧
Desconsidere este README por enquanto, pois ele será refatorado futuramente de acordo com a reformulação deste projeto. Ainda não decidi quais pontos vou reescrever, então vou deixar o README original como referência.
V1
- Refatorar os códigos de mensagens de API Rate Limiter
- Incluir solução de Cache para redirecionamento de url
- Atualizar cache para cada alteraçãoo/criação de url
- Adicionar eventos para atualizar cache de urls ordenadas
- Finalizar a documentação
- Descomentar as imagens deste readme
V2
- Incluir recuperação de senha
- Incluir geração de arquivos CSV de urls cadastradas pelos usuários cadastrados
- Envio de CSV por email do usuário (se possível)
- Verificar possibilidade de cadastrar/entrar com Google OAuth
- Sobre
- API Rate Limiter
- Features
- Features em desenvolvimento
- Endpoints
- Como usar localmente
- Tecnologias/ferramentas usadas
- Autor
Este projeto foi feito com objetivo de enriquecer meu portfólio e ampliar meus conhecimentos em NodeJS, desenvolvendo uma aplicação de back-end que consiste de uma API Restful para encurtar URL's, onde um usuário, cadastrado ou anônimo, pode informar uma url que ele julgue ser grande demais, ou que ele queira anônimar, e receberá a sua versão equivalente encurtada, para ele possa usá-la ou compartilhá-la.
Por exemplo, um usuário anônimo pode informar uma url do tipo:
https://www.umaurlgrandequalquer.com.br/caminho/de/teste/1
informar um apelido, por exemplo: minha-url
, e receber, como retorno, por exemplo, a sua versão equivalente encurtada: http://localhost:8080/minha-url
. Neste caso o host está como http://localhost:8080
pois estou adotando como exemplo o servidor local de desenvolvimento da API, rodando em minha máquina com minhas configurações de servidor. Em produção ou em outros ambientes de teste, esse host está sujeito a valores diferentes.
Quando afirmo url equivalente, estou dizendo que o servidor será capaz de capturar o apelido no link http://localhost:8080/
minha-url
, resolver este apelido e redirecionar para a url de destino, https://www.umaurlgrandequalquer.com.br/caminho/de/teste/1
.
Os recurso que cada usuário, anônimo ou cadastrado, pode usar, será especificado e explicado a seguir na documentação.
Após esta API está concluída, vou desenvolver um front-end para implementar as funcionalidades desta API. O projeto front-end será feito em React (NextJS) e, futuramente, pretendo criar um app deste front-end com React Native, quando meus conhecimentos nesta plataforma estiverem mais consolidados. Consulte os repositórios deste perfil para ver se já está disponível o projeto front-end.
Este projeto possui limitadores de API para ajudar a previnir ataques DoS e DDoS. Um dos exemplos do efeito desta medida protetora é para realizar o login na aplicação que possui um limite de 5 tentativas de login antes de bloquear futuras tentativas por 1 minuto.
As outras rotas também possuem limitadores incluindo proteção para Brute Force Attack, máximo de uso da API por dia, dentre outros...
Esta aplicação pode ser de duas formas: Usuário anônimo ou usuário cadastrado.
Dependendo da forma que a aplicação será usada, determinado recurso estará ou não disponível.
Quais recursos estão diponíveis e para quem? 🤔
Vamos ver a seguir...
Um usuário que não está cadastrado no sistema (usuário anônimo), ele tem acesso aos seguintes recursos/benefícios:
-
Encurtar uma URL, informando um apelido (
alias
) e aurl
a ser encurtada (www.urlgigante.com.br
). -
Visualizar todas as URLs encurtadas e que estão publicas (
"public_status": true
). -
Limite de 10 caracteres para o apelido informado.
-
Tamanho do apelido aleatório gerado pelo sistema é de 7 caracteres.
Exemplo:
Executando o projeto localmente, um usuário anônimo que informar os seguintes parâmetros:
{
"url":"https://www.youtube.com/watch?v=O_Cc-Xzc0zM",
"alias": "seu-tubo"
}
Receberá o seguinte retorno:
{
"message": "Nova URL adicionada com sucesso.",
"urlCreated": {
"alias": "seu-tubo",
"url": "https://www.youtube.com/watch?v=O_Cc-Xzc0zM",
"shortenedUrl": "http://localhost:8080/seu-tubo",
"domain": "youtube.com",
"public_status": true,
"createdAt": "24/11/2020"
}
}
A resposta vem padronizada para usuários anônimos, ou seja, toda e qualquer URL que ele encurtar, terá por padrão o status publico. Qualquer usuário pode visualizar a URL (que for publica), que foi encurtada e o seu apelido.
O apelido não é obrigatório, o usuário pode apenas informar a url, o apelido será gerado com nome aleatório pelo serviço do back-end.
Um usuário pode se cadastrar no sistema e ter acesso a alguns recursos a mais que um usuário anônimo. Estes recursos podem ser relevantes ou não dependendo da vontade do usuário.
Ao se cadastrar na aplicação, o usuário autenticado pode, além de acessar todos os recursos para usuários anônimos, ter acesso aos seguintes recursos/benefícios:
-
Definir a url encurtada como privada (esta não será exibida na listagem publica).
-
Editar uma url privada que ele criou, alterando seu apelido ou url.
-
Limite de 14 caracteres para o apelido informado
-
Tamanho do apelido aleatório gerado pelo sistema é de 5 caracteres.
Um usuário quando define uma url como privada, esta apenas não será exibida na listagem publica de urls encurtadas, logo nada irá impedir de o usuário compartilhar a sua url encurtada, mas cabe ao usuário garantir o funcionamento da mesma, pois se ele utiliza uma url privada em algum lugar, e por algum motivo ele editou o apelido ou excluiu, esta não irá funcionar corretamente.
O projeto possui um arquivo json chamado Insomnia_API.json
que server para fazer teste manuais das rotas e recursos da aplicação. Usando o aplicativo para testar API's Insomnia, você pode importar o arquivo deste projeto e começar a testar.
As chamada para a API estão organizadas por pastas, para facilitar o entendimento do arquivo. As pastas estão divididas de acordo com os recursos que as chamadas solicitão:
-
Signup Login Logout
: é responsável por tratar chamadas para as funcionalidades de autenticação e cadastro de novos usuários; -
User
: é responsável por tratar chamadas para funcionalidades de usuário cadastrado e autenticado no sistema, como criar urls privadas, editar, excluir, etc...; -
Public
: é responsável por tratar chamadas para funcionalidades de usuário anônimo, como criar e visualizar urls publicas.
Na pasta Public
, eu adicionei chamadas personalizadas para testar recursos de paginação, ordenação dos dados retornados pela API, como por exemplo, ordenar por data de criação/apelido/dominio/numero de acessos, além de poder fazer uma busca filtrada, filtrando a busca por dominio, por exemplo.
Veja abaixo um exemplo de filtrar publicamente uma url por dominio, através de uma query string:
Apesar deste projeto não ter seguido a metodologia TDD, eu irei inserir testes usando a biblioteca JEST. Quando feito, será informado nesta seção a explicação para usos de testes automatizados.
Estes metodos estao relacionados a usuários anônimos (sem cadastro no sistema) onde estes usuários podem cadastrar uma nova url, que por padrão, esta url é publica, e visualizar todas as url publicas cadastradas no sistema.
-
Método:
GET
-
Path:
/api/urls
-
Corpo de requisicao:
null
-
Retorno da requisicao (exemplo):
{
"message": "Todas as URLs publicas.",
"public_urls": [
{
"alias": "seu-tubo",
"url": "https://www.youtube.com/"
}
]
}
Campo | Tipo | Descrição |
---|---|---|
message | string |
Mensagem de informação da consulta |
public_urls | Array |
Array de objetos contendo o alias e a url das urls cadastradas |
alias | string |
Nome do apelido dado para a url encurtada |
url | string |
url cadastrada |
É possível ordernar as public_urls
através das query strings. É possível ordernar se baseando nos seguintes atributos:
domain
, ordena as urls de acordo com o domínio em ordem alfabética;number_access
, ordena as urls de acordo como o número de acessos em ordem decrescente;alias
, ordena as urls de acordo com o apelido em ordem alfabética;date
, ordena as urls de acordo com a data de criação das mais recentes para as mais antigas.
Para ordenar deve-se informar via query string no path
os valores para a variável orderby
.
Exemplo:
- Ordena por domínio:
/api/urls?orderby=domain
- Ordena pela data de criação:
/api/urls?orderby=date
Para paginar os resultados, informar na query string o valor para a variável page
.
Exemplo:
- Ordena por domínio e retorna a primeira página:
/api/urls?orderby=domain&page=0
- Ordena por domínio e retorna a segunda página:
/api/urls?orderby=domain&page=1
-
Método:
GET
-
Path:
/api/urls/filtered
-
Corpo de requisicao:
null
-
Retorno da requisicao (exemplo):
{
"message": "Todas as URLs publicas.",
"public_urls": [
{
"alias": "seu-tubo",
"url": "https://www.youtube.com/"
}
]
}
Campo | Tipo | Descrição |
---|---|---|
message | string |
Mensagem de informação da consulta |
public_urls | Array |
Array de objetos contendo o alias e a url das URLs cadastradas |
alias | string |
Nome do apelido dado para a URL encurtada |
url | string |
URL cadastrada |
Para usar localmente em sua máquina, voce deve ter instalado em sua máquina o NodeJS com uma versão minima recomendada v12.0.0
, MongoDB e o Git.
Além disto é bom ter um editor para trabalhar com o código como VSCode.
Para começar, faça o clone deste repositório. Digite o comando no terminal:
$ git clone https://github.com/IglanCardeal/my-sweet-url-api
Acesse a pasta do projeto:
$ cd my-sweet-url-api
Instale as dependências do projeto usando o npm
ou yarn
se preferir:
$ npm install
# ou
$ yarn install
Agora precisamos configurar o arquivo .env
, que contém as variáveis de ambientes essenciais para executar a aplicação. Neste respositório, temos um arquivo de exemplo das variáveis de ambiente chamado .env,example
. Abra esse arquivo e veremos o seguinte:
# APP detalhes
APP_NAME= App Envio de Email
APP_AUTHOR= Iglan Cardeal
APP_EMAIL= emailperformanceapp@teste.com
# APP Port
PORT= 3000
HOST= localhost
# Database MongoDB
DB_NAME=app-envio-email
DB_PORT=27017
# Quando NODE_ENV=development
DB_DEV_HOST=127.0.0.1
# Quando NODE_ENV=production
DB_HOST=127.0.0.1
# URL Provedor externo
DB_HOST_EXTERNAL=
Agora, renomeie o arquivo .env.example
para .env
.
Feito isso, execute o comando abaixo e o aplicativo será iniciado localmente como ambiente de desenvolvimento em sua máquina:
$ npm run dev
# ou
$ yarn dev
Agora abra seu navegador na URL http://localhost:3000
e verá a página inicial do projeto.
Sem problemas!
Você pode inserir uma URI de algum provedor como o Atlas. Neste caso, vamos definir um URI no em DB_HOST_EXTERNAL=
. Esta variável tem prioridade, logo se você definiu uma URI, ela será usada, senão deixe-a vazia.
A URI a ser usada, no caso se você usar o Atlas, terá o formato semelhante a seguir:
DB_HOST_EXTERNAL=mongodb+srv://<username>:<password>@cluster0.zcr3z.mongodb.net/<dbname>?retryWrites=true&w=majority
Onde:
-
username
: seu nome de usuário -
password
: sua senha -
dbname
: nome da base de dados. Eu recomendo chamar deemail-performance-app
Tendo Feito todas as configurações, execute npm run dev
ou yarn dev
para iniciar a aplicação.
OBS: ao executar o comando para iniciar a aplicação, será exibido no terminal a URI de conexão com o banco.
Uma solução alternativa é subir um container do Docker do MongoDB. Existe a imagem oficial do mongo que podemos usar para subir um container mongodb e usar o banco de dados.
Na raíz do projeto temos um arquivo docker-compose.yml
com as seguintes características:
version: "3"
services:
# app:
# container_name: my_sweet_url
# build: .
# ports:
# - "3000:3000"
# command: yarn dev
# # volumes:
# # - ./data:/data/db
# links:
# - mongo
mongo:
container_name: my_sweet_mongo
image: mongo
ports:
- ${DB_PORT}:27017
Esse arquivo é a base para gerar um container do mongodb.
Temos também um arquivo Makefile
para que possamos executar comandos do docker-compose
de uma maneira mais rápida.
Características do Makefile
:
include .env
.PHONY: up
up:
docker-compose up -d
.PHONY: down
down:
docker-compose down
.PHONY: logs
logs:
docker-compose logs -f
-
include .env
carrega as variáveis de ambiente do arquivo.env
. -
up
executa odocker-compose
com os containers em background -
logs
exibe os logs -
down
desmonta os containers
Para subir o container, digite no terminal make up
, e aguarde o docker baixar e montar a imagem do mongodb.
Ao finalizar, execute make logs
, para verificar se tudo ocorreu bem nos logs.
Execute make down
para desmontar o container.
Iglan Cardeal
Desenvolvido e mantido por Iglan Cardeal 🔨
Desenvolvedor NodeJS 💻
Entre em contato! 👋🏽
- cmtcardeal@outlook.com 📧
- Instagram @cmtcardeal
- StackOverflow Cmte Cardeal