Estou construindo um servidor que permite aos clientes armazenar objetos. Esses objetos são totalmente construídos no lado do cliente, completos com IDs de objeto que são permanentes por toda a vida útil do objeto.
Eu defini a API para que os clientes possam criar ou modificar objetos usando PUT:
PUT /objects/{id} HTTP/1.1
...
{json representation of the object}
O {id} é o ID do objeto, portanto faz parte do Request-URI.
Agora, também estou pensando em permitir que os clientes criem o objeto usando POST:
POST /objects/ HTTP/1.1
...
{json representation of the object, including ID}
Como POST é uma operação "anexar", não tenho certeza do que fazer caso o objeto já esteja lá. Devo tratar a solicitação como solicitação de modificação ou devo retornar algum código de erro (qual)?
Respostas:
Meu sentimento é que
409 Conflict
é o mais apropriado, porém, raramente visto na natureza, é claro:fonte
HTTP 409
com umLocation
cabeçalho apontando para o recurso existente / conflitante.De acordo com a RFC 7231 , um 303 Consulte Outros PODE ser usado Se o resultado do processamento de um POST for equivalente a uma representação de um recurso existente .
fonte
Pessoalmente, eu vou com a extensão WebDAV
422 Unprocessable Entity
.De acordo com a RFC 4918
fonte
422
me parece estranho ...É tudo sobre contexto e também quem é responsável por lidar com duplicatas em solicitações (servidor ou cliente ou ambos)
Se o servidor apenas apontar a duplicata , veja 4xx:
Para manipulação implícita de duplicatas, veja 2XX:
se é esperado que o servidor retorne algo , veja 3XX:
quando o servidor é capaz de apontar o recurso existente, isso implica em um redirecionamento.
Se o exposto acima não for suficiente, é sempre uma boa prática preparar alguma mensagem de erro no corpo da resposta.
fonte
Talvez esteja atrasado para o jogo, mas me deparei com esse problema semântico enquanto tentava criar uma API REST.
Para expandir um pouco a resposta de Wrikken, acho que você pode usar qualquer uma delas,
409 Conflict
ou403 Forbidden
dependendo da situação - em resumo, use um erro 403 quando o usuário não puder fazer absolutamente nada para resolver o conflito e concluir a solicitação (por exemplo, não pode enviar umDELETE
solicitação para remover explicitamente o recurso) ou use 409 se algo puder ser feito.Atualmente, alguém diz "403" e um problema de permissão ou autenticação vem à mente, mas a especificação diz que é basicamente o servidor que diz ao cliente que não vai fazer isso, não pergunte novamente e é por isso que o cliente não deve 't.
Quanto a
PUT
vs.POST
...POST
deve ser usado para criar uma nova instância de um recurso quando o usuário não tem meios ou não deve criar um identificador para o recurso.PUT
é usado quando a identidade do recurso é conhecida.fonte
POST
solicitação (quando usado corretamente), pois indica que deve ser retornado quando entrar em conflito com o recurso de destino . Como o recurso de destino ainda não foi lançado, ele não pode entrar em conflito e, portanto, responder com409 Conflict
isso não faz sentido.POST
, de fato, eu inferiria o contrário porque "É mais provável que os conflitos ocorram em resposta a uma solicitação PUT". parece indicar que outros métodos de solicitação também podem usar esse código. Além disso, "O corpo da resposta deve incluir informações suficientes para o usuário reconhecer a origem do conflito. Idealmente, a entidade de resposta incluiria informações suficientes para que o usuário ou o agente do usuário corrija o problema; no entanto, isso pode não ser possível e é não é necessário ". ( webdav.org/specs/rfc2616.html#status.409 )"302 encontrado" parece lógico para mim. E o RFC 2616 diz que PODE ser atendido para outros pedidos que não sejam GET e HEAD (e isso certamente inclui o POST)
Mas ainda mantém o visitante acessando este URL para obter esse recurso "Encontrado" pela RFC. Para fazê-lo ir diretamente para o URL "Encontrado" real, deve-se usar "303 See Other", o que faz sentido, mas força outra chamada a GET o seguinte URL. No lado bom, esse GET é armazenável em cache.
Eu acho que usaria "303 See Other" . Não sei se posso responder com a "coisa" encontrada no corpo, mas gostaria de fazer isso para salvar uma viagem de ida e volta ao servidor.
ATUALIZAÇÃO: Depois de reler o RFC, ainda acho que um código inexistente "4XX + 303 encontrado" deve estar correto. No entanto, o "409 Conflict" é o melhor código de resposta existente (como apontado por @Wrikken), talvez incluindo um cabeçalho Location apontando para o recurso existente.
fonte
Eu não acho que você deveria fazer isso.
O POST é, como você sabe, modificar a coleção e é usado para criar um novo item. Portanto, se você enviar o ID (acho que não é uma boa ideia), modifique a coleção, ou seja, modifique o item, mas é confuso.
Use-o para adicionar um item, sem identificação. É a melhor prática.
Se você deseja capturar uma restrição UNIQUE (não o ID), pode responder 409, como é possível nas solicitações PUT. Mas não o ID.
fonte
Eu iria com
422 Unprocessable Entity
, que é usado quando uma solicitação é inválida, mas o problema não está na sintaxe ou na autenticação.Como argumento contra outras respostas, usar qualquer
4xx
código que não seja de erro implicaria que não é um erro do cliente, e obviamente é. Usar um4xx
código que não seja erro para representar um erro do cliente simplesmente não faz sentido.Parece que
409 Conflict
é a resposta mais comum aqui, mas, de acordo com as especificações, isso implica que o recurso já existe e que os novos dados que você está aplicando são incompatíveis com seu estado atual. Se você estiver enviando umPOST
solicitar, com, por exemplo, um nome de usuário que já seja usado, na verdade não esteja em conflito com o recurso de destino, pois o recurso de destino (o recurso que você está tentando criar) ainda não foi publicado. É um erro especificamente para o controle de versão, quando há um conflito entre a versão do recurso armazenado e a versão do recurso solicitado. É muito útil para esse fim, por exemplo, quando o cliente armazena em cache uma versão antiga do recurso e envia uma solicitação com base nessa versão incorreta que não seria mais válida condicionalmente. "Nesse caso, a representação da resposta provavelmente conteria informações úteis para mesclar as diferenças com base no histórico de revisões." A solicitação para criar outro usuário com esse nome de usuário não é processável, não tendo nada a ver com o controle de versão.Para o registro, 422 também é o código de status que o GitHub usa quando você tenta criar um repositório com um nome já em uso.
fonte
Penso que, para o REST, você só precisa tomar uma decisão sobre o comportamento desse sistema específico. Nesse caso, acho que a resposta "certa" seria uma das poucas respostas dadas aqui. Se você deseja que a solicitação pare e se comporte como se o cliente tivesse cometido um erro que precisa corrigir antes de continuar, use 409. Se o conflito realmente não é tão importante e deseja manter a solicitação, responda redirecionando o cliente para a entidade que foi encontrada. Acho que as APIs REST adequadas devem ser redirecionadas (ou pelo menos fornecer o cabeçalho do local) para o ponto de extremidade GET para esse recurso após um POST de qualquer maneira, para que esse comportamento proporcione uma experiência consistente.
EDIT: Também vale a pena notar que você deve considerar um PUT, pois está fornecendo o ID. Então o comportamento é simples: "Eu não me importo com o que há agora, coloque isso aí". Ou seja, se não houver nada, ele será criado; se algo estiver lá, será substituído. Eu acho que um POST é mais apropriado quando o servidor gerencia esse ID. A separação dos dois conceitos basicamente mostra como lidar com ele (por exemplo, PUT é idempotente, portanto, ele deve sempre funcionar enquanto a carga útil valida, o POST sempre cria; portanto, se houver uma colisão de IDs, um 409 descreveria esse conflito) .
fonte
POST
solicitação (quando usado corretamente), pois afirma que deve ser retornado quando entrar em conflito com o recurso de destino . Como o recurso de destino ainda não foi lançado, ele não pode entrar em conflito e, portanto, responder com409 Conflict
não faz sentido.PUT
.Outro tratamento potencial é usar PATCH, afinal. Um PATCH é definido como algo que altera o estado interno e não se restringe a anexar.
PATCH resolveria o problema, permitindo a atualização de itens já existentes. Consulte: RFC 5789: PATCH
fonte
Por que não um 202 aceito ? É uma solicitação OK (200s), não houve erros do cliente (400s), por si só.
De 10 definições de código de status :
... porque não precisava ser concluída, porque já existia. O cliente não sabe que já existia, não fez nada de errado.
Estou apostando em lançar um 202 e retornar um conteúdo semelhante ao que um GET
/{resource}/{id}
teria retornado.fonte
Tropecei nessa pergunta enquanto verifica o código correto para o registro duplicado.
Perdoe minha ignorância, mas não entendo por que todo mundo está ignorando o código "300", que diz claramente "múltipla escolha" ou "ambíguo"
Na minha opinião, esse seria o código perfeito para criar um sistema não padrão ou particular para seu próprio uso. Eu também poderia estar errado!
https://tools.ietf.org/html/rfc7231#section-6.4.1
fonte
Mais provavelmente é
400 Bad Request
Como a solicitação contém valor duplicado (valor que já existe), ela pode ser percebida como um erro do cliente. Precisa alterar a solicitação antes da próxima tentativa.
Ao considerar esses fatos, podemos concluir como HTTP STATUS 400 Bad Request.
fonte
E o 208 - http://httpstatusdogs.com/208-already-reported ? Isso é uma opção?
Na minha opinião, se a única coisa é um recurso repetido, nenhum erro deve ser gerado. Afinal, não há erro nem no lado do cliente nem no servidor.
fonte
No seu caso, você pode usar
409 Conflict
E se você quiser verificar outros
HTTPs
códigos de status da lista abaixo1 ×✓ Informativo
2 ×✓ Sucesso
Redirecionamento 3x ×
Erro × Cliente × ×
Erro de servidor 5 ×✓
fonte