Slim Framework — Criando Microservices 06 — Middlewares, Logging e HTTP Errors Fallback

Fala pessoal, tudo bem? Olha eu aqui mais uma vez falando sobre a construção de uma API REST voltada a Microservice como Microframework Slim. Nesse post vamos nos aprofundar um pouco mais nos Erros Handling específicos, brincar um pouco com Middlewares e implementar um sistema de logs em arquivos para debug em templo de execução.

Caso não tenha visto os outros posts, recomendo muito que leia antes de iniciar aqui caso tenha caído de paraquedas:

Um middleware, de uma maneira simplificada, é uma camada que fica “no meio” na primeira camada que recebe o request para a aplicação, todas camadas de acesso a informação, lógica de negócio até a ultima camada que devolve um response para o usuário. Ou seja, os middlewares podem manipular nossos dados e comportamentos antes de nos entregar para que possamos gerenciar os mesmos e devolver algo para o usuário.

Primeiro Middleware: Tratando a / do request

Aqui vamos precisar aplicar uma cama de Middleware bem simples que vai fazer algumas modificações do nosso Request antes de entregá-la para alguma rota da nossa aplicação.

Por Default, em diversos frameworks que nos fornecem algum serviço de rotas, essas declarações para os resources costumam ser literais, ou seja, requests feitos para :

http://meusite.com/meuresource

São diferentes dos requests feitos para:

http://meusite.com/meuresource/

Podendo causar erros de 404 e até dificultando algumas implementações de consumo de algumas API`s como no exemplo abaixo:

Podemos resolver esse problema utilizando um Middleware third party que segue a PSR7 que nos fará redirects para com ou sem / no final da URI que nossos clientes vão requisitar, mantendo um acesso uniforme fazendo com que o acesso ao resource:

http://localhost/book/

Tenha o mesmo efeito que:

http://localhost/book

Parece uma coisa besta e trivial, porém para consumers do nosso serviço, esse detalhe pode acabar dificultando e até gerando uma implementação defeituosa. O Middleware no padrão PSR7 que vamos utilizar nos provê uma gama muito grande de recursos, um deles já implementa isso no Slim para nós durante o Request de uma maneira bem simples, removendo, ou adicionando a / antes de tratar o nosso request pelo restante da aplicação.

Essa biblioteca é um projeto de terceiro, porém é reconhecido e está validado no site do próprio Slim.

Github do Projeto: https://github.com/oscarotero/psr7-middlewares

$ composer require oscarotero/psr7-middlewares

A implementação fica:

use Psr7Middlewares\Middleware\TrailingSlash;

$app->add(new TrailingSlash(false));

Essa classe permite a passagem de argumentos bool no construtor, onde

  • true — Adiciona um / no final
  • false — Remove o / no final

Em nossa implementação nós vamos remover essa / e dar um redirect amigável para o usuário.

bootstrap.php

Podemos testar a implementação facilmente, fazendo requests com e sem o / no final, assim como fizemos para causar o erro.

Gerando Logs do Serviço com Monolog

Uma parte em que perdemos quando adquirimos uma arquitetura voltada a Microservices é na questão de debug. Então, devemos facilitar nossos services para gerar o máximo de logs possível. Para essa missão vamos utilizar uma library de logs muito poderosa chamada Monolog. O monolog possui drivers para diversos tipos de logs como arquivos, syslog, GELF e etc.

Para esse exemplo vamos utilizar via file. Quem sabe em outro artigo não abordamos a implementação do envio de logs direto para um Graylog com o GELF ou um Rsyslog.

$ composer require monolog/monolog

Agora vamos criar a pasta chamada logs na raiz do projeto para armazenar nossos logs da aplicação.

$ mkdir logs/

Vamos implementar nosso Monolog no container de dependências cm o Log Level mínimo de INFO. Esse é o menor nível de Log, ou seja, isso vai nos permitir logar qualquer tipo de informação futuramente.

bootstrap.php

No nosso index, vamos na rota de POST e no final dela vamos adicionar um log de informação contendo o registro da criação de um livro.

...
$logger = $this->get('logger');
$logger->info('Book Created!', $book->getValues());
...

Podemos espalhar em vários locais do nosso Microservice. Inclusive nos locais que possivelmente pode acarretar em um erro. Como em 404, tentativas de update, delete, search e etc.

Error Handling — 405 Not Allowed e Options

Podemos prevenir e informar ao cliente sobre métodos não permitidos de um determinado Resource. Isso pode ser tanto um item de qualidade, quanto informativo quanto de segurança do nosso serviço. Normalmente o Slim nos retornará um html informando sobre o erro, mas a ideia é uniformizar todo o Request e Response via JSON, então vamos retornar o Status Code 405 — Method Not Allowed junto a um JSON contendo a mensagem e os resources disponíveis na API. Também vamos informar via HEADER do response.

bootstrap.php

Testando o Response feito a um método não permitido

Para testar nossa implementação, podemos escolher qualquer um dos métodos HTTP que ainda não foram implementados. No caso, vamos escolher o método PATCH.

$ curl -X PATCH  --verbose http://localhost:8000/book

Podemos ver que o Handling do erro 405 funcionou perfeitamente como o planejado. Ele verificou o método HTTP do request para o resource /book, verificou que não havia nenhuma rota criada para ele na nossa API e já retornou um JSON com o erro que configuramos informando os métodos que estão disponíveis para o cliente no JSON e no HEADER.

Podemos restar isso também com fazendo requests com algum método não implementado como PATCH para o resource informando o ID /book/1 que tem rotas implementadas apenas para GET, PUT e DELETE.

$ curl -X PATCH  --verbose http://localhost:8000/book/1

Error Handling — 404 Not Found

Da mesma forma que implementamos um Fallback para o Erro 405, vamos implementar um igual para o erro 404 para resources não encontrados na nossa API. O comportamento padrão é retornar um HTML com a mensagem de erro, vamos converter isso para JSON no nosso bootstrap

bootstrap.php

No nosso teste, podemos fazer uma requisição GET simples sobre qualquer resource que não exista, pode ser o famoso SADASDASDSD e verificar se a API está fazendo o handling correto com o JSON dos responses 404.

Nosso Projeto até aqui

bootstrap.php

index.php

Espero ter ajudado e até a próxima! Vamos falar de autenticação HTTP e por JWT. Até amanhã!

Nosso código até aqui:

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.