“Nenhum resultado” deve ser um erro em uma resposta RESTful?

45

Vou descrever um exemplo:
Eu começo a fazer uma API para uma confeitaria. A API permitirá que as pessoas pesquisem seus catálogos por produtos assados, como biscoitos caseiros de chocolate com menta, usando api.examplebakery.com/search?q=..... .

Alguém usa isso para procurar um produto chamado pineapple-banana flavoured cookies e, obviamente, não encontrará nenhum resultado.

Isso deve ser retornado como um erro? A pesquisa não falhou, a API pesquisou e concluiu com êxito que nenhum cookie foi encontrado. A API não deve retornar 404 , porque a API foi realmente encontrada.

    
por Berry M. 28.09.2017 / 12:47
fonte

6 respostas

116

Quando há resultados, a saída é uma lista (JSON, baseada em seu comentário). Para consultas sem resultados, a saída deve ser exatamente a mesma. A lista simples tem 0 itens.

Então, se sua resposta é normalmente esta:

{
    "results": [
        {
            "name": "Pancakes",
            ....
        },
        {
            "name": "French Fries",
            ....
        }
    ]
}

Então, para uma consulta com 0 resultados, deve ser isso:

{
    "results": []
}

Se você também incluir metadados sobre quantas "páginas" de resultados existem, links para essas "páginas", etc., sugiro dizer que há 1 "página".

O status HTTP deve ser o mesmo de quando há resultados - 200 OK .

204 No Content também pode parecer uma opção, mas não é porque você está de fato retornando "conteúdo" - a lista vazia. Se você achar que uma lista vazia não conta como "conteúdo", e se você alterar a resposta para oferecer sugestões de ortografia? O núcleo da resposta ainda será uma lista vazia, mas agora há ainda mais "conteúdo".

Para informações mais úteis sobre os códigos de status HTTP, jpmc26, sua resposta vale a pena ser lida.

    
por 28.09.2017 / 13:07
fonte
36

Sempre que decidir sobre um código HTTP, você deve sempre fazer essa pergunta:

What can/will/should any arbitrary client do with the response?

  1. O cliente sempre tratará a resposta como uma falha? Então você quer 4xx ou 5xx, dependendo se o problema é a entrada do cliente ou os processos do servidor.
  2. O cliente deve fazer uma solicitação em outro lugar? Então 3xx é para você.
  3. O servidor fez o que o cliente pediu (teve sucesso)? Isso é 2xx.

Sempre decida em qual faixa seu código de resposta deve estar primeiro. Fazê-lo rapidamente elimina muitos códigos de resposta como opções e (talvez mais importante) torna muito mais simples seguir a semântica dos códigos. Veja as seções iniciais da documentação do código HTTP para as explicações sobre o que cada categoria de códigos representa.

Nesse caso, o cliente solicitou uma lista de resultados considerando um filtro de um endpoint existente válido e com autorização para acessá-lo. O servidor pôde processar a solicitação e determinar os dados apropriados a serem retornados (nenhum item), portanto, a solicitação foi bem-sucedida. Acontece que o filtro que eles deram filtrou todos os resultados. Não cabe ao servidor determinar se é isso que o cliente queria ou não, pois isso pode ser um resultado esperado para alguns clientes. Se, de alguma forma, for um problema para o código do cliente, é responsabilidade do cliente determinar, verificar e manipular adequadamente. Então, isso é claramente 2xx.

Agora a pergunta é "Qual 2xx?" Isso depende de como você pretende que o servidor responda.

  • Você enviará de volta uma representação de uma lista vazia, como algumas outras respostas descrevem? Se assim, você quer 200. 200 significa que o servidor não teve problemas e tem uma representação dos resultados para o cliente consumir. Esta é provavelmente a maneira mais conveniente de responder por seus consumidores, que podem apenas analisar a resposta se houve resultados ou não e, em seguida, descobrir como lidar com uma lista vazia.
  • 204 não é semanticamente errado aqui, mas você teria que responder com nenhum corpo de mensagem qualquer . Isso significa que todo o código do cliente teria que verificar explicitamente códigos HTTP diferentes (ou pelo menos a falta de um corpo da mensagem) e tratá-los separadamente. É inconveniente e mais propenso a levar a clientes mal comportados.

