precisamos enviar todos os dados do artigo de volta à API para atualização e o trabalho multiusuário não pôde ser implementado. Por exemplo, o editor poderia enviar dados mais antigos de 5 segundos e substituir a correção que algum outro jornalista fez há apenas 2 segundos atrás, e não há como explicar isso aos clientes, uma vez que aqueles que publicam um artigo não estão realmente conectados à atualização do conteúdo.
Esse tipo de coisa é um desafio, não importa o que você faça. É um problema muito semelhante ao controle de fonte distribuído (mercurial, git etc.), e a solução, escrita em HTTP / ReST, parece um pouco semelhante.
Supondo que você tenha dois usuários, Alice e Bob, ambos trabalhando /articles/lunch
. (para maior clareza, a resposta está em negrito)
Primeiro, Alice cria o artigo.
PUT /articles/lunch HTTP/1.1
Host: example.com
Content-Type: text/plain
Authorization: Basic YWxpY2U6c2VjcmV0
Hey Bob, what do you want for lunch today?
301 Moved Permanently
Location: /articles/lunch/1
O servidor não criou um recurso, porque não havia "versão" anexada à solicitação (assumindo um identificador de /articles/{id}/{version}
. Para executar a criação, Alice foi redirecionada para o URL do artigo / versão que criará. O usuário de Alice O agente reaplicará a solicitação no novo endereço.
PUT /articles/lunch/1 HTTP/1.1
Host: example.com
Content-Type: text/plain
Authorization: Basic YWxpY2U6c2VjcmV0
Hey Bob, what do you want for lunch today?
201 Created
E agora o artigo foi criado. Em seguida, Bob analisa o artigo:
GET /articles/lunch HTTP/1.1
Host: example.com
Authorization: Basic Ym9iOnBhc3N3b3Jk
301 Moved Permanently
Location: /articles/lunch/1
Bob olha para lá:
GET /articles/lunch/1 HTTP/1.1
Host: example.com
Authorization: Basic Ym9iOnBhc3N3b3Jk
200 Ok
Content-Type: text/plain
Hey Bob, what do you want for lunch today?
Ele decide adicionar sua própria mudança.
PUT /articles/lunch/1 HTTP/1.1
Host: example.com
Content-Type: text/plain
Authorization: Basic Ym9iOnBhc3N3b3Jk
Hey Bob, what do you want for lunch today?
Does pizza sound good to you, Alice?
301 Moved Permanently
Location: /articles/lunch/2
Assim como Alice, Bob é redirecionado para onde ele criará uma nova versão.
PUT /articles/lunch/2 HTTP/1.1
Host: example.com
Content-Type: text/plain
Authorization: Basic Ym9iOnBhc3N3b3Jk
Hey Bob, what do you want for lunch today?
Does pizza sound good to you, Alice?
201 Created
Por fim, Alice decide que gostaria de adicionar ao seu próprio artigo:
PUT /articles/lunch/1 HTTP/1.1
Host: example.com
Content-Type: text/plain
Authorization: Basic YWxpY2U6c2VjcmV0
Hey Bob, what do you want for lunch today?
I was thinking about getting Sushi.
409 Conflict
Location: /articles/lunch/3
Content-Type: text/diff
---/articles/lunch/2
+++/articles/lunch/3
@@ 1,2 1,2 @@
Hey Bob, what do you want for lunch today?
-Does pizza sound good to you, Alice?
+I was thinking about getting Sushi.
Em vez de ser redirecionado normalmente, um código de status diferente é retornado ao cliente 409
, que informa a Alice que a versão da qual ela estava tentando ramificar já foi ramificada. Os novos recursos foram criados de qualquer maneira (conforme mostrado no Location
cabeçalho) e as diferenças entre os dois foram incluídas no corpo da resposta. Alice agora sabe que o pedido que ela acabou de fazer precisa ser mesclado de alguma maneira.
Todo esse redirecionamento está relacionado à semântica de PUT
, o que exige que novos recursos sejam criados exatamente onde a linha de solicitação solicita. isso também poderia salvar um ciclo de solicitação usando POST
, mas o número da versão teria que ser codificado na solicitação por alguma outra mágica, o que me pareceu menos óbvio para fins de ilustração, mas provavelmente ainda seria preferido em uma API real para minimizar os ciclos de solicitação / resposta.
api/article?action=publish
? Os parâmetros de consulta destinam-se a casos em que o estado do recurso depende do 'algoritmo' (ou ação) mencionado. Por exemplo,api/articles?sort=asc
é válido