Como escolho um código de status HTTP na API REST para "Ainda não está pronto, tente novamente mais tarde"? [fechadas]

152

Estou desenvolvendo uma API RESTful na qual http://server/thingyapi/thingyblob/1234retorna o arquivo (também conhecido como "blob") associado à coisinha # 1234 para download. Mas pode ser que a solicitação seja feita em um momento em que o arquivo não exista no servidor, mas definitivamente estará disponível posteriormente. Há um processo em lote no servidor que gera todos os blobs para todas as coisas. O Thingy 1234 já existe e seus dados, exceto o blob, já estão disponíveis. O servidor ainda não conseguiu gerar o blob de 1234.

Eu não quero retornar 404; isso é para coisinhas que não existem. Isso é algo que existe, mas seu blob ainda não foi gerado. Como um vídeo do YouTube que está "processando". Também não acho que os códigos de redirecionamento sejam adequados; não há "outro" URL para tentar.

Qual é o código de status HTTP correto para retornar nesse caso?

JCCyC
fonte
3
Um pouco relacionado
Rob Hruska /
7
Primeiro, se o 1234 ainda não possui nenhuma representação capaz de GET, em que sentido ele existe como um recurso (da perspectiva do cliente)? O fato de que, interno ao servidor, existe um trabalho na fila para criar 1234, não parece implicar que o recurso 1234 existe. Segundo, onde o cliente conseguiu o URI ... / thingyblob / 1234? O servidor provavelmente não deveria ter fornecido esse URI para o cliente até que o recurso fosse realmente GET.
Andy Dennie 21/03
1
Uma coisa tem outras propriedades que valem a pena obter além da bolha. É apenas o blob que leva tempo para gerar. Cliente recebe os, por exemplo, server / thingyapi / coisinha / 1234
JCCyC
10
O padrão HTTP fornece orientação sobre quais códigos de status usar para quais situações. Portanto, esta questão não é realmente primariamente baseada em opiniões .
Raedwald
2
Que tal 204"Sem Conteúdo"? Is indica que o servidor processou a solicitação com sucesso e não está retornando nenhum conteúdo [no momento].
Timo

Respostas:

77

Eu sugiro 202 - Accepted. A partir da documentação :

A solicitação foi aceita para processamento, mas o processamento não foi concluído. [...] Seu objetivo é permitir que um servidor aceite uma solicitação para outro processo (talvez um processo orientado a lotes que seja executado apenas uma vez por dia)

Matsev
fonte
62
-1: isso faria sentido para a solicitação que inicia o processo que eventualmente cria "coisinha # 1234", mas não para a solicitação GET emitida posteriormente para a coisinha # 1234 ". Em particular, um 202 sugere que, como resultado da solicitação GET, o serviço enviará os dados para "coisinha # 1234" em um momento posterior. Isso simplesmente não está correto.
Sam Harwell 14/10
7
Ele também diz: "A entidade retornada com esta resposta DEVE incluir uma indicação do status atual da solicitação e um ponteiro para um monitor de status ou alguma estimativa de quando o usuário pode esperar que a solicitação seja atendida.", Portanto, isso seria um uma boa maneira de informar ao cliente que o blob ainda não está pronto e uma maneira de descobrir quando ele está pronto.
Remy Lebeau 15/10
3
Eu argumentaria que "aceito para processamento" indica que você está salvando a solicitação para ser processada posteriormente. Se estiver sendo ignorado, você deve retornar um código 4xx ou 5xx para indicar ao cliente que ele pode tentar novamente.
Lucas
3
102 (processamento) também parece uma escolha razoável às vezes, mesmo que esteja nas especificações do webdav.
akostadinov 02/12/19
2
Não posso discordar mais desta resposta. O servidor não está retornando nada ou está planejando (não está processando devido a essa solicitação - o que de qualquer maneira não deveria para um GET). Como tal, o recurso não está disponível de alguma forma para o cliente. Isso deve ser tratado como um erro, para que nenhum código 2XX seja apropriado. Algo no espaço 4XX ou 5XX. A solicitação " não foi aceita para processamento" ; na prática, a solicitação está sendo descartada.
Adam
52

O "problema", como é, está no lado do servidor: o cliente fez uma solicitação bem-formada, mas o servidor não pode atendê-la. Então, estou inclinado a um "Erro de servidor", código de status 5xx.

Quoth RFC 7231 (o padrão HTTP atual, ênfase adicionada):

A classe 5xx (Erro do servidor) do código de status indica que o servidor está ciente de que errou ou é incapaz de executar o método solicitado . Exceto ao responder a uma solicitação HEAD, o servidor DEVE enviar uma representação contendo uma explicação da situação de erro e se é uma condição temporária ou permanente.

Nota

  • "errou ou é incapaz de executar a solicitação": apesar do título de "Erro no servidor", eles não são apenas para erros do servidor.
  • " temporário ou permanente": esses códigos são adequados para recursos temporariamente indisponíveis, como o seu.

