Devo usar códigos de status HTTP para descrever eventos no nível do aplicativo


54

Vários servidores com os quais eu lidei retornam o HTTP 200 para solicitações que o cliente deve considerar uma falha, com algo como 'success: false' no corpo.

Isso não parece uma implementação adequada de códigos HTTP para mim, principalmente em casos de falha na autenticação. Li os códigos de erro HTTP resumidos de maneira bem sucinta, como '4xx' indica que a solicitação não deve ser feita novamente até ser alterada, enquanto '5xx' indica que a solicitação pode ou não ser válida e pode ser tentada novamente, mas não teve êxito. Nesse caso, 200: login falhou ou 200: não foi possível encontrar esse arquivo ou 200: faltando o parâmetro x, definitivamente parece errado.

Por outro lado, pude ver o argumento de que '4xx' deve indicar apenas um problema estrutural com a solicitação. Portanto, é adequado retornar 200: usuário / senha incorretos, em vez de 401, não autorizados, porque o cliente pode fazer a solicitação, mas isso está incorreto. Esse argumento pode ser resumido como, se o servidor pudesse processar a solicitação e fazer uma determinação, o código de resposta deveria ser 200 e cabe ao cliente verificar o corpo para obter mais informações.

Basicamente, isso parece ser uma questão de preferência. Mas isso é insatisfatório; portanto, se alguém tiver uma razão para que um desses paradigmas seja mais correto, eu gostaria de saber.


9
success: falseimplica que a solicitação falhou e você a conhece. Isso deve ser um 500. Algo como seu nome de usuário / senha incorreto seria um 401. Isso não é tão ambíguo.
Pete


4
Essa é uma daquelas perguntas que podem invocar guerras religiosas, eu acho. Para uma API RESTful, a resposta é clara, mas existem outros tipos de APIs em que o HTTP é tratado apenas como uma camada de transporte e, nesses casos, os erros do aplicativo não devem sangrar nessa camada.
Gort the Robot

5
Quando não tenho certeza do status do http a retornar, é sempre tentador escolher 418 "Sou um bule de chá".
joshp

11
Um exemplo é várias solicitações e respostas (em lote) . Lote não é algo repousante; mas as preocupações práticas de eficiência geralmente exigem algum suporte para agrupar questões de elegância.
Rwong

Respostas:


35

Pergunta interessante.

Basicamente, podemos reduzir isso da maneira correta para classificar as coisas em termos análogos às camadas OSI. O HTTP é geralmente definido como um protocolo no nível do aplicativo e o HTTP é realmente um protocolo genérico de cliente / servidor.

No entanto, na prática, o servidor é quase sempre um dispositivo de retransmissão, e o cliente é um navegador da web, responsável pela interpretação e renderização do conteúdo: o servidor apenas repassa as coisas para um aplicativo arbitrário e esse aplicativo envia scripts arbitrários que o navegador é responsável pela execução. A própria interação HTTP - os formulários de solicitação / resposta, códigos de status e assim por diante - é principalmente uma questão de como solicitar, servir e renderizar conteúdo arbitrário da maneira mais eficiente possível, sem atrapalhar. Muitos dos códigos e cabeçalhos de status foram projetados para esses fins.

O problema ao tentar pegar o protocolo HTTP para lidar com fluxos específicos de aplicativos é que você tem uma das duas opções: 1) Você deve tornar sua lógica de solicitação / resposta um subconjunto das regras HTTP; ou 2) Você deve reutilizar certas regras e a separação de preocupações tende a ficar confusa. Isso pode parecer agradável e limpo no começo, mas acho que é uma daquelas decisões de design das quais você acaba se arrependendo à medida que seu projeto evolui.

Portanto, eu diria que é melhor ser explícito sobre a separação de protocolos. Deixe o servidor HTTP e o navegador da Web fazerem suas próprias coisas e deixe o aplicativo fazer suas próprias coisas. O aplicativo precisa poder fazer solicitações e precisa das respostas - e sua lógica de como solicitar, de como interpretar as respostas, pode ser mais (ou menos) complexa do que a perspectiva HTTP.

