Skip to content

IglanCardeal/my-sweet-url-api

Repository files navigation

My Sweet URL

Projeto de uma API Restful para encurtar URL's


Status do Projeto

🚧 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.

TODO

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

Tabela de conteúdos

Sobre ☕

Sobre esta API

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.

Projeto front-end

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.

API Rate Limiter ✋

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...

Features 📋

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...

Usuário anônimo

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 a url 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.

Usuário cadastrado

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.

Testes

Testes manuais

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:

Testes automatizados

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.

Endpoints

Métodos e retornos anônimos (Publico)

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.

Listar todas as URLs publicas
  • 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
Listar todas as URLs publicas
  • 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

Como usar localmente? 📌

Requisitos

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.

Não tem MongoDB instalado?

Sem problemas!

Atlas

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 de email-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.

você usa Docker? 🐳

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 o docker-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.

Quais tecnologias/ferrramentas foram usadas? 🔧

Autor

iglan cardeal

Iglan Cardeal

Desenvolvido e mantido por Iglan Cardeal 🔨
Desenvolvedor NodeJS 💻
Entre em contato! 👋🏽