Os outros não são aplicáveis:

  • 201 está fora de questão. Você não criou recursos persistentes e não está retornando um local para um recurso criado.
  • 202 está fora de questão. O pedido está feito; não está processando em segundo plano.
  • 203 significa que a resposta foi modificada entre o servidor autoritativo e o cliente. Sua interface RESTful é o servidor autoritativo, portanto, isso não se aplica aqui.
  • 205 não faz sentido. Você não precisa do cliente para limpar ou atualizar qualquer coisa.
  • 206 parece ter sido projetado para retornar um recurso grande em várias respostas. Também requer que o cliente peça por uma parte do conteúdo nos cabeçalhos (assim a paginação via strings de consulta não se qualifica). Não aplicável aqui.

Portanto, ele deve ser 200 ou 204 e é mais provável que 200 leve a um código de cliente mais simples e mais robusto (especialmente se você usar uma estrutura de resposta consistente contendo uma lista vazia).

    
por 29.09.2017 / 02:46
fonte
15

Não. o uso de 404 para indicar "sua consulta foi processada, mas não houve correspondência" é horrível porque:

  • fluxo condicional com base no tratamento de exceções (ou seja, forçando um resultado não excepcional a criar e manipular uma exceção no cliente que pode ser sem desempenho e inábil)

  • ambigüidade entre a página 'real' não encontrada, você digitou os erros errados do endpoint

A coisa a ser lembrada é que sempre há um cliente para desserializar a mensagem e o que esse cliente retorna é importante; não a serialização.

Se o cliente retornar nulo, use a serialização de nulo. Se o cliente devolver uma matriz vazia, use [], se o cliente enviar um erro use 500 e passe a mensagem de erro

    
por 28.09.2017 / 17:54
fonte
9

Além da resposta muito boa de @ Ewan:

Se a consulta for do tipo que retorna um conjunto de resultados, o conjunto vazio será logicamente tão apropriado quanto um conjunto de um ou um conjunto de mais. De um modo geral, pelas razões que @Ewan declara, é mais prejudicial do que bom alterar o conjunto vazio para um erro, e é simplesmente desnecessário.

Se a consulta é do tipo que procura e retorna um singleton específico (que se espera encontrar, por exemplo, correspondência exata por id), então não é encontrada uma resposta possível logicamente apropriada.

    
por 28.09.2017 / 18:06
fonte
5

Você está assumindo que o código precisa executar uma ação especial quando não há dados retornados, mas isso pode não ser o caso. O código pode simplesmente estar procurando por uma contagem de produtos ou anexar os resultados a uma lista ou a qualquer número de itens. Você só deve dar um erro ao usuário se houver um erro.

    
por 28.09.2017 / 22:44
fonte
0

Quando uso uma API, como cliente, tenho que lidar com casos de "sucesso" diferentes de casos de "erro"; Eu não tenho escolha lá. Portanto, você deve retornar um erro em situações que o cliente deseja que trate de forma diferente, e o sucesso em situações que o cliente quer trate o mesmo.

Se eu fizer uma consulta que poderia, em teoria, retornar qualquer número de resultados, zero, um, duzentos e assim por diante, você deve retornar "sucesso" sempre que a API fornecer a lista completa de todos os resultados. E, possivelmente, nos casos em que há muitos resultados, você retornou uma lista parcial de resultados para evitar um tamanho excessivo, e há um modo acordado de como obteria os outros resultados. Isso porque, como cliente, muitas vezes quero lidar com o caso de zero resultados, como no caso de mais resultados. Eu poderia tratar de forma diferente, mas não quero ser forçada a isso.

É diferente no caso em que eu procuro um valor. Espero exatamente um resultado, o valor que estou procurando. E eu preciso desse resultado para continuar o que quero fazer de uma maneira significativa. Aqui é muito mais aceitável retornar um status 404 para o caso de não haver nenhum valor, porque eu preciso lidar com esse caso de maneira diferente.

Resumo: Se o cliente esperar qualquer número de resultados, de zero a números grandes, retorne "sucesso" se todos os resultados forem entregues, mesmo que o número seja zero. Se o cliente esperar exatamente um resultado, retorne o sucesso se o resultado for encontrado e um erro se o resultado não for encontrado.

    
por 02.10.2017 / 19:55
fonte