Qual é o código de resposta REST adequado para uma solicitação válida, exceto dados vazios?

332

Por exemplo, você executa uma solicitação GET, users/9mas não há usuário com o ID nº 9. Qual é o melhor código de resposta?

  • 200 OK
  • 202 Aceito
  • 204 Sem Conteúdo
  • 400 Solicitação incorreta
  • 404 não encontrado
EU SOU B
fonte
19
Dica: você encontrou o usuário 9?
31712 Chris Pfohl
42
Dica 2: Então o usuário 9 não foi encontrado ?
Tomasz Nurkiewicz
18
@IMB quem está dizendo 204? "Sem conteúdo" indica que a entidade que você está procurando existe, mas não tem representação. Por exemplo, se o blog com o ID 15 não tiver comentários e você não desejar retornar uma lista vazia para os comentários do número 15 do blog: "/ blog / 15 / comments" retornaria NoContent. Por outro lado, se o blog 15 existir, '404 não encontrado' é mais apropriado.
Chris Pfohl
12
@Crisfole você não quis dizer ". Por outro lado, se o blog 15 não existir, '404 Not Found' é mais apropriado"
gdoron está apoiando Monica
15
Eu certamente fiz @gdoron! :) Obrigado. Infelizmente, estou aproximadamente três anos atrasado para editar e corrigir.
precisa

Respostas:

249

TL; DR: uso 404

Veja este blog . Isso explica muito bem.

Resumo dos comentários do blog em 204 :

  1. 204 No Content não é muito útil como código de resposta para um navegador (embora, de acordo com as especificações HTTP, os navegadores precisem entendê-lo como um código de resposta 'não mude a exibição').
  2. 204 No Content é , no entanto, muito útil para serviços da web ajax, que podem indicar sucesso sem precisar retornar algo. (Especialmente em casos como DELETEouPOST s que não requerem o feedback).

A resposta, portanto, à sua pergunta é usada 404no seu caso. 204é um código de resposta especializado que você geralmente não deve retornar a um navegador em resposta a umGET .

Os outros códigos de resposta que são ainda menos adequados que 204e 404:

  1. 200deve ser devolvido com o corpo do que você buscou com sucesso. Não é apropriado quando a entidade que você está buscando não existe.
  2. 202é usado quando o servidor começa a trabalhar em um objeto, mas o objeto ainda não está totalmente pronto. Certamente não é o caso aqui. Você não iniciou, nem começará a construção do usuário 9 em resposta a umaGET solicitação. Isso quebra todos os tipos de regras.
  3. 400é usado em resposta a uma solicitação HTTP mal formatada (por exemplo, cabeçalhos http malformados, segmentos ordenados incorretamente etc.). Isso quase certamente será tratado por qualquer estrutura que você esteja usando. Você não deveria ter que lidar com isso, a menos que esteja escrevendo seu próprio servidor do zero. Editar : RFCs mais recentes agora permitem que 400 sejam usados ​​para solicitações semanticamente inválidas.

A descrição dos códigos de status HTTP da Wikipedia é particularmente útil. Você também pode ver as definições no documento HTTP / 1.1 RFC2616 em www.w3.org

Chris Pfohl
fonte
8
Nota: os códigos de resposta nos anos 200 indicam sucesso. Os códigos de resposta nos 400s indicam falha. O resumo, pontos um e dois, é sobre o 204código de resposta (sem conteúdo).
22612 Chris Pfohl
227
-1, pois me oponho fortemente a 404 como resposta a uma chamada bem - sucedida que não possui registros a serem retornados. Como desenvolvedor que lida com uma API para um aplicativo que não é da Web, perdi horas entrando em contato com os desenvolvedores da API para rastrear por que o ponto de extremidade da API que eu estava chamando não existia, quando na verdade existia, simplesmente não tinha dados a relatar. Com relação ao fato de um 204 não ser particularmente útil para um navegador, é um pouco como a cauda que abana o cachorro, já que a maioria dos pontos de extremidade da API em nosso universo de dispositivos inteligentes não é baseada em navegador e aqueles que provavelmente usam o AJAX. Desculpe tirar pontos embora.
Matt Cashatt 16/09/16
38
@MatthewPatrickCashatt você está livre para votar como quiser. Agora finalmente entendo por que as pessoas estão votando contra mim, mas a lógica ainda está errada. Ao receber um 404, isso não significa que a rota não faz sentido, significa que não há recurso nesse local. Ponto final. Isso é verdade se você estiver solicitando /badurlou /user/9quando esse usuário não existir. Um desenvolvedor pode ajudar adicionando uma frase de motivo melhor que 'Não encontrado', mas não é necessário.
217166 Chris Pfohl #
19
@Crisfole Estou inclinado a discordar (embora não tenha voto negativo, continue lendo), baseado na definição W3 de 404 , especificamente The server has not found anything matching the Request-URI. De fato, o servidor da Web / aplicativo encontrou uma AÇÃO correspondente ao URI da solicitação, embora o servidor db não tenha encontrado. No entanto, também diz This status code is commonly used when [...] no other response is applicable, então acho que valida um pouco o seu uso (mesmo que eu não concorde com / goste).
Daevin
8
Não acho que você esteja abordando o argumento que estou afirmando: um 404 é perigosamente confuso. Confiar em um chamador verificando uma frase de razão ou o corpo da resposta significa que você não está confiando no código de status; nesse caso, não é útil.
Adrian Baker
364

