Validando requests no express usando Joi

Matheus Vellone
stonetech

--

Uma simples pesquisa por never trust the client no Google e você vai encontrar vários resultados sobre o porquê não devemos nunca confiar no cliente. Nesse caso, cliente remete a qualquer usuário que use sua aplicação, esteja ele bem, ou mal intencionado.

Mesmo que o client-side da sua aplicação seja desenvolvido por você mesmo, e que sua API não é exposta nem documentada em lugar nenhum, o usuário sempre poderá abrir o dev tools do navegador e "aprender" a usar a sua API apenas visualizando as requests que são feitas. Inclusive já fiz projetos pessoais para automatizar rotinas utilizando essa técnica.

Existem várias formas de se proteger de usuários mal intencionados, e a forma mais simples é a validação dos dados enviados.

Exemplo de uma API sem validação de input de dados na vida real

Esse artigo explica e apresenta uma forma de fazer validação dos dados recebidos da request usando express e Joi que resolve o problema de forma eficaz e sem adicionar muita complexidade ao projeto como um todo.

Para começarmos, precisamos de um middleware que funcione em qualquer rota e garanta uniformidade na interface de resposta. O importante nesse ponto é que sejam validados apenas os dados sem gerar complexidade desnecessária ou aglutinar responsabilidades de outros trechos do projeto:

Agora que temos a função que fará a validação e responderá a request em caso de erro, precisamos das regras de validação. E para criá-las precisamos de um schema do Joi com as regras que fizerem sentido para nossa aplicação. Por exemplo:

Agora basta unir os dois pontos declarando a utilização do middleware com a regra que deve ser utilizada:

E com tudo isso, teremos ponto central onde toda validação é realizada.

Bônus: olhando a primeira linha do middleware de validação, veremos que o objeto req inteiro é passado para ser validado. Esse objeto possui todas informações a respeito da request recebida. Algumas dessas informações são enviadas pelo usuário e podem ser validadas:

  • params para validar parâmetros da URL;
  • query para validar parâmetros de query string;
  • e headers para validar, bom, os headers.

Para validar esses parâmetros, basta adicionar uma destas chaves no mesmo nível da chave body no schema de validação utilizado no exemplo.

Recomendo fortemente a leitura desse artigo para isolar melhor as responsabilidades de cada parte do código. Assim, trocaríamos o res.send do middleware de validação para o seguinte

Onde o JoiValidationError seria responsável por transformar o erro do Joi no formato esperado e o error handler seria responsável por responder a request.

Esse artigo não cita em momento algum testes para o código sugerido, mas testá-lo unitariamente não deveria ser um desafio muito grande.

Esse é um formato que cheguei depois de um tempo brincando em uma API onde aplico over-engineering para explorar novas formar de se resolver um problema. Você pode encontrar mais exemplos no repositório onde mantenho esse código.

--

--