O outro benefício dessa abordagem, que vale a pena mencionar, é que os aplicativos, em geral, não devem depender de um protocolo de transporte subjacente (do ponto de vista lógico). O próprio HTTP mudou no passado, e agora temos o HTTP 2 entrando, seguindo o SPDY. Se você visualizar seu aplicativo como não mais que um plug-in de funcionalidade HTTP, poderá ficar parado quando novas infraestruturas assumirem o controle.


8
Muito perspicaz. O argumento mais forte aqui é a incompatibilidade (impedância) entre os códigos de status HTTP e os valores de retorno do seu aplicativo. Isso pode se tornar um pesadelo a longo prazo. Além disso, eu apoio fortemente a separação de preocupações entre o transporte (HTTP) e a carga útil (dados do aplicativo). Se você digitar incorretamente a URL de um terminal em serviço, obterá um 404. Se você solicitar um item inexistente ao serviço, receberá uma mensagem específica do aplicativo (talvez com informações adicionais que você possa usar para resolver o problema).

2
Se você digitar incorretamente o URL, poderá nem acabar no servidor certo e, então, tudo poderá acontecer.
gnasher729

Este é um visual bem matizado. Acho que a questão do HTTP se tornar uma camada de pseudo-transporte é o verdadeiro problema de se fazer uma determinação. Na maioria das vezes, eu mesmo me deparo com essa pergunta quando você tem um servidor nginx ou apache proxy de um servidor nodejs, em que o proxy já possui regras para o envio desses códigos, e a pergunta passa a ser se é apropriado que o back-end esteja em conformidade com o padrão. Em alguns desses casos, pode haver um motivo de design para não enviar um código de erro, pois o nginx pode interpretá-lo como 'back-end'.
Kagan Mattson

4
Concordo. Não há nada errado com um erro da camada de aplicativo sendo relatado em uma resposta HTTP 200. O 200 indica que a própria solicitação / resposta HTTP foi bem-sucedida, sem dizer nada sobre o conteúdo ou a semântica da camada de aplicativo sendo invocada no momento.
Lightness Races com Monica

22

Esta questão é um pouco baseada em opiniões, mas de qualquer maneira.

Do meu ponto de vista, 200 podem servir como "erros leves". Quando se trata de criar APIs, tento distinguir entre esses e os "erros graves".

"Erros leves" serão exibidos com um código de status 200, mas conterão uma descrição do erro e um status de sucesso de false. "Erros leves" ocorrerão apenas quando o resultado for "conforme o esperado", mas não será um sucesso no sentido mais estrito.

É importante observar que "erros leves" são mais uma dica para o implementador. Portanto, é importante também fornecer mais informações sobre o erro, como uma mensagem de erro legível por humanos e / ou algum tipo de código que pode ser usado para fornecer feedback ao usuário final. Esses erros fornecem ao implementador (e ao usuário final) mais informações sobre o que aconteceu no lado do servidor .

Por exemplo, digamos que você tenha uma API com uma função de pesquisa, mas durante uma pesquisa, nenhum resultado será gerado. Isso não é errado, mas também não é um "sucesso", nem no sentido mais estrito da definição.

Exemplo formatado como JSON:

{
    "meta" {
        "success": false,
        "message": "Search yielded no results",
        "code": "NORESULTS"
    }
    "data": []
}

"Erros graves", por outro lado, serão exibidos com um código de status recomendado para o erro. O usuário não está logado? - 403 / 401. Entrada malformada? - 400. Erro no servidor? - 50X. E assim por diante.

Novamente, é um pouco baseado em opiniões. Algumas pessoas querem tratar todos os erros igualmente, "erro grave" em tudo. Nenhum resultado de pesquisa? Isso é um 404! Do outro lado da moeda, nenhum resultado de pesquisa? - Isso é como esperado, sem erros.

Outro fator importante a ser levado em consideração é sua arquitetura, por exemplo; se você interagir com sua API usando solicitações JavaScript XHR e jQuery ou AngularJS. Esses "erros graves" terão que ser tratados com um retorno de chamada separado, enquanto os "erros leves" podem ser tratados com o retorno "success". Não quebrando nada, o resultado ainda é "como esperado". O código do lado do cliente pode examinar o status de sucesso e o código (ou mensagem). E imprima isso para o usuário final.


2
Na verdade, classificar isso como um erro no nível da API é uma decisão curiosa. Mesmo que o cliente possa, a seu critério, classificá-lo como inesperado no nível do usuário.
Deduplicator