Oponho-me fortemente a 404 a favor de 204 ou 200 com dados vazios. Ou pelo menos um deve usar uma entidade de resposta com o 404.

A solicitação foi recebida e processada adequadamente - ela acionou o código do aplicativo no servidor, portanto, não se pode realmente dizer que foi um erro do cliente e, portanto, toda a classe de códigos de erro do cliente (4xx) não é adequada.

Mais importante, o 404 pode acontecer por vários motivos técnicos. Por exemplo, o aplicativo sendo temporariamente desativado ou desinstalado no servidor, problemas de conexão de proxy e outros enfeites. Portanto, o cliente não pode distinguir entre um 404 que significa "conjunto de resultados vazio" e um 404 que significa "o serviço não pode ser encontrado, tente novamente mais tarde".

Isso pode ser fatal: imagine um serviço de contabilidade em sua empresa que lista todos os funcionários que recebem um bônus anual. Infelizmente, a única vez em que é chamada retorna um 404. Isso significa que ninguém recebe um bônus ou que o aplicativo está atualmente inativo para uma nova implantação?

-> Para aplicativos que se preocupam com a qualidade de seus dados, o 404 sem entidade de resposta é, portanto, praticamente inútil.

Além disso, muitas estruturas de clientes respondem a um 404 lançando uma exceção sem mais perguntas. Isso força o desenvolvedor do cliente a capturar essa exceção, avaliá-la e decidir com base nisso se deve registrá-la como um erro detectado por, por exemplo, um componente de monitoramento ou se deve ignorá-la. Isso também não parece bonito para mim.

A vantagem de 404 sobre 204 é que ele pode retornar uma entidade de resposta que pode conter algumas informações sobre o motivo pelo qual o recurso solicitado não foi encontrado. Mas, se isso realmente for relevante, pode-se considerar o uso de uma resposta 200 OK e projetar o sistema de maneira a permitir respostas de erro nos dados da carga útil. Como alternativa, pode-se usar a carga útil da resposta 404 para retornar informações estruturadas ao chamador. Se ele recebe, por exemplo, uma página html em vez de XML ou JSON que ele pode analisar, é um bom indicador de que algo técnico deu errado em vez de uma resposta "sem resultado" que pode ser válida do ponto de vista do chamador. Ou pode-se usar um cabeçalho de resposta HTTP para isso.

Ainda assim, eu preferiria um 204 ou 200 com resposta vazia. Dessa forma, o status da execução técnica da solicitação é separado do resultado lógico da solicitação. 2xx significa "execução técnica ok, este é o resultado, lide com isso".

Penso que, na maioria dos casos, deve ser deixado ao cliente decidir se um resultado vazio é aceitável ou não. Ao retornar 404 sem entidade de resposta, apesar de uma execução técnica correta, o cliente pode decidir considerar os casos como erros que simplesmente não são erros.

Outra analogia rápida: retornar 404 para "nenhum resultado encontrado" é como lançar um DatabaseConnectionException se uma consulta SQL não retornar resultados. Ele pode fazer o trabalho, mas há muitas causas técnicas possíveis que lançam a mesma exceção, que seriam confundidas com um resultado válido.

Jens Wurm
fonte
30
Os motivos técnicos para um 'não encontrado' também são conhecidos como erros do servidor. Aqueles devem estar na década de 500. Especificamente: "O serviço não pode ser encontrado" é 503 Service Unavailable.
precisa saber é o seguinte
43
O solicitante também estava perguntando sobre um recurso específico: um único usuário (não a /usersrota, mas /users/9, por exemplo, "O usuário conhecido como # 9"), para que a comparação do 'conjunto de resultados vazio' não faça sentido. 404 significa que o objeto não existe.
precisa saber é o seguinte
29
404 indica simplesmente que o recurso solicitado (nesse caso, o usuário número 9) não foi encontrado. Não tem nada a ver com o fato de o código do aplicativo ter sido disparado ou não, não tem nada a ver com a resposta ou não de um aplicativo de back-end. Um servidor da web é o assunto da pergunta, não houve menção de proxy reverso na pergunta.
precisa
29
O raciocínio nesta resposta é terrivelmente errado.
Kurt Spindler
21
404: o cliente conseguiu se comunicar com um determinado servidor, mas o servidor não pôde encontrar o que foi solicitado. Literalmente, que: pedido recebido, foi bem e formatado corretamente (pedido ruim 400), foi autenticado ou público (401 / proibido 403 não autorizado), nenhum pagamento necessário (pagamento exigido 402), o método de pedido foi bom (método não permitido 405 ), a solicitação de aceitação pode ser atendida (não aceitável 406). 200 Ok deve ser usado quando o usuário obtém o recurso. Vazio não é um recurso. Intervalo 400 é para erros do cliente intervalo 500 é para erros do servidor Resumindo: seu raciocínio está desativado.
Derk-Jan
62

No começo, pensei que um 204 faria sentido, mas após as discussões, acredito que 404 é a única resposta correta verdadeira. Considere os seguintes dados:

