É errado retornar 202 “Aceito” em resposta ao HTTP GET?

90

Tenho um conjunto de recursos cujas representações são criadas preguiçosamente. O cálculo para construir essas representações pode levar de alguns milissegundos a algumas horas, dependendo da carga do servidor, do recurso específico e da fase da lua.

A primeira solicitação GET recebida para o recurso inicia a computação no servidor. Se o cálculo for concluído em alguns segundos, a representação computada será retornada. Caso contrário, um código de status 202 "Aceito" é retornado e o cliente deve pesquisar o recurso até que a representação final esteja disponível.

O motivo para esse comportamento é o seguinte: Se um resultado estiver disponível em alguns segundos, ele precisa ser recuperado o mais rápido possível; caso contrário, quando estiver disponível, não é importante.

Devido à memória limitada e ao grande volume de solicitações, nem NIO nem long polling são uma opção ( ou seja, não consigo manter conexões abertas o suficiente, nem mesmo caber todas as solicitações na memória; uma vez "alguns segundos" passaram, eu persisto os pedidos em excesso). Da mesma forma, as limitações do cliente são tais que eles não podem lidar com um retorno de chamada de conclusão. Por fim, observe que não estou interessado em criar um recurso de "fábrica" ​​para o qual seja feito um POST, pois as viagens extras significam que falhamos na restrição de tempo real por partes mais do que o desejado (além disso, é uma complexidade extra; também, este é um recurso que beneficiar do armazenamento em cache).

Imagino que haja alguma controvérsia sobre o retorno de um código de status 202 "Aceito" em resposta a uma solicitação GET, visto que nunca vi isso na prática e seu uso mais intuitivo é em resposta a métodos inseguros, mas nunca encontrou algo especificamente desencorajador. Além disso, não estou preservando a segurança e a idempotência?

Então, o que as pessoas pensam sobre essa abordagem?

EDIT : Devo mencionar que isso é para uma chamada API da web de negócios - não para navegadores.

usuário359996
fonte
2
Eu pessoalmente acho que é bom, é exatamente a definição de a 202. O fato de raramente ser usado na prática é mais IMHO porque poucos desenvolvedores da web se preocupam com os códigos de status adequados, já que estão mais acostumados com a interação navegador / usuário-agente, caso em que a não 202dá a eles nenhuma pista visível (dê a eles um 200e eles ficarão felizes. ..).
Wrikken
1
@ user359996, basta usar 200. 202é o que deveria ser, mas na prática as pessoas não esperam 202.
Pacerier
ele precisa de um ETA para um 200 para ser útil na prática.
Rob

Respostas:

66

Se for para uma API bem definida e documentada, 202soa exatamente o que está acontecendo.

Se for para a Internet pública, eu ficaria muito preocupado com a compatibilidade do cliente. Já vi tantos if (status == 200)hard-coded .... Nesse caso, eu retornaria a 200.

Além disso, o RFC não faz nenhuma indicação de que o uso de 202 para uma solicitação GET seja errado, embora faça distinções claras em outras descrições de código (por exemplo, 200).

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

Pekka
fonte
17

Fizemos isso para um aplicativo recente, um cliente (aplicativo personalizado, não um navegador) postou uma consulta e o servidor retornou 202 com um URI para o "trabalho" sendo postado - o cliente usaria esse URI para pesquisar o resultado - isso parece se encaixar perfeitamente com o que estava sendo feito.

A coisa mais importante aqui é documentar como seu serviço / API funciona e o que uma resposta de 202 significa.

nos
fonte
+1 Obrigado pelo seu comentário. Bom ponto sobre a documentação. Mas, por favor, observe as edições esclarecedoras à minha pergunta (procure por "fábrica").
user359996
Bem, você pode omitir esse URI na resposta se quiser apenas pesquisar o mesmo URI que solicitou inicialmente. (Apenas documente como isso deve funcionar :-))
nos
Boa ideia, mas lembre-se de que quero cache, portanto, não há POST. Além disso, o URI especifica o recurso, não um método. Estou adotando uma abordagem RESTful, em vez de RPC (desculpe, outra restrição não especificada - minha má).
user359996
Para ser preciso, por "RESTful", na verdade quero dizer "orientado a recursos", o que é tecnicamente um pouco mais do que o especificado pelas restrições REST.
user359996
Isso também é apoiado por "1.10 How to Use POST for Asynchronous Tasks" pelo livro " RESTful Web Services Cookbook " por Subbu Allamraju
koppor
12

Pelo que me lembro - GET deve retornar um recurso sem modificar o servidor. Talvez a atividade seja registrada ou algo assim, mas a solicitação deve ser reiniciada com o mesmo resultado.

O POST, por outro lado, é uma solicitação para alterar o estado de algo no servidor. Insira um registro, exclua um registro, execute um trabalho, algo assim. 202 seria apropriado para um POST que retornou, mas não foi concluído, mas não é realmente uma solicitação GET.

É tudo muito puritano e não é bem praticado na natureza, então você provavelmente está seguro ao retornar 202. GET deve retornar 200. O POST pode retornar 200 se for concluído ou 202 se não for feito.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Dlongnecker
fonte
4
Muito bom pensamento, mas não tenho certeza se isso se aplica aqui: Pelo que diz o OP, esta parece ser uma solicitação GET adequada (na medida em que não muda nada no servidor), apenas leva mais tempo para computar e nesse caso, deve ser buscado em outro momento. Talvez o OP possa fazer um comentário confiável. É para uma API, então não há problema em ser "puritano" por causa de uma interface limpa
Pekka
Oh, touche pekka. Você está certo, GET é o caminho a percorrer. E eu não acho que o HTTP spc realmente levou em conta os GETs que não estão prontos. Então ele poderia ir de qualquer maneira
Dlongnecker
7
Comentário autoritário (agora irrelevante): Sim, considero isso idempotente. O recurso não está sendo modificado nem criado, mas sua representação ainda não foi calculada.
user359996
1
Onde está escrito isso? Além disso, se eu retornar 200, o cliente deve esperar que uma representação tenha sido retornada, mas não foi.
user359996
1
Eu retiro. 202 não corresponde apenas a GET ou POST ao que parece. Apenas a mentalidade que eu tinha quando olhei para o protocolo me fez pensar que 202 só existia para solicitações GET. 202 deve ser bom para seus propósitos.
Dlongnecker
0

No caso de um recurso que deveria ter uma representação de uma entidade que é claramente especificada por um ID (ao contrário de um recurso de "fábrica", conforme descrito na pergunta), recomendo ficar com o método GET e, em um situação em que a entidade / representação não está disponível devido à criação preguiçosa ou qualquer outra situação temporária, use o código de resposta 503 Serviço indisponível que é mais apropriado e foi realmente projetado para situações como esta.

Os motivos para isso podem ser encontrados nas RFCs para o próprio HTTP (verifique a descrição do código de resposta 503), bem como em vários outros recursos.

Compare com o código de status HTTP para páginas temporariamente indisponíveis . Embora essa pergunta seja sobre um caso de uso diferente, na verdade ela está relacionada ao mesmo recurso do HTTP.

Hermes
fonte