HTTP Status Cheat Sheet

Canela, RS
Canela, RS

Este artigo é abordado na prática nos meus cursos de Node.js!

Já tem alguns anos que trabalho forte com backend e ensino outros a fazê-lo e uma das dúvidas mais recorrentes é sobre o uso correto dos status code HTTP para retorno de mensagens em Web APIs RESTful.

Embora possa parecer muito tentador simplesmente retornar 200 pra tudo e um JSON no corpo detalhando se teve sucesso ou não e sua respectiva mensagem, isso não é nem de perto uma abordagem RESTful, vide que era exatamente o que se fazia no início dos anos 2000 com SOAP.

Então, o artigo de hoje é uma cheat sheet, ou um compilado de status codes comuns que uso e em que situações uso cada um deles. Alguns são extremamente diretos e sem muita margem de interpretação, outros acabam gerando algumas divergências entre devs.

Dentro do possível tentarei me ater à especificação oficial do HTTP, a RFC 7231 de 2014, a mais recente que encontrei e na documentação da Mozilla, que utilizo bastante como base. Ainda assim, caso tenha alguma dúvida ou discordância, deixe nos comentários.

Sucesso

Nesta primeira seção, quero apresentar os status code HTTP que uso para respostas de requisições bem sucedidas.

200 OK

O mais clássico de todos, uso sempre que a requisição foi bem sucedida, o processamento foi concluída, não houve criação de novos recurso e há retorno no corpo da resposta. Pode ser usado por exemplo como resposta para consultas de registros, retornando-os no corpo.

201 CREATE

É uma especialização do 200, onde neste caso, criamos um novo recurso no servidor, como por exemplo ao salvar um novo registro no banco. No corpo da requisição, devemos este registro recém criado.

202 ACCEPTED

Imagine que seu servidor receba a requisição mas que ele vá processá-la de maneira assíncrona, usando filas por exemplo. Você retorna para o cliente que recebeu com sucesso e está processando, mas não há retorno no corpo da resposta.

204 NO CONTENT

Este código indica que seu servidor processou a requisição com sucesso mas não há nada novo para ser devolvido no corpo da resposta. O exemplo clássico é se os seus PUTS e DELETEs não retornam nada, um 204 pode ser utilizado pra eles.

Falha

Nesta segunda seção, vou apresentar os status code HTTP que utilizo para mensagens de erro, usando as famílias 400 e 500.

400 BAD REQUEST

O servidor não conseguiu processar a requisição devido a parâmetros inválidos ou errados nela (headers, path params e query string geralmente), geralmente atrelados a regras de negócio da aplicação. Caso o cliente deseje tentar novamente, ele deve modificar a requisição.

Você pode opcionalmente no corpo da resposta indicar o que o cliente errou (query string faltante, por exemplo), se não for expor informações sensíveis ou que possam ser usadas para explorar a segurança da sua API. Isso serve para ajudar ele a tentar novamente.

500 INTERNAL SERVER ERROR

Diferente do 400 que indica que você deve tentar de novo mudando parâmetros, um erro 500 é devolvido quando um erro inesperado acontece no servidor, algo realmente não previsto como a captura de uma exceção ou um momento difícil do servidor em processar requisições. Também diferente do 400, não há qualquer garantia de que mudando path params, query string, etc o cliente conseguirá realizar nova requisição com sucesso.

Como o erro 500 é algo inesperado, não se recomenda devolver detalhes do erro no corpo da resposta, uma vez que pode expor vulnerabilidades da sua aplicação que nem você conhece. Sendo assim, registre o ocorrido com detalhes internamente, mas devolva um erro genérico ao cliente.

401 UNAUTHORIZED

Um 401 é retornado sempre que uma requisição é enviada para uma rota segura sem informações de autenticação ou com informações inválidas/expiradas. Sem qualquer mensagem sendo necessária, isso já indica ao cliente que ele deve se autenticar primeiro e enviar nas próximas requests suas informações de segurança (geralmente um token JWT ou similar) no header da requisição.

Sob hipótese alguma dê detalhes do seu mecanismo de segurança aqui.

403 FORBIDDEN

Um 403 deve ser retornado quando um usuário não possui permissão para acessar um recurso/rota da sua aplicação ou web API. Não importa se ele está autenticado ou não, é uma request proibida para ele.