Usuários: John, Peter

METHOD  URL                      STATUS  RESPONSE
GET     /users                   200     [John, Peter]
GET     /users/john              200     John
GET     /users/kyle              404     Not found
GET     /users?name=kyle`        200     []
DELETE  /users/john              204     No Content

Alguns antecedentes:

  1. a pesquisa retorna uma matriz, mas não possui correspondências, mas tem conteúdo: uma matriz vazia .

  2. Naturalmente, 404 é mais conhecido por URLs que não são suportados pelo servidor solicitado, mas um recurso ausente é o mesmo.
    Mesmo /users/:namecombinando com users/kyle, o usuário Kyle não está disponível, portanto um 404 ainda se aplica. Não é uma consulta de pesquisa, é uma referência direta por um URL dinâmico , portanto 404.

Enfim, meus dois centavos :)

Justus Romijn
fonte
9
Jogando meu peso por trás desse estilo para uma API REST. Nenhum cliente deve pedir / usuários / Kyle, a menos que foi dito que recursos existiria através de uma chamada para ou / usuários e / ou usuários name = Kyle?
Gary Barker
@ GaryBarker Mas, como essa é a "entrada do usuário" de alguma forma, a API ainda precisa lidar com isso corretamente. Embora você deva impedir o 404 no SEU cliente, não é possível garantir que ele realmente foi verificado em primeiro lugar. O design da API deve ser feito sem considerar a implementação exata do seu cliente, especialmente em termos de entrada verificada do usuário.
precisa saber é o seguinte
Esta é a resposta que eu mais concordo. Exemplo perfeito de como eu quero que as APIs funcionem. O comentário de @ GaryBarker também é perfeito. É um erro quando você pesquisa algo por ID e ele não existe. Você deve saber que o ID existe antes de fazer a chamada. Principalmente porque obter uma resposta vazia 'bem-sucedida' apenas retrocede o erro mais adiante, provavelmente para alguns 'não é possível ler o nome da propriedade indefinido' ao executar user.name ou algo assim.
Jamie Twells
Que tal uma combinação dos dois. Supondo que os usuários tenham amigos. / users / kyle / friends? name = fred. Kyle não existe, então essa resposta seria 404? Ou seriam 200 porque não nos importamos exatamente com Kyle, apenas nos preocupamos em procurar seus amigos com o nome fred?
precisa saber é o seguinte
OMI que produziria um 404, pois é um pedido inválido: Kyle não existe, portanto, também não é possível procurar seus amigos.
Justus Romijn
23

Se é esperado que o recurso exista, mas possa estar vazio, eu diria que talvez seja mais fácil obter um OK 200 com uma representação que indique que o item está vazio.

Então, eu preferiria que as coisas retornassem 200 OK com {"Items": []} do que 204 com nada, porque dessa maneira uma coleção com 0 itens pode ser tratada da mesma forma que uma coleção com um ou mais itens. mais item nele.

Gostaria apenas de deixar o 204 No Content for PUTs e DELETEs, onde pode ser o caso de realmente não haver representação útil.

No caso de / coisa / 9 realmente não existir, um 404 é apropriado.

j0057
fonte
1
Parece que você prefere programar em uma API usando um formulário mais abstrato chamado RPC. Em vez de acessar recursos, seguindo de perto os verbos e um URL baseado em recursos, como customers/1/addressbook, a maneira RPC é chamar um ponto de extremidade como GetCustomerAddressBooke receber os dados ou essencialmente nulo e não precisar se preocupar tanto com as complexidades do HTTP. Há prós e contras em ambos.
The Muffin Man
2
@ The Muffin Man, não sei como você pode fingir saber se prefiro REST ou RPC, nem por que é relevante para uma discussão sobre qual código de status retornar a uma solicitação HTTP GET.
J0057 3/03
Tive alguns problemas horríveis de cache ao usar o 204. O Chrome trataria a solicitação de maneira estranha e não mostraria nada na rede e armazenaria em cache o resultado anterior. Mesmo com todos os cabeçalhos sem cache do mundo. Concordo com esta resposta, 200 parece ser o melhor com um array / objeto vazio passado para o usuário.
Jack
22

Em projetos anteriores, usei 404. Se não houver usuário 9, o objeto não foi encontrado. Portanto, 404 não encontrado é apropriado.

Para o objeto existe, mas não há dados, 204 Nenhum Conteúdo seria apropriado. Eu acho que no seu caso, o objeto ainda não existe.

Máx.
fonte
14

De acordo com o post do w3 ,

200 OK

A solicitação foi bem sucedida. As informações retornadas com a resposta dependem do método usado na solicitação

202 Aceito

A solicitação foi aceita para processamento, mas o processamento não foi concluído.

204 Sem Conteúdo

O servidor atendeu à solicitação, mas não precisa retornar um corpo de entidade e pode querer retornar metainformações atualizadas.

400 Solicitação incorreta

A solicitação não pôde ser entendida pelo servidor devido à sintaxe incorreta. O cliente NÃO DEVE repetir o pedido sem modificações

401 não autorizado

A solicitação requer autenticação do usuário. A resposta DEVE incluir um campo de cabeçalho WWW-Authenticate

404 não encontrado

O servidor não encontrou nada que corresponda ao Request-URI. Nenhuma indicação é dada se a condição é temporária ou permanente

JustCode
fonte
A postagem do w3 é sobre códigos de status HTTP. HTTP não é idêntico ao REST. O REST usa principalmente HTTP, mas não necessariamente, como protocolo de transporte. 404 é um código de erro de transporte HTTP. Se REST for o mesmo que HTTP, não deve ser chamado de HTTP?
111118
1
@anneb Como você disse, o REST usa HTTP, então essa resposta faz totalmente sentido. REST não é HTTP, REST não é um protocolo de qualquer maneira. O REST não precisa ser idêntico (ou igual ao HTTP) para que esta resposta não faça sentido.
Koray Tugay
@Koray Tugay: a pesquisa no google também usa http; portanto, de acordo com esta resposta, a pesquisa no google deve responder o status http 404 se nada corresponder à pesquisa?
anneb
@anneb A Pesquisa do Google mencionou um aplicativo RESTful? Eu acho que não. Portanto, a resposta será não. Voltando à pergunta original e a esta resposta, em vez de cair em uma toca de coelho. Se um dia a Pesquisa do Google criar uma API RESTful (ou talvez já a tenha, eu não sei), ela poderá retornar 204 No Contentquando não encontrar resultados. Não 404, ele tem um resultado para você, mas não tem conteúdo ..
Koray Tugay
13

Para resumir ou simplificar,

2xx: Dados opcionais: URI bem formado: os critérios não fazem parte do URI: se o critério for opcional, pode ser especificado em @RequestBody e @RequestParam deve levar a 2xx. Exemplo: filtrar por nome / status

4xx: dados esperados: URI não bem formado: os critérios fazem parte do URI: se os critérios forem obrigatórios e só puderem ser especificados em @PathVariable, deverão resultar em 4xx. Exemplo: pesquisa por ID exclusivo.

Assim, para a situação solicitada: "users / 9" seria 4xx (possivelmente 404). Mas para "users? Name = superman" deveria ser 2xx (possivelmente 204).

Ashish Singh
fonte
12

Há duas perguntas. Um no título e outro no exemplo. Eu acho que isso levou em parte à quantidade de controvérsias sobre qual resposta é apropriada.

O título da pergunta pergunta sobre dados vazios. Dados vazios ainda são dados, mas não são iguais a nenhum dado. Portanto, isso sugere solicitar um conjunto de resultados, ou seja, uma lista, talvez de/users . Se uma lista estiver vazia, ainda será uma lista, portanto, um 204 (Sem Conteúdo) é o mais apropriado. Você acabou de pedir uma lista de usuários e recebeu um, por acaso não possui conteúdo.

O exemplo fornecido, em vez disso, pergunta sobre um objeto específico, um usuário /users/9,. Se o usuário nº 9 não for encontrado, nenhum objeto de usuário será retornado. Você solicitou um recurso específico (um objeto de usuário) e não recebeu porque não foi encontrado; portanto, um 404 é apropriado.

Eu acho que a maneira de resolver isso é se você pode usar a resposta da maneira que esperaria sem adicionar nenhuma declaração condicional; em seguida, use um 204, caso contrário, use um 404.

Nos meus exemplos, eu posso percorrer uma lista vazia sem verificar se há conteúdo, mas não consigo exibir dados do objeto de usuário em um objeto nulo sem quebrar algo ou adicionar uma verificação para verificar se é nula.

Obviamente, você poderia retornar um objeto usando o padrão de objeto nulo, se isso atender às suas necessidades, mas isso for uma discussão para outro encadeamento.

Caixa azul
fonte
9

Depois de analisar a questão, você não deve usar o 404porquê?

Com base na RFC 7231, o código de status correto é204

Nas respostas acima, notei um pequeno mal-entendido:

1.- o recurso é: /users

2.- /users/8não é o recurso, é este: o recurso /userscom parâmetro de rota8 , o consumidor talvez não consiga percebê-lo e não saiba a diferença, mas o editor conhece e deve saber disso! ... portanto, ele deve retornar uma resposta precisa para os consumidores. período.

tão:

Com base no RFC: 404 está incorreto porque os recursos foram /usersencontrados, mas a lógica executada usando o parâmetro 8não encontrou nenhum contentretorno como resposta, portanto, a resposta correta é:204

O ponto principal aqui é: 404nem mesmo o recurso foi encontrado para processar a lógica interna

204é um: Encontrei o recurso, a lógica foi executada, mas não encontrei nenhum dado usando seus critérios dados no parâmetro route, portanto não posso retornar nada para você. Desculpe, verifique seus critérios e ligue para mim novamente.

200: ok, encontrei o recurso, a lógica foi executada (mesmo quando não sou obrigada a retornar nada) pegue isso e use-o à sua vontade.

205: (a melhor opção de uma resposta GET) Encontrei o recurso, a lógica foi executada, tenho algum conteúdo para você, use-o bem, a propósito, se você deseja compartilhar isso em uma visualização, atualize a visualização para exibi-lo.

Espero que ajude.

rodfraga
fonte
8

O que as respostas existentes não elaboram é que faz diferença se você usa parâmetros de caminho ou parâmetros de consulta.

  • No caso de parâmetros do caminho, o parâmetro faz parte do caminho do recurso. No caso de /users/9, a resposta deve ser 404porque esse recurso não foi encontrado. /users/9é o recurso e o resultado é unário ou um erro, ele não existe. Esta não é uma mônada.
  • No caso de parâmetros de consulta, o parâmetro não faz parte do caminho do recurso. No caso de /users?id=9, a resposta deve ser 204porque o recurso /usersfoi encontrado, mas não pôde retornar nenhum dado. O recurso /usersexiste e o resultado é n-ário, existe mesmo se estiver vazio. Se idfor único, é uma mônada.

A utilização de parâmetros de caminho ou de consulta depende do caso de uso. Prefiro parâmetros de caminho para argumentos obrigatórios, normativos ou de identificação e parâmetros de consulta para argumentos opcionais, não normativos ou de atribuição (como paginação, local de agrupamento e outras coisas). Em uma API REST, eu usaria /users/9não /users?id=9especialmente por causa do possível aninhamento para obter "registros filhos", como /users/9/ssh-keys/0obter a primeira chave pública ssh ou /users/9/address/2o terceiro endereço postal.

Eu prefiro usar 404. Aqui está o porquê:

  • Os pedidos de métodos unários (1 resultado) e n-ário (n resultados) não devem variar sem um bom motivo. Eu gosto de ter os mesmos códigos de resposta, se possível. O número de resultados esperados é obviamente uma diferença, digamos, que você espera que o corpo seja um objeto (unário) ou uma matriz de objetos (n-ária).
  • Para n-ária, eu retornaria uma matriz e, caso não houvesse resultados, não retornaria nenhum conjunto (sem documento), retornaria um conjunto vazio (documento vazio, como matriz vazia em JSON ou elemento vazio em XML ) Ou seja, ainda são 200, mas com zero registro. Não há razão para colocar essas informações no fio, a não ser no corpo.
  • 204é como um voidmétodo. Eu não iria usá-lo para GET, apenas para POST, PUTe DELETE. Eu faço uma exceção no caso de GETonde os identificadores são parâmetros de consulta e não parâmetros de caminho.
  • Não encontrar o registro é como NoSuchElementException, ArrayIndexOutOfBoundsExceptionou algo parecido, causado pelo cliente usando um ID que não existe, portanto, é um erro do cliente.
  • De uma perspectiva de código, obter 204significa uma ramificação adicional no código que poderia ser evitada. Isso complica o código do cliente e, em alguns casos, também o código do servidor (dependendo de você usar mônadas de entidade / modelo ou entidades / modelos simples; e eu recomendo fortemente ficar longe das mônadas de entidade / modelo, pois isso pode levar a erros desagradáveis, porque da mônada, você acha que uma operação é bem-sucedida e retorna 200 ou 204 quando você realmente deveria ter retornado outra coisa).
  • É mais fácil escrever e entender o código do cliente se 2xx significa que o servidor fez o que o cliente solicitou e 4xx significa que o servidor não fez o que o cliente solicitou e a culpa é do cliente. Não fornecer ao cliente o registro de que o cliente solicitado pelo ID é culpa do cliente, porque ele solicitou um ID que não existe.

Por último, mas não menos importante: Consistência

  • GET /users/9
  • PUT /users/9 e DELETE /users/9

PUT /users/9e DELETE /users/9já precisa retornar 204em caso de atualização ou exclusão bem-sucedida. Então, o que eles devem retornar caso o usuário 9 não exista? Não faz sentido ter a mesma situação apresentada como códigos de status diferentes, dependendo do método HTTP usado.

Além disso, não é uma razão normativa, mas cultural: se 204for usada para a GET /users/9próxima coisa que acontecerá no projeto é que alguém acha que retornar 204é bom para métodos n-ários. E isso complica o código do cliente, porque, em vez de apenas 2xxprocurar 204e decodificar o corpo, o cliente agora precisa procurar especificamente e, nesse caso, pular a decodificação do corpo. Brotar o que o cliente faz em seu lugar? Criar uma matriz vazia? Por que não ter isso no fio, então? Se o cliente cria a matriz vazia, 204 é uma forma de compactação estúpida. Se o cliente usar null, uma lata de worms totalmente diferente será aberta.

Christian Hujer
fonte
3

204 é mais apropriado. Especialmente quando você tem um sistema de alerta para garantir a segurança do site, o 404 nesse caso causaria confusão, porque você não sabe que alguns alertas 404 são erros de back-end ou solicitações normais, mas a resposta está vazia.

刘武豪
fonte
Você não deve retornar 404 se tiver um erro de back-end.
appalling22
3

Eu diria que nenhum deles é realmente apropriado. Como foi dito - por exemplo, por @anneb, eu também acho que parte dos problemas surge do uso de um código de resposta HTTP para transportar um status relacionado a um serviço RESTful. Tudo o que o serviço REST tem a dizer sobre seu próprio processamento deve ser transportado por meio de códigos específicos do REST.

1

Eu diria que, se o servidor HTTP encontrar algum serviço pronto para responder a uma solicitação que foi enviada, ele não deverá responder com um HTTP 404 - no final, algo foi encontrado pelo servidor - a menos que seja explicitamente explicado pelo serviço que processa a solicitação.

Vamos assumir por um momento o seguinte URL: http://example.com/service/return/test.

  • O caso A é que o servidor está "simplesmente procurando o arquivo no sistema de arquivos". Se não estiver presente, 404está correto. O mesmo é verdade, se ele solicitar algum tipo de serviço para entregar exatamente esse arquivo e esse serviço informar que não existe esse nome.
  • No caso B, o servidor não funciona com arquivos "reais", mas na verdade a solicitação é processada por algum outro serviço - por exemplo, algum tipo de sistema de modelagem. Aqui, o servidor não pode fazer nenhuma reivindicação sobre a existência do recurso, pois não sabe nada sobre ele (a menos que seja informado pelo serviço que o manipula).

Sem qualquer resposta do serviço que exija explicitamente um comportamento diferente, o servidor HTTP pode dizer apenas três coisas:

  • 503 se o serviço que deveria lidar com a solicitação não estiver em execução ou respondendo;
  • 200 caso contrário, como o servidor HTTP pode realmente atender à solicitação - não importa o que o serviço dirá posteriormente;
  • 400ou 404para indicar que não existe esse serviço (em vez de "existe, mas está offline") e nada mais foi encontrado.

2

Voltando à questão em questão: acho que a abordagem mais limpa seria não usar nenhum código de resposta HTTP além do que foi dito anteriormente. Se o serviço estiver presente e respondendo, o código HTTP deve ser 200. A resposta deve conter o status que o serviço retornou em um cabeçalho separado - aqui, o serviço pode dizer

  • REST:EMPTYpor exemplo, se foi solicitado a procurar sth. e que a pesquisa retornou vazia;
  • REST:NOT FOUNDse foi solicitado especificamente para sth. “Tipo ID” - seja um nome de arquivo ou um recurso por ID ou entrada nº 24, etc. - e esse recurso específico não foi encontrado (geralmente, um recurso específico foi solicitado e não encontrado);
  • REST:INVALID se alguma parte da solicitação que foi enviada não for reconhecida pelo serviço.

(observe que eu os prefixei com "REST:" de propósito para marcar o fato de que, embora possam ter os mesmos valores ou palavras que os códigos de resposta HTTP, eles são completamente diferentes)

3

Vamos voltar ao URL acima e inspecionar o caso B em que o serviço indica ao servidor HTTP que ele não processa essa solicitação em si, mas a repassa SERVICE. O HTTP serve apenas o que é devolvido SERVICE, ele não sabe nada sobre a return/testparte em que é entregue SERVICE. Se esse serviço estiver em execução, o HTTP deverá retornar 200, pois de fato encontrou algo para lidar com a solicitação.

O status retornado por SERVICE(e que, como dito acima, gostaria de ver em um cabeçalho separado) depende de qual ação é realmente esperada:

  • se return/testsolicita um recurso específico: se existir, retorne-o com um status de REST:FOUND; se esse recurso não existir, retorne REST:NOT FOUND; isso poderia ser estendido para retornar REST:GONEse soubermos que ela já existia e não voltará, e REST:MOVEDse sabemos que se tornou hollywood
  • se return/testfor considerada uma operação de pesquisa ou semelhante a filtro: se o conjunto de resultados estiver vazio, retorne um conjunto vazio no tipo solicitado e no status de REST:EMPTY; um conjunto de resultados no tipo solicitado e um status deREST:SUCCESS
  • se return/testnão for uma operação reconhecida por SERVICE: retorne REST:ERRORse estiver completamente errada (por exemplo, um erro de digitação retrun/test), ou REST:NOT IMPLEMENTEDcaso esteja planejada para mais tarde.

4

Essa distinção é muito mais limpa do que misturar as duas coisas diferentes. Isso também tornará a depuração mais fácil e o processamento apenas um pouco mais complexo, se houver.

  • Se um HTTP 404 for retornado, o servidor me dirá: "Não faço ideia do que você está falando". Embora a parte REST da minha solicitação esteja perfeitamente correta, estou procurando par'Mach em todos os lugares errados.
  • Por outro lado, o HTTP 200 e o REST: ERR informam que eu obtive o serviço, mas fiz algo errado na minha solicitação ao serviço.
  • Do HTTP 200 e REST: VAZIO, sei que não fiz nada errado - servidor certo, o servidor encontrou o serviço, solicitação correta para o serviço - mas o resultado da pesquisa está vazio.

Resumo

O problema e a discussão decorrem do fato de que os códigos de resposta HTTP estão sendo usados ​​para indicar o estado de um serviço cujos resultados são atendidos por HTTP ou para indicar sth. isso não está no escopo do próprio servidor HTTP. Devido a essa discrepância, a pergunta não pode ser respondida e todas as opiniões estão sujeitas a muita discussão.

O estado de uma solicitação processada por um serviço e não pelo servidor HTTP REALMENTE NÃO (RFC 6919) deve ser fornecido por um código de resposta HTTP. O código HTTP DEVE (RFC 2119) conter apenas as informações que o servidor HTTP pode fornecer a partir de seu próprio escopo: a saber, se o serviço foi encontrado para processar a solicitação ou não.

Em vez disso, uma maneira diferente deve ser usada para informar um consumidor sobre o estado da solicitação para o serviço que está realmente processando a solicitação. Minha proposta é fazê-lo através de um cabeçalho específico. Idealmente, o nome do cabeçalho e seu conteúdo seguem um padrão que facilita o trabalho dos consumidores com essas respostas.

dariok
fonte
2

De acordo com o RFC7231 - page59 ( https://tools.ietf.org/html/rfc7231#page-59 ), a definição de resposta do código de status 404 é:

6.5.4 404 não encontrado O código de status 404 (não encontrado) indica que o servidor de origem não encontrou uma representação atual para o recurso de destino ou não está disposto a divulgar que existe. Um código de status 404 não indica se essa falta de representação é temporária ou permanente; o código de status 410 (Gone) é preferido sobre 404, se o servidor de origem souber, presumivelmente por alguns meios configuráveis, que a condição provavelmente será permanente. Uma resposta 404 é armazenável em cache por padrão; isto é, a menos que indicado de outra forma pela definição do método ou pelos controles explícitos de cache (consulte a Seção 4.2.2 de [RFC7234]).

E o principal que traz dúvidas é a definição de recurso no contexto acima. De acordo com a mesma RFC (7231), a definição de recurso é:

Recursos: o destino de uma solicitação HTTP é chamado de "recurso". HTTP não limita a natureza de um recurso; apenas define uma interface que pode ser usada para interagir com recursos. Cada recurso é identificado por um URI (Uniform Resource Identifier), conforme descrito na Seção 2.7 da [RFC7230]. Quando um cliente constrói uma mensagem de solicitação HTTP / 1.1, ele envia o URI de destino em um dos vários formulários, conforme definido na (Seção 5.3 de [RFC7230]). Quando uma solicitação é recebida, o servidor reconstrói um URI de solicitação eficaz para o recurso de destino (Seção 5.5 de [RFC7230]). Um objetivo do projeto do HTTP é separar a identificação de recursos da semântica de solicitação, o que é possível investindo a semântica de solicitação no método de solicitação (Seção 4) e alguns campos de cabeçalho de modificação de solicitação (Seção 5).

Portanto, no meu entender, o código de status 404 não deve ser usado em uma solicitação GET bem-sucedida com resultado vazio. (Exemplo: uma lista sem resultado para filtro específico)

Filipe Moisés
fonte
2

Tais coisas podem ser subjetivas e há alguns argumentos interessantes e vários sólidos de ambos os lados. No entanto [na minha opinião], retornar um 404 por dados ausentes não está correto . Aqui está uma descrição simplificada para deixar isso claro:

  • Pedido: Posso ter alguns dados, por favor?
  • Recurso (ponto de extremidade da API): receberei essa solicitação para você aqui [envia uma resposta de dados em potencial]

Nada quebrou, o terminal foi encontrado e a tabela e as colunas foram localizadas, de modo que o banco de dados consultado e os dados foram "retornados" com sucesso!

Agora - se essa "resposta bem-sucedida" possui dados ou não, não importa, você solicitou uma resposta de dados "potenciais" e essa resposta com dados "potenciais" foi atendida. Nulo, vazio etc. são dados válidos.

200 significa apenas que qualquer solicitação que fizemos foi bem-sucedida. Estou solicitando dados, nada deu errado com o HTTP / REST e, como os dados (embora vazios) foram retornados, minha "solicitação de dados" foi bem-sucedida.

Retorne 200 e deixe o solicitante lidar com dados vazios, conforme cada cenário específico o justifique!

Considere este exemplo:

  • Pedido: consulta a tabela "infrações" com o ID do usuário 1234
  • Recurso (ponto de extremidade da API): retorna uma resposta, mas os dados estão vazios

Esses dados vazios são totalmente válidos. Isso significa que o usuário não possui infrações. Este é um 200, pois é tudo válido, como então eu posso fazer:

Você não tem infrações, tem um muffin de mirtilo!

Se você considera 404 o que está afirmando? Não foi possível encontrar as infrações do usuário? Agora, gramaticalmente, isso está correto, mas simplesmente não está correto no mundo REST, quando o sucesso ou o fracasso é sobre a solicitação. Os dados de "infração" para este usuário foram encontrados com sucesso, existem zero infrações - um número real que representa um estado válido.


[Nota atrevida ..]

No seu título, você concorda subconscientemente que 200 é a resposta correta:

Qual é o código de resposta REST adequado para uma solicitação válida, exceto dados vazios?


Aqui estão algumas coisas a considerar ao escolher qual código de status usar, independentemente da subjetividade e das escolhas complicadas:

  1. Consistência . Se você usar 404 para "sem dados", use-o sempre que uma resposta retornar nenhum dado.
  2. Não use o mesmo status para mais de um significado . Se você retornar 404 quando um recurso não foi encontrado (por exemplo, o ponto final da API não existe, etc.), também não o use para nenhum dado retornado. Isso apenas torna difícil lidar com as respostas.
  3. Considere o contexto cuidadosamente . Qual é o "pedido"? O que você está dizendo que está tentando alcançar?
James
fonte
1

Codifique o conteúdo da resposta com uma enumeração comum que permita ao cliente ativá-lo e dividir a lógica de acordo. Não tenho certeza de como seu cliente distinguiria a diferença entre um "dado não encontrado" 404 e um "recurso da web não encontrado" 404? Você não deseja que alguém navegue até o usuário Z / 9 e faça com que o cliente se pergunte como se a solicitação fosse válida, mas não houvesse dados retornados.

Entre
fonte
1

Por que não usar 410? Isso sugere que o recurso solicitado não existe mais e que o cliente nunca deve fazer uma solicitação para esse recurso, no seu caso users/9.

Você pode encontrar mais detalhes sobre o 410 aqui: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Akshat
fonte
2
'espera-se que o cliente nunca faça uma solicitação' - e se esse usuário for criado mais tarde, sua resposta sugere que você garanta que esse usuário nunca existirá, isso é uma suposição muito ousada e provavelmente está errada
Holly
O que Holly disse. Para acrescentar a ela: mesmo que o usuário exista e tenha sido excluído, 410 está errado, porque e se o usuário for excluído? (Que tipo de é um caso especial de é criado mais tarde.)
Christian Hujer
porque 410 deve ser uma situação permanente. restapitutorial.com/httpstatuscodes.html
Akostha
1

É triste que algo tão simples e bem definido tenha se tornado "baseado em opiniões" neste tópico.

Um servidor HTTP conhece apenas "entidades", que é uma abstração para qualquer conteúdo, seja uma página estática da Web, uma lista de resultados de pesquisa, uma lista de outras entidades, uma descrição json de algo, um arquivo de mídia, etc.

Espera-se que cada uma dessas entidades seja identificável por um URL exclusivo, por exemplo

  • / user / 9 - uma única entidade: um USER ID = 9
  • / users - uma única entidade: uma lista de todos os usuários
  • /media/x.mp3 - uma única entidade: um arquivo de mídia chamado x.mp3
  • / search - uma única entidade: um CONTEÚDO dinâmico baseado em parâmetros de consulta

Se um servidor encontrar um recurso pelo URL fornecido, não importa qual seja seu conteúdo - 2G de dados, nulo, {}, [] - enquanto existir, será 200. Mas se essa entidade for não é conhecido pelo servidor, espera-se retornar 404 "Não encontrado".

Parece haver uma confusão de desenvolvedores que pensam que, se o aplicativo possui um manipulador para um determinado formato de caminho, não deve haver erro. Aos olhos do protocolo HTTP, não importa o que aconteceu nas partes internas do servidor (ou seja, se o roteador padrão respondeu ou um manipulador para um formato de caminho específico), desde que não haja uma entidade correspondente no servidor para o servidor. URL solicitada (que solicitou arquivo MP3, página da web, objeto de usuário etc.), que retornaria conteúdo válido (vazio ou não), deve ser 404 (ou 410 etc.).

Outro ponto de confusão parece estar em torno de "sem dados" e "sem entidade". O primeiro é sobre o conteúdo de uma entidade, e o último sobre a sua existência.

Exemplo 1:

  • Sem dados: / users retorna 200 OK, corpo: [] porque ninguém se registrou ainda
  • Nenhuma entidade: / users retorna 404 porque não há caminho / usuários

Exemplo 2:

  • Sem dados: / user / 9 retorna retorno 200 OK, corpo: {}, porque o ID do usuário = 9 nunca inseriu seus dados pessoais
  • Nenhuma entidade: / user / 9 retorna 404 porque não há um ID de usuário = 9

Exemplo 3:

  • Sem dados: / search? Name = Joe retorna 200 OK [], porque não há Joe no banco de dados
  • Nenhuma entidade: / search? Name = Joe retorna 404 porque não há caminho / pesquisa
Darko Maksimovic
fonte
0

404 seria muito confuso para qualquer cliente se você retornar apenas porque não há dados em resposta.

Para mim, o Código de Resposta 200 com um corpo vazio é suficiente para entender que tudo está perfeito, mas não há dados correspondentes aos requisitos.

energia escura
fonte
0

Conforme declarado por muitos, 404 é enganoso e não permite ao cliente discriminar se o uri da solicitação não existe ou se o uri solicitado não pode buscar o recurso solicitado.

Espera-se que o status 200 contenha dados de recursos - portanto, não é a escolha certa. O status 204 significa algo totalmente diferente e não deve ser usado como resposta para solicitações GET.

Todos os outros status existentes não são aplicáveis, por um motivo ou por outro.

Eu já vi esse tópico discutido várias vezes em vários lugares. Para mim, é dolorosamente óbvio que, para eliminar a confusão em torno do tópico, é necessário um status de sucesso dedicado. Algo como " 209 - Nenhum recurso para exibir".

Será um status 2xx porque não encontrar um ID não deve ser considerado um erro do cliente (se os clientes soubessem tudo o que está no banco de dados do servidor, eles não precisariam pedir nada ao servidor, não?). Esse status dedicado abordará todos os problemas debatidos com o uso de outros status.

A única pergunta é: como faço para que o RFC aceite isso como padrão?

Umberto Bar
fonte