Estou trabalhando com uma API REST que reside em um servidor que lida com dados de vários dispositivos IoT.
Minha tarefa é consultar o servidor usando a API para coletar informações de desempenho específicas sobre esses dispositivos.
Em uma instância, obtenho uma lista de dispositivos disponíveis e seus identificadores correspondentes e, posteriormente, consulte o servidor para obter mais detalhes usando esses identificadores (GUIDs).
O servidor está retornando um 500 Internal Server Error
para uma consulta em um desses IDs. No meu aplicativo, uma exceção é lançada e não vejo detalhes sobre o erro. Se eu examinar a resposta mais de perto com o Postman , posso ver que o servidor retornou JSON no corpo que contém:
errorMessage: "This ID does not exist"
.
Ignore o fato de que o servidor forneceu o ID para começar - esse é um problema separado para o desenvolvedor.
Uma API REST deve retornar a 500 Internal Server Error
para relatar que uma consulta faz referência a um objeto que não existe? Na minha opinião, os códigos de resposta HTTP devem se referir estritamente ao status da chamada REST, e não à mecânica interna da API. Eu esperaria um 200 OK
com a resposta contendo o erro e a descrição, que seriam proprietários da API em questão.
Ocorre-me que há uma diferença potencial de expectativa, dependendo de como a chamada REST está estruturada.
Considere estes exemplos:
http://example.com/restapi/deviceinfo?id=123
http://example.com/restapi/device/123/info
No primeiro caso, o ID do dispositivo é passado como uma variável GET. Um 404 ou 500 indica que o caminho ( /restapi/deviceinfo
) não foi encontrado ou resultou em um erro do servidor.
No segundo caso, o ID do dispositivo faz parte do URL. Eu entenderia melhor a 404 Not Found
, mas ainda assim poderia argumentar com base em quais partes do caminho são interpretadas como variáveis versus pontos finais.
fonte
Respostas:
Eu acho que uma resposta 404 é a melhor correspondência semântica aqui, porque o recurso que você estava tentando encontrar (representado pelo URI usado para a consulta) não foi encontrado. O retorno de uma carga útil de erro no corpo é razoável, mas não é obrigatório.
De acordo com a RFC 2616 , a definição do código de status 404 é:
fonte
/questions
, é/questions/368213
. Esse ponto de extremidade não existe no seu cenário. Pense da seguinte maneira: se você faz um GET on / foo / bar e não há bar, por que a resposta deve ser diferente se / foo existe ou não?How do you differentiate between a 404 meaning "the query returned no results" and a 404 meaning "the endpoint does not exist"?
- 400 Pedido inválido.Vou usar seus exemplos.
Se o nó de extremidade retornar uma matriz json , a melhor opção é
200 OK
com uma matriz vazia se nenhum resultado for encontrado.Se o terminal é projetado para retornar um único resultado , minha escolha seria
404 NOT FOUND
, pois, para mim, a sintaxe correta para este tipo de endpoint é:http://example.com/restapi/deviceinfo/123
. Eu normalmente uso o parâmetro de solicitação apenas para filtrar e quando meu ponto de extremidade retorna uma matriz.Eu acho que essa pergunta já foi respondida aqui . POST ou GET, a melhor opção parece
404 NOT FOUND
porque o recurso123
não foi encontrado.Nos dois casos, não vejo a necessidade de explicar o motivo da solicitação não ter sido concluída. As informações da solicitação e o código HTTP já explicam o porquê.
fonte
/itms/1234
ou não/items/12234
.HTTP 404
está correto, porque o servidor entende qual recurso o cliente está solicitando, mas não possui esse recurso.O fato de você estar trabalhando com uma "API REST" é a chave. A API deve se comportar como se estivesse executando uma transferência de estado REpresentational, não executando uma função. (Certamente, o termo "REST" passou a ter um significado mais amplo, mas ainda é possível usar seu significado literal aqui.) O cliente solicitou o estado de um recurso descrito pelo URL
http://example.com/restapi/device/123/info
. Uma querystring (/deviceinfo?id=123
) não mudaria a situação. O servidor sabe que você está solicitando a transferência do estado do dispositivo 123, mas não o reconhece como um recurso conhecido. Por issoHTTP 404
.As outras respostas possíveis discutidas aqui também têm significados específicos:
HTTP 200
- Temos o estado para você; está no corpo da resposta.HTTP 204
- Temos o estado para você; está em branco.HTTP 400
- Não podemos dizer sobre o recurso que você está perguntando. Corrija seu URL.HTTP 500
- Falhamos. Não é sua culpa.Veja RFC 2616 Sec. 10 conforme apropriado.
fonte
Um erro 5xx geralmente é usado para indicar que o servidor encontrou um erro e não pode concluir a solicitação. Se o servidor atender à solicitação, puder analisá-la com êxito e executar seu trabalho, isso não retornará um erro 5xx.
Não tenho certeza se existe algum tipo de convenção sobre o que retornar se uma consulta não produzir resultados. Eu vi tanto o que você descreve (um 200 com um corpo que contém uma mensagem) quanto um 404 indicando que os resultados não foram encontrados. O 200 provavelmente faz mais sentido - a solicitação foi concluída com êxito e não houve problemas com a solicitação do cliente ou durante o servidor processando a solicitação. Um corpo pode entregar uma mensagem ao cliente.
Eu trataria os dois exemplos (
http://example.com/restapi/deviceinfo?id=123
ehttp://example.com/restapi/device/123/info
) da mesma forma - o123
parâmetro é um. Ambos os casos são maneiras diferentes de estruturar uma solicitação para obter informações sobre um dispositivo com ID 123.Primeiro, eu consideraria a autorização e autenticação. Se o usuário não tiver as permissões apropriadas, eu retornaria um 403 ou um 401, conforme apropriado. Embora seja chamado de "Não autorizado", meu entendimento é que 401 é mais sobre autenticação e 403 é sobre não autorizado ou permissão negada. Eu não seria muito exigente aqui, no entanto, se você quisesse manter o 403 em todos os erros de autenticação e autorização.
Então, eu cuidaria da identificação. Com base no seu exemplo, parece que é um ID numérico. Se um valor não numérico fosse fornecido, eu retornaria um 400. Se o parâmetro pudesse ser um identificador de dispositivo válido, continuaria com o processamento. Se houvesse outros argumentos, eles também seriam verificados aqui. Eu esperaria que o corpo da resposta contivesse informações apropriadas sobre por que a solicitação foi ruim.
Se todos os parâmetros fossem válidos, eu começaria a processar a solicitação. Se o sistema ou qualquer dependência (um banco de dados, um serviço de terceiros, outro serviço interno) estiver indisponível, eu retornaria um código 5xx - 503 seria específico, mas 500 também seriam aceitáveis. Nos dois casos, eu retornaria um corpo com detalhes adicionais. Considere que, se uma dependência externa relatar um tempo limite de solicitação 408, eu comeria isso e retornaria 500 para o meu cliente, permitindo que um cliente recebesse um 408 somente se a solicitação para o meu sistema expirar. Se o sistema puder concluir a solicitação, eu retornaria 200 e o corpo apropriado.
204 pode ser útil em alguns casos, mas impede o envio de um corpo de resposta. Especialmente em uma configuração de API, enviar um corpo de resposta com informações que podem ser alimentadas em um mecanismo de registro ou relatório parece ser a decisão certa a ser tomada na maioria dos casos.
A única vez que um 404 seria retornado é se o servidor não tivesse um
/deviceinfo
terminal ou um/device/:id/info
terminal.Eu não consideraria um ID que não seja o mesmo que o recurso não encontrado. O recurso são as informações do dispositivo para um dispositivo específico (no seu exemplo). Retornar um 404 significaria que o recurso (as informações do dispositivo) não existe. Um 200 com um corpo apropriado significa que o sistema pode realmente fornecer informações sobre o dispositivo. Pode ou não haver um dispositivo com o ID especificado.
fonte
device: 123; status: not found;
. Então eu sei que a consulta funcionou e que a API está me informando informações úteis.Um erro HTTP da série 500 indica um mau funcionamento do servidor. Além de
501 Not Implemented
e505 HTTP Version Not Supported
, o uso desses códigos de erro implica que a tentativa de repetir a solicitação posteriormente poderá ser bem-sucedida (embora apenas o503 Service Unavailable
exponha explicitamente). Idealmente, um servidor nunca deve produzir um desses códigos, embora a incapacidade de escrever software livre de erros e fornecer ao servidor recursos infinitos signifique que você precisará deles de tempos em tempos.Para um resultado "objeto não existe", você provavelmente deve retornar
404 Not Found
(quando a solicitação é um objeto por nome) ou200 Success
com um corpo de resultado vazio (ao procurar um objeto por atributos).204 No Content
parece tentador, mas eu o usaria apenas para situações em que a falta de um corpo de resposta é o resultado esperado.fonte
Como cliente da sua API, quando faço uma dessas chamadas:
http://example.com/restapi/deviceinfo?id=123
http://example.com/restapi/device/123/info
Espero recuperar um (representação de) um
DeviceInfo
objeto (ou algum tipo específico de qualquer maneira, seja um tipo formal ou apenas algo conforme uma convenção "tipo de pato" documentada). Quero que um200
status signifique que realmente tenho um, e posso usá-lo.Para APIs REST, penso em códigos de status 400 e 500 como algo como exceções. Você os usa para indicar quando não pode retornar uma resposta "normal" para a solicitação que recebeu, portanto o cliente precisará fazer algo excepcional em vez de processar as informações que esperava recuperar.
Isso significa, como consumidor da API, que eu posso usar algum tipo de função de chamada de descanso verificado que recupera uma resposta ou gera uma exceção. Isso é ótimo; minha lógica normal pode ser um código de linha reta e posso organizar meu tratamento de erros da mesma maneira que faço no código local. 404s inesperados se manifestarão como exceções "nenhum recurso encontrado" sem que eu precise fazer nada, e não como erros de "atributo ausente" quando mais tarde eu processarmos
{ errorMessage: "Device 123 not found" }
como se fosse umDeviceInfo
objeto.Se você considerar que o terminal
http://example.com/restapi/deviceinfo
foi encontrado e não for o únicoid=123
, e retornar 200 com uma mensagem de erro no corpo, estará criando exatamente o mesmo tipo de problemas de interface que as funções C que poderiam retornar um resultado correto ou um código de erro ou métodos que indicam problemas retornando arbitrariamentenull
. É muito melhor, como usuário da sua interface, indicar erros através de um canal "separado" dos retornos regulares. Isso se aplica aqui também, mesmo que as respostas HTTP 200, 404 e 500 sejam o mesmo canal do ponto de vista de baixo nível. Eles são padronizados e fáceis de distinguir para que minha estrutura de cliente REST possa alternar facilmente esses status para transformá-los nas estruturas apropriadas no meu idioma; para fazer a mesma coisa com a camada JSON (onde você sempre diz 200 e me dá umaDeviceInfo
ou uma mensagem de erro), preciso incorporar algum conhecimento dos esquemas JSON usados.Portanto, use apenas 200 quando você puder retornar um valor válido do tipo esperado (é por isso que
http://example.com/restapi/search-devices?colour=blue
pode retornar 200 com uma matriz vazia se não houver dispositivos azuis; uma matriz vazia é uma matriz válida e uma resposta sensata à solicitação "I gostaria dos detalhes de todos os dispositivos azuis "). Se não puder, use o código de status não-200 mais apropriado. Mesmo que "o dispositivo 123 não exista" seja a resposta correta para "forneça os detalhes do dispositivo 123" e não seja um erro para o servidor , é uma exceção à expectativa do cliente de que ele retornaráDeviceInfo
e deve não seja comunicado como uma resposta normal "aqui está o que você pediu".fonte
Você poderia usar o erro 422 Unprocessable Entity para diferenciar de 404 não encontrado . 422 significa que o servidor entende a solicitação, mas não pode dar uma resposta adequada. Estou usando esse código em situações semelhantes.
fonte
O erro 500 normalmente indica que a solicitação travou um programa do lado do servidor; em ambientes corporativos, esses erros são tratados como um ovo na cara e estão sendo evitados.
O erro 4xx deve sinalizar ao programador que o ponto de extremidade da API (recurso) não existe. Consequentemente, uma vez atingido o ponto de extremidade apropriado, qualquer tratamento de erro a partir desse ponto é de responsabilidade do programador da API que deve ser tratado normalmente, ou seja, com uma mensagem de erro de 200 respostas.
fonte
Embora o w3 observe que 404 é usado quando nenhuma outra resposta é aplicável , não seria para isso que uma resposta 204 (Sem conteúdo) é adequada? A solicitação era válida do ponto de vista de processamento e o servidor processou a solicitação e tem um resultado. Esse é um sucesso, que se inclina para respostas 2xx. Como não havia conteúdo para essa solicitação específica, o 204 informa ao usuário que não havia nada errado com a consulta, mas não havia nada lá.
Você também pode argumentar que 409 (Conflito) é uma resposta apropriada. Embora 409 seja usado com mais frequência para um POST, ele diz
indiscutivelmente, a inexistência do ID solicitado é o conflito aqui, e retornar na mensagem que esse ID não existe no sistema é informação suficiente para o usuário reconhecer e corrigir o conflito.
fonte
As outras respostas cobrem isso, mas eu só queria ressaltar que um erro da série 500 significa "eu errei". Nesse caso, "I" significa a API, portanto, um erro de servidor não tratado ou semelhante. Um erro da série 400 significa "você errou" - o chamador da API enviou algo incorreto.
fonte
Outros usuários forneceram respostas válidas para o que fazer se você quiser seguir as instruções.
No entanto, eu sugiro que você esteja lendo muito sobre o RESTfulness e sendo absolutamente respeitoso com relação a ele.
REST é um protocolo caprichoso, porque se você deseja seguir o livro enquanto o usa, força o cliente e o servidor a serem construídos com conhecimento específico do fato de que estão se comunicando via REST, portanto, em essência, o protocolo de comunicação específico usado não pode ser abstraído.
Há uma abordagem diferente: evite completamente o RESTfulness e use-o apenas como um protocolo de comunicação e nada mais. Isso significa que as únicas respostas que precisam ser retornadas são "HTTP 200 OK" e "Erro interno do servidor HTTP 500" porque, no que diz respeito ao protocolo de comunicação, qualquer tentativa de comunicação pode ter apenas dois resultados: a solicitação foi bem-sucedida entregue ao servidor ou não.
O que acontece após a entrega não é da conta do protocolo de comunicação. Portanto, uma vez que o servidor tenha recebido a solicitação com êxito e comece a processá-la, muitos erros poderão ocorrer, mas esses são todos erros específicos do aplicativo que não são da conta do protocolo de comunicação nada. Eles devem ser comunicados dentro da carga de uma resposta que pareça perfeitamente bem-sucedida, tanto quanto o protocolo de comunicação sabe.
Portanto, eu recomendo retornar um "HTTP 200 OK" e, dentro da carga útil da resposta ("corpo do conteúdo da resposta" na linguagem HTTP), tenha um código de erro específico do aplicativo que diga "ID não encontrado" ou qualquer outra coisa.
fonte