Por exemplo, ele pode estar acessando informações de outro usuário manipulando a URL, tentando fazer uma tarefa não permitida para seu perfil de segurança ou tentando acessar pastas do servidor que estão fora dos limites da aplicação.

Por questões de segurança, não se recomenda dar detalhes no corpo do retorno, assim como no 401.

404 NOT FOUND

Um 404 deve ser enviado sempre que um recurso não for encontrado no servidor, como por exemplo uma busca por usuário com um ID inexistente. Como os browsers costumam jogar 404 naturalmente quando se tenta acessar URLs inválidas, pode ser que você queira retornar alguma mensagem mais detalhada no corpo da resposta, indicando se o recurso não existe mesmo, já que o padrão subentende-se que a URL não existe.

Existe uma discussão se em uma tentativa de login com um usuário inexistente se devemos retornar 401 ou 404. Para não dar detalhes do porque a autenticação falhou, o ideal é dar um 401 sempre.

409 CONFLICT

Então veio uma requisição para salvar um cliente novo na base, mas devido a uma regra de negócio ele conflita com outro cliente já existente (CPF repetido talvez). Retornamos um 409 para ele, opcionalmente com detalhes do conflito no corpo da resposta.

Alguns devs usam 400 para estes conflitos, mas existe um código específico para eles, então é uma boa utilizá-lo.

422 UNPROCESSABLE ENTITY

Este é outro exemplo de status code que os devs costumam usar 400 por preguiça. Diferente do 400 BAD REQUEST que é mais genérico, que serve para requests com qualquer problema, o 422 é mais específico e trata de entidades enviadas junto da requisição, ou seja, no seu body. Esta entidade enviada não pode ser processada, geralmente devido a uma regra e negócio do servidor, como validação de campos, por exemplo.

Então, se você faz validação de entidades nas requests e uma request não passou na validação, retorne um 422 pra ela, geralmente com mais informações da negativa no corpo da resposta.

429 TOO MANY REQUESTS

Este erro aqui é mais específico para web APIs que possuam limite de requests mensal, como SMTP Gateways e outros serviços populares que cobram por uso. Quando uma request de um cliente chega no servidor, mas a quota de uso do cliente já está estourada, deve-se retornar um 429.

Como é um recurso bem atrelado ao business da sua aplicação, pode ser interessante retornar mais detalhes no corpo da resposta, indicando qual recurso que ele exauriu o uso no mês e próximos passos se ele quiser pagar mais.

Outros códigos

Vale aqui uma menção do porquê não utilizo outros códigos além destes.

Sobre os códigos da família 300, são todos relacionados a redirecionamentos. Quando faço esse tipo de processamento, geralmente a própria biblioteca que estou usando (como o Express no caso de Node.js) já retorna o status code de redirecionamento correto.

Sobre o 405 METHOD NOT ALLOWED e o 501 NOT IMPLEMENTED, geralmente quando não implementamos um método na Web API, e um usuário tenta usar, ele recebe um 404. Não faz muito sentido pra mim implementar uma rota apenas para retornar um 405. O mesmo vale para um 410 GONE, se o recurso não existe mais, vai receber um 404 na minha opinião (mesmo no caso de soft-delete).

408 REQUEST TIMEOUT é enviada automaticamente pelos servidores quando esgota o tempo da requisição ser processada, bem como o 413 PAYLOAD TOO LARGE quando o body está grande demais, o 414 URI TOO LONG quando a URL está exagerada, o 431 REQUEST HEADER FIELDS TOO LARGE quando é o header que está exagerado e o 503 SERVICE UNAVAILABLE quando o servidor não está dando conta. Ou seja, nunca tive de usar eles a nível de aplicação.

Não espero esgotar este assunto com apenas este artigo, mas ao menos dar uma ajuda e ideia geral de uso de alguns status codes populares para quem ainda está começando esta jornada com RESTful.

Um abraço e sucesso.

Quer aprender a construir web apis e aplicações web comigo? Confira o meu curso abaixo.

Curso Node.js e MongoDB

Publicado por

Luiz Duarte

Pós-graduado em computação, professor, empreendedor, autor, Agile Coach e programador nas horas vagas.