Dos códigos disponíveis, eu diria 503, "Serviço indisponível" foi o mais adequado:

O código de status 503 (Serviço Indisponível) indica que o servidor atualmente não pode lidar com a solicitação devido a uma sobrecarga temporária ou manutenção agendada, que provavelmente será aliviada após algum atraso. O servidor PODE enviar um campo de cabeçalho Repetir-Após ... para sugerir uma quantidade adequada de tempo para o cliente aguardar antes de repetir a solicitação.

Nota:

  • "provavelmente será aliviado após algum atraso": verdadeiro para o seu caso.
  • "sobrecarga temporária": não é pedanticamente verdade para o seu caso. Mas, pode-se argumentar, se o seu servidor fosse muito mais rápido, o processamento em lote já teria sido feito quando o cliente fez a solicitação, portanto, é uma espécie de "sobrecarga": o cliente está solicitando recursos mais rapidamente do que o servidor pode fazer eles disponíveis.
  • A nova tentativa é adequada para o seu serviço, portanto, sua resposta deve incluir um Retry-Aftervalor. Você pode fornecer como valor o tempo estimado de conclusão da próxima execução do processo em lote ou o intervalo de execução do processo em lote.

Definir seu próprio código de status 5xx (591, por exemplo), embora permitido , teria a semântica incorreta:

um cliente DEVE entender a classe de qualquer código de status, conforme indicado pelo primeiro dígito, e tratar um código de status não reconhecido como equivalente ao código de status x00 dessa classe

Os clientes tratariam seu próprio código de status como 500, "Erro interno do servidor" , o que não seria correto.

Raedwald
fonte
2
Não consigo ver como é melhor do que 202: benramsey.com/blog/2008/04/…
JCCyC 6/12/12
4
@JCCyC, seu blog é um bom argumento para retornar um 202 em resposta a uma solicitação para criar algo (um POST ou PUT). A pergunta parece estar perguntando sobre o que retornar para um GET.
Raedwald 6/09/12
@JCCyC poderia ser visto como um tom diferente de não-prontidão: imagine um ajax para esse recurso, você prefere 202 como status de sucesso ou 503 como status de erro? assim você pode ver o que significa que você prefere implicitamente no contexto da reação de seu aplicativo para a resposta
rloth
Também gosto do aspecto prático da "Retry-After" que vai bem com algo sendo "não está pronto"
rloth
1
NB: "Retry-After" também pode ir com 307 - TEMPORARY REDIRECTo que é bom se você quer do lado do cliente força de esperar em outro lugar, enquanto o seu ressource está sendo "preparado"
rloth
28

Eu acho que 423 - Locked pode ser usado para este fim:

O código de status 423 (Bloqueado) significa que o recurso de origem ou destino de um método está bloqueado. Esta resposta deve conter um código de pré-condição ou pós-condição apropriado, como 'bloqueio de token enviado' ou 'sem conflito de bloqueio'.

Fernando Ortega
fonte
1
Excelente resposta! Eu me pergunto por que não tem mais votos.
Lex82
10
Talvez por ser um código HTTP WebDAV?
Stephan L
1
Em akka-http, há StatusCode RetryWith = reg (c (449) ("Repetir com", "A solicitação deve ser tentada novamente após executar a ação apropriada.")) Onde a ação seria aguardar e tentar novamente
ozma
2
De muitas maneiras, eu concordo com isso. Eu tenho uma situação semelhante (no meu caso, pesquisando em um índice que ainda não pode ser preenchido). Semanticamente, acho que isso está correto. No entanto, o RFC para 423 estados "Esta resposta deve conter um código de pré-condição ou pós-condição apropriado, como 'bloqueio de token enviado' ou 'sem conflito de bloqueio'". Não sei como aplicar isso aqui. E pessoalmente eu aceitaria o 409 Conflict, mas isso foi prejudicado sem comentários - não sei por que?
Adam
22

Eu não quero retornar 404; isso é para coisinhas que não existem.

O URL não corresponde a uma solicitação de algo.

http://server/thingyapi/thingyblob/1234

O cliente está solicitando um thingyblob, que não existe. Se existisse, você daria a eles.

404

funroll
fonte
1
Estou feliz que alguém tenha dito isso! Não acredito que há tantas pessoas que pensam 503ser uma resposta apropriada. Sem mencionar algumas das outras sugestões estranhas.
Jason Desrosiers
Embora eu concorde que um 404 seja a resposta mais apropriada aqui, ele não responde à pergunta do OP como indicar quando o item está disponível :-). Eu acho que o campo Retry-After parece o melhor candidato, mas só pode ser usado oficialmente para códigos 503 e 3xx. @ Jason: Eu acho que isso explica algumas das sugestões estranhas.
Ron Deijkers
Eu acho que essa é a melhor resposta. Você tem permissão para retornar um corpo em uma resposta 404. O corpo pode indicar que a coisa estará disponível em uma data posterior. Ou use o cabeçalho Retry-After também. O padrão precisa ser esticado um pouco aqui, porque não cobre bem esse caso.
WW.
4
As pessoas se acostumaram demais à página de significado 404 não encontrada e não podem desassociar isso logicamente no contexto de uma API.
The Muffin Man
1
Isso é muuuuito 404. O Thingyblob ainda não existe, ou nunca .. Para http, é irrelevante se algum dia ele estará disponível. No momento, ele não existe, e seu 404. Quando estará disponível, há outro problema, que pode ser resolvido empurrando uma mensagem do servidor para o cliente, dizendo: whatyblob: 1234 available. Execute um get novamente e pronto ..
100r
21

