Estou trabalhando em um projeto e depois de discutir com as pessoas no trabalho por mais de uma hora. Decidi saber o que as pessoas na troca de pilhas poderiam dizer.
Estamos escrevendo uma API para um sistema, há uma consulta que deve retornar uma árvore da organização ou uma árvore de objetivos.
A árvore da organização é a organização na qual o usuário está presente. Em outras palavras, essa árvore sempre deve existir. Na organização, uma árvore de objetivos deve estar sempre presente. (foi aí que o argumento começou). Caso a árvore não exista, meu colega de trabalho decidiu que seria correto responder a resposta com o código de status 200. E então comecei a me pedir para corrigir meu código porque o aplicativo estava desmoronando quando não havia árvore.
Vou tentar poupar chamas e fúria.
Sugeri gerar um erro 404 quando não há árvore. Pelo menos, me informaria que algo está errado. Ao usar o 200, tenho que adicionar uma verificação especial à minha resposta no retorno de chamada de sucesso para lidar com erros. Estou esperando receber um objeto, mas posso receber uma resposta vazia porque nada foi encontrado. Parece totalmente justo marcar a resposta como 404. E então a guerra começou e recebi a mensagem de que não entendia o esquema do código de status HTTP. Então, eu estou aqui e perguntando o que há de errado com 404 neste caso? Eu até entendi o argumento "Não encontrou nada, então é correto retornar 200". Eu acredito que está errado, pois a árvore deve estar sempre presente. Se não encontramos nada e esperamos algo, deve ser um 404.
Mais informações,
Esqueci de adicionar os URLs que foram buscados.
Organizações
/OrgTree/Get
Metas
/GoalTree/GetByDate?versionDate=...
/GoalTree/GetById?versionId=...
Meu erro, ambos os parâmetros são necessários. Se qualquer versionDate que puder ser analisada até uma data for fornecida, ela retornará a revisão de fechamento. Se você digitar algo no passado, ele retornará a primeira revisão. Se por ID com um ID que não existe, suspeito que ele retornará uma resposta vazia com 200.
Extra
Além disso, acredito que a melhor resposta para o problema é criar objetos padrão quando as organizações são criadas, não ter árvore não deve ser um caso válido e deve ser visto como um comportamento indefinido. Não há como uma conta ser usada sem as duas árvores. Por esse motivo, eles devem estar sempre presentes.
também eu liguei isso (um semelhante, mas não consigo encontrá-lo)
http://viswaug.files.wordpress.com/2008/11/http-headers-status1.png
fonte
/GoalTree/GetById?versionId=CompletelyInvalidID
retornar? Não foi bem-sucedido, pois o recurso chamado/GoalTree/GetById?versionId=CompletelyInvalidID
literalmente não foi encontrado.Respostas:
Em caso de dúvida, consulte a documentação . A revisão das definições do W3C para códigos de status HTTP nos fornece o seguinte:
No contexto da sua API, depende muito de como as consultas são criadas e como os objetos são recuperados. Mas, minha interpretação sempre foi a seguinte:
200
código de retorno , se ele não existir, retorne o404
código correto .200
código. A lógica para isso é que a consulta era válida, foi bem-sucedida e a consulta não retornou nada.Portanto, neste caso, você está correto , o serviço não está procurando por "uma coisa específica", está solicitando uma coisa em particular, se essa coisa não for encontrada, diga isso claramente.
Eu acho que a Wikipedia coloca da melhor maneira:
Parece muito claro para mim.
Em relação aos pedidos de exemplo
Para o formato, você disse, sempre retorne a revisão mais próxima a essa data. Ele nunca não retornará um objeto, portanto sempre deve retornar
200 OK
. Mesmo que isso pudesse levar um intervalo de datas, e a lógica seria retornar todos os objetos dentro desse prazo, retornando 200 resultados OK - 0 está ok, pois era para isso que era a solicitação - o conjunto de coisas que atendiam a esse critério.No entanto, o último é diferente, pois você está solicitando um objeto específico , presumivelmente único, com essa identidade. O retorno
200 OK
neste caso está errado, pois o recurso solicitado não existe e não foi encontrado .Sobre a escolha de códigos de status
Você mencionou em um comentário usando um código 5xx, mas seu sistema está funcionando. Foi solicitada uma consulta que não funciona e precisa comunicá-la ao UA. Não importa como você o corta, este é um território 4xx.
Considere um alienígena consultando nosso sistema solar
fonte
Ignorando o fato de que / GoalTree / Get * parece um verbo, não recursos, você sempre deve retornar 200 porque o URI / GoalTree / Get * representa recursos sempre disponíveis para acesso e não é erro do cliente se não houver uma árvore como resultado de um pedido. Apenas retorne 200 com o conjunto vazio quando não houver nenhuma entidade a ser retornada.
Você usa 404 se o recurso não for encontrado, não quando não houver entidade.
Em outras palavras, se você quiser retornar 404 para seus objetos, forneça a eles seus próprios URIs.
fonte
/GoalTree/GetById?versionId=12345
é um URI perfeitamente bom (bem, um relativo, pelo menos) que identifica um recurso específico, ou seja, os dados correspondentes ao ID da versão12345
no sistema. Se não houver dados com esse ID, uma resposta HTTP 404 é perfeitamente apropriada. Obviamente, o corpo da resposta deve, em qualquer caso, conter uma resposta formatada adequadamente (por exemplo, JSON, se é o que os clientes típicos que solicitam tais recursos esperam), indicando a natureza específica e a causa do erro.Essa é uma pergunta interessante, porque é tudo sobre as especificações do sistema.
A resposta de imel96 me convenceu que um 404 não seria uma resposta adequada, pois a família de códigos 4xx é principalmente para erros de usuário / cliente , e esse não é um deles. O URL está bem formado e a árvore deve estar lá; caso contrário, o sistema está em um estado inconsistente!
Portanto, este é um erro do servidor , ou seja, algo da família 5xx. Possivelmente um erro interno de servidor 500 genérico ou um serviço 503 indisponível (o serviço sendo "me traga a árvore que deve estar lá").
fonte
Eu diria que um código de resposta 200 ou 404 pode ser válido , dependendo de como você olha a situação.
O problema é que os códigos de resposta HTTP são definidos no contexto de um servidor , que pode fornecer vários recursos com base em sua URL. Nesse contexto, os significados de
200 OK
e404 Not Found
são perfeitamente inequívocos: o primeiro diz "aqui está o recurso que você solicitou", enquanto o segundo diz "desculpe, eu não tenho nenhum recurso como esse".No entanto, na sua situação, você tem uma camada de aplicativo adicional entre o servidor HTTP e os recursos reais (árvores) que estão sendo solicitados. O aplicativo ocupa uma espécie de espaço intermediário que não é bem endereçado na especificação HTTP.
Do ponto de vista do servidor, o aplicativo parece tipo de como um recurso: é tipicamente um arquivo no servidor, identificado por (uma parte do) o URL, assim como outros recursos (por exemplo, arquivos estáticos) o servidor pode servir. Por outro lado, é um tipo estranho de recurso, uma vez que consiste em código executável que determina dinamicamente o conteúdo e, de fato, potencialmente até o código de status da resposta, fazendo com que ele se comporte de certa forma mais como um miniservidor.
Em particular, no seu exemplo de exemplo, o servidor da Web pode localizar o aplicativo perfeitamente, mas o aplicativo falha ao localizar o sub-recurso (árvore) solicitado. Agora, se você considera o aplicativo apenas uma extensão do servidor e o subitem (árvore) é o recurso real, uma resposta 404 é apropriada: o servidor apenas delegou a tarefa de localizar o recurso real no aplicativo , que por sua vez não conseguiu.
Por outro lado, se seu ponto de vista é que o aplicativo é o recurso que está sendo solicitado, obviamente o servidor da web deve retornar uma resposta 200 ; afinal, o aplicativo foi encontrado e executado corretamente. Obviamente, nesse caso, o aplicativo deve realmente retornar um corpo de resposta válido no formato esperado, indicando (usando qualquer protocolo de nível superior que esse formato codifique) que nenhum dado real correspondente à consulta foi encontrado.
Ambos os pontos de vista podem fazer sentido. Na maioria dos casos , pelo menos para aplicativos destinados a serem acessados diretamente via HTTP com um navegador da Web comum, eu preferiria a visão anterior : o usuário geralmente não se importa com detalhes internos, como a diferença entre o servidor e o aplicativo, eles apenas se preocupam se os dados que eles querem estão lá ou não.
No entanto, no caso específico de um aplicativo projetado para se comunicar com outros programas de computador usando um protocolo API de alto nível personalizado, usando HTTP apenas como uma camada de transporte de baixo nível , há um argumento a ser adotado em favor dessa última visualização : Se os clientes fizerem interface com esse aplicativo, o que realmente interessa, no nível HTTP , é se eles conseguiram entrar em contato com o aplicativo ou não. Tudo o resto é, nesses casos, frequentemente comunicado de forma mais natural usando o protocolo de nível superior.
De qualquer forma, independentemente de qual das visualizações acima você preferir, há alguns detalhes que você deve ter em mente. Uma é que, em muitos casos, pode haver uma distinção significativa entre um recurso (essencialmente) vazio e um recurso inexistente .
No nível HTTP, um recurso vazio seria simplesmente indicado por um código de resposta 200 e um corpo de resposta vazio, enquanto um recurso inexistente seria indicado por uma resposta 404 e um corpo de recurso explicando a ausência do recurso. Em um protocolo API de nível superior, normalmente indica-se um recurso inexistente por uma resposta de erro, contendo um código / mensagem de erro específico do protocolo adequado, enquanto uma resposta vazia seria simplesmente uma estrutura de resposta normal sem itens de dados.
(Observe que um recurso não precisa ter literalmente zero bytes para ficar "vazio" no sentido que quero dizer acima. Por exemplo, um resultado de pesquisa sem itens correspondentes contaria como vazio no sentido amplo, assim como uma consulta SQL com sem linhas ou um documento XML que não contém dados reais.)
Além disso, é claro, se a aplicação realmente acredita que o subrecurso solicitado deve estar lá, mas não consegue encontrá-lo, em seguida, um terceiro código de resposta possível existir:
500 Internal Server Error
. Essa resposta faz sentido se a existência do recurso for uma condição prévia assumida para o aplicativo, de modo que sua ausência indique necessariamente um mau funcionamento interno.Por fim, você deve sempre ter em mente a lei de Postel :
Se o servidor deve responder em uma situação particular com um 200 ou uma resposta 404, isso não é desculpa você como o cliente implementador do manuseamento quer resposta adequada e na forma que maximiza a interoperabilidade robusta. Obviamente, o que significa manipulação "apropriada" em diferentes situações pode ser discutido, mas certamente não deveria normalmente incluir falhas ou "desmoronar".
fonte
Que tal um 204 sem conteúdo? Isso sugere que sua solicitação foi processada com êxito, mas não está retornando nada. Ainda é um "sucesso", mas permite que você veja se possui resultados apenas com base no código de status.
fonte
Se o URL representar um recurso que nunca existiu, retorne 404 Não encontrado
Se o URL representar um recurso que é uma lista vazia, retorne uma lista vazia e 200 OK.
Exemplo:
Se o URL representar um recurso que existia, retorne 410 Gone.
Sobre o diálogo de Lego Stormtrooper:
fonte
Pelo que parece, esta é uma API para uso interno . Isso dá a vantagem de usar qualquer esquema que traga mais benefícios , independentemente de ser manual ou não (especificação). Isso não significa inventar completamente seus próprios códigos de status, mas não há problema em 'torcer' as regras um pouco, se for benéfico.
Concordo com a sua posição de que você deve obter um código de status que mostre que algo deu errado. Afinal, é para isso que servem os códigos de status. Além disso, você obtém o benefício de bibliotecas que lançam exceções / etc. no código de status que não seja 200, para que você não precise verificar explicitamente (ou pode escrever seu próprio wrapper que faz isso).
Também concordo com o ponto de vista de Andres F. de que 500 é apropriado, pois a árvore deve existir. Na prática, eu gosto de dividir os erros do servidor em duas categorias. Algo inesperado deu errado e algo que eu posso praticamente verificar deu errado. Isso resulta nos seguintes códigos de status,
No seu caso particular, você pode verificar se a árvore existe ou não no lado do servidor e, se não estiver lá, retornar um 409. É um erro esperado (você sabe que isso pode acontecer, pode verificar, etc.) . Se o conflito é apenas minha preferência pessoal, um 5xx também pode ser apropriado desde que você possa se sentar e decidir isso com sua equipe.
A categorização de códigos como esse ajuda a identificar mais rapidamente o tipo de erro, mas pode trazer benefícios além da organização. Geralmente, com erros no site, você não deseja que o cliente obtenha erros inesperados, pois isso pode ser uma preocupação de segurança e revelar vulnerabilidades, e você retorna 500 genéricos "Ocorreu um erro". e registre o erro completo no servidor. Mas se um erro esperado ocorrer como um 409, você sabe que seria seguro mostrar o erro ao cliente e não precisa deixá-lo no escuro sobre o que aconteceu. Esse é apenas um uso prático que posso contar, mas há muitas possibilidades.
Isso é um pouco complicado porque você está postando isso por não conseguir concordar com seus colegas de trabalho, mas parece que vocês estão discutindo mais sobre semântica e quem é politicamente correto. Realmente não importa quem é mais adequado, desde que você possa criar um sistema que mais beneficie a empresa.
Por outro lado, se essa é uma API pública que segue as especificações o mais próximo possível, seria mais importante para evitar confusão entre a comunidade.
fonte
Tomando uma facada tangencial no seguinte: se um humano estiver usando a API (por meio de uma GUI), eu sugeriria que fizesse o que facilita a vida do usuário final. A inexistência da árvore quando deveria existir é um erro "Inconsistência do modelo de domínio". Um erro do sistema ocorre quando você fica sem memória ou apresenta alguma outra falha sistêmica. Portanto, retornar 5xx é inadequado. Como mencionado por várias pessoas acima, 4xx pode ser apropriado se a própria árvore tiver seu próprio URI, o que não é o caso aqui. Mas aqui está o que 404 diz ao cliente: você pode tentar novamente e novamente até obter algo em troca. Se você retornou 200, poderá retornar diagnósticos suficientes de volta ao usuário ou agente do usuário para que o agente do usuário possa exibir uma medição para que o usuário pare de tentar novamente e apenas contate o suporte. Por outro lado, se esta API for destinada apenas a sistemas,
fonte