11
Há muitas coisas que precisam ser levadas em consideração. Tudo depende da implementação da API. Também, novamente, um pouco com base em opiniões e também no que a API define como "sucesso" e / ou "erro". O "success": falsesinalizador-é mais uma dica para o implementador de que algo está acontecendo . Normalmente, ele deve incluir um código de status interno . Um "code": "NORESULTS"ou um código numérico - qualquer que seja o criador da API. Está principalmente lá, para quem implementa a API pode deduzir informações sobre o que aconteceu no servidor.
die maus

15

Existem dois aspectos de uma API: o esforço para implementar a API e o esforço de todos os clientes para usar a API corretamente.

Como autor do cliente, eu sei que, quando envio uma solicitação para um servidor Web, posso receber um erro (nunca falei adequadamente com o servidor) ou uma resposta com um código de status. Eu tenho que lidar com os erros. Eu tenho que lidar com uma boa resposta. Eu tenho que lidar com respostas esperadas, documentadas e "ruins". Eu tenho que lidar com o que mais voltar.

Ao projetar a API, você deve analisar o que é mais fácil para o cliente processar. Se o cliente enviar uma solicitação bem-formada e você puder fazer o que a solicitação solicita, deverá responder no intervalo 200 (há alguns casos em que um número diferente de 200 nesse intervalo é apropriado).

Se o cliente solicitar "forneça todos os registros como ..." e houver zero, um 200 com êxito e uma matriz de zero registros serão totalmente adequados. Os casos que você menciona:

"Falha no login" geralmente deve ser um 401. "Não foi possível encontrar o arquivo" deve ser um 404. "Parâmetro ausente x" deve ser algo em torno de 500 (na verdade, 400 se o servidor descobrir que a solicitação está incorreta e 500 se o servidor estiver totalmente confuso com minha solicitação e não tiver ideia do que está acontecendo). Retornar 200 nesses casos é inútil. Apenas significa que, como autor de um cliente, não posso apenas olhar o código de status, tenho que estudar a resposta também. Não posso simplesmente dizer "status 200, ótimo, aqui estão os dados".

Especialmente o "parâmetro em falta" - isso não é algo que eu jamais iria lidar . Isso significa que minha solicitação está incorreta. Se minha solicitação estiver incorreta, não tenho um substituto para corrigir essa solicitação incorreta - enviaria uma solicitação correta para começar. Agora sou forçado a lidar com isso. Eu recebo um 200 e tenho que verificar se há uma resposta "parâmetro ausente". Isso é horrível.

No final, existem uma dúzia ou dois códigos de status para lidar com muitas situações diferentes, e você deve usá-los.


3
Ao conectar-me a uma API, eu pessoalmente prefiro obter 200 em um 'arquivo não encontrado' ao conectar-me a um endpoint válido, pois meu tratamento HTTP não precisa sangrar na camada que lida com a API.
Whatsisname

4
"O parâmetro x ausente" deve ser 400 BAD_REQUEST porque é o cliente que está fazendo algo errado. 500 INTERNAL_SERVER_ERROR deve ser reservado para casos em que o servidor está fazendo a coisa errada. Um 500 implica que o cliente poderá tentar novamente. Um 400 implica que alguém deve consertar o cliente.
Gort the Robot

11
Se você estiver escrevendo uma interface RESTful, o URL identifica um objeto específico e, portanto, um 404 é apropriado. Conceitualmente, o mesmo /customers/premium/johndoe.jsonse refere a um cliente que não está no banco de dados e se /files/morefiles/customers.htmlrefere a uma página que não está no sistema de arquivos.
Gort the Robot

@whatsisname O que você está dizendo faz sentido, porque não está claro se o ponto de extremidade está ruim ou se o recurso não existe. Você também pode argumentar que, independentemente de o ponto de extremidade ser válido ou não, nenhum recurso existe nesse endereço, portanto, a 404está correto nos dois casos.
Pete

2
Uma coisa que eu não vi mencionado é que, quando você coloca os erros do aplicativo nos códigos de status HTTP, pode perder informações. Se o aplicativo retornar apenas um 404 e nada mais, você não saberá se foi porque sua API retornou um 404 ou porque o servidor não conseguiu encontrar o arquivo. Isso pode adicionar uma etapa extra à sua depuração.
AmadeusDrZaius
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.