Outra opção: 503 - Service Unavailable.

Brian Kelly
fonte
5
De acordo com o W3C , não é o que você quer dizer ao cliente (embora signifique "volte sempre" de alguma maneira): "No momento, o servidor não consegue lidar com a solicitação devido a uma sobrecarga ou manutenção temporária do servidor. A implicação é que esta é uma condição temporária que será atenuada após algum atraso.Se conhecida, a duração do atraso PODE ser indicada no cabeçalho Retry-After. Se nenhum Retry-After for fornecido, o cliente DEVE lidar com a resposta como faria para um 500 resposta ".
skalee
4
O serviço não está disponível, o serviço está disponível, mas o processamento não está completo. Então 503 provavelmente não é uma boa ideia.
Ishtiaque Khan
17

Como seu recurso não está pronto, você provavelmente sabe quando (aproximadamente) estará disponível e quando o cliente poderá tentar novamente sua solicitação. Isso significa que você pode querer utilizar o cabeçalho Retry-After . Esse cabeçalho é válido com as respostas 503 (Serviço Indisponível), o que significa que todo o site está inativo para manutenção e 3xx (Redirecionamento).

Na minha opinião, 302 (Encontrado) com o cabeçalho Repetir-Após seria a melhor opção, mas não tenho certeza se o campo Local do cabeçalho da resposta pode ser igual ao pedido de URL. É redirecionamento circular, de qualquer maneira.

skalee
fonte
3
Mesmo se for permitido, se o cliente não tiver implementado suporte para o cabeçalho Retry-After, um redirecionamento 3xx para a mesma página poderá terminar em 503 ... (opcionalmente com um cabeçalho Retry-After, é claro)
Ron Deijkers
1
A nova tentativa também é válida com o HTTP 429 "Solicitações em excesso", adicionado pela RFC 6585 (abril de 2012). Isso pode ser apropriado se o motivo do recurso ainda não estar pronto é que o cliente está dando muito trabalho ao servidor.
Silas S. Brown
8

409 Conflito

Indica que a solicitação não pôde ser processada devido a um conflito na solicitação, como um conflito de edição no caso de várias atualizações. [Fonte: Wikipedia.]

Isso pode ser apropriado.

Se você não puder atender à solicitação retornando os dados - não será um sucesso. Eu acho que 202 sugere que o servidor enfileirou a solicitação e a atenderá posteriormente. Mas, no seu caso, a solicitação é de dados agora e falhou. Se você tentar novamente mais tarde, é uma solicitação diferente.

Eu acho que você tem um conflito .. você quer os dados .. mas está sendo editado / atualizado. Esse também seria o caso se o Thingy1234 já existisse e tivesse sido baixado com sucesso antes, mas agora estava sendo editado e não estava disponível enquanto a edição estava ocorrendo.

J Moore
fonte
2
Não sei por que isso foi rejeitado. Parece a resposta certa para mim. No RFC: "O código de status 409 (Conflito) indica que a solicitação não pôde ser concluída devido a um conflito com o estado atual do recurso de destino. Esse código é usado em situações nas quais o usuário pode resolver o conflito e reenvie a solicitação. "Você solicitou um recurso que o servidor não pode retornar porque o servidor está no processo de atualização desse recurso - ou seja, devido ao estado atual do recurso. O cliente pode resolver isso espera e reenviá
Adam
1
@ Adam Acho que a implicação em "o usuário pode resolver o conflito" é que algo sobre a reenvio seria diferente, além de apenas esperar.
Holistic Developer
3

501 - Não implementado

Exatamente como parece. Um recurso que ainda não foi implementado, mas implica disponibilidade futura.

Aqui está um link para um resumo dos erros 5xx .

Dan
fonte
4
Para esta pergunta, parece que o recurso em si existe, mas o item solicitado não.
Lucas
A descrição do @Luke 501 no link da minha resposta: '... falta a capacidade de atender à solicitação. Normalmente, isso implica disponibilidade futura '. Isso cumpre exatamente o que o OP estava pedindo. Independentemente de os dados existirem ou não em seus servidores ou banco de dados. O resultado final é que ele não está acessível por meio da API no momento. Portanto, a API não pode atender à solicitação, mas gostaria de sugerir que ela estará disponível no futuro através do código http.
Dan