Barra à direita na API RESTful

60

Eu tenho tido um debate sobre o que fazer com uma barra final em uma API RESTful.

Digamos que eu tenho um recurso chamado cães e recursos subordinados para cães individuais. Podemos, portanto, fazer o seguinte:

GET/PUT/POST/DELETE http://example.com/dogs
GET/PUT/POST/DELETE http://example.com/dogs/{id}

Mas o que fazemos com o seguinte caso especial:

GET/PUT/POST/DELETE http://example.com/dogs/

Minha opinião pessoal é que isso significa enviar uma solicitação para um recurso individual de cão com id = null. Eu acho que a API deve retornar um 404 para este caso.

Outros dizem que a solicitação está acessando o recurso dogs, ou seja, a barra final é ignorada.

Alguém sabe a resposta definitiva?

Gaz_Edge
fonte
2
Eu pensei que a maneira RESTful era distinguir entre cão / id e cães (ou seja, todos os cães).
#Revista
Do livro RESTful Web Services - recursos subordinados: recursos que existem em relação a algum outro recurso "pai", por exemplo, dogs / {id} Um banco de dados ativado pela Web pode expor uma tabela como recurso, e o banco de dados individual filas como recursos subordinados .
Gaz_Edge
Ele está acessando o recurso dog, a barra à direita deve ser ignorada, o que significa que deve receber uma resposta proibida por tentar excluir algo ao qual a exclusão não deve ser aplicada. Eu acho que 404 também é aceitável. Isso importa?
Benjamin Gruenbaum
Eu não sigo - quem disse que você não pode excluir cães? Se você excluir cães, ele excluirá a si mesmo e a todos os cães individuais. É por isso que acho que permitir chamadas para cães / é arriscado. E se o cliente pretendesse excluir um cão individual, mas acidentalmente deixasse de fora o {id}. O resultado seria que todos os cães seriam excluídos. Muito mais seguro para assumir que está pedindo {id} nula e voltar 404
Gaz_Edge
Eu trataria dogse dogs/como equivalente. Para mim, é claro que dogs/é um diretório que contém os cães individuais. É menos claro o que dogsé, mas eu trataria isso como equivalente, assim como a maioria dos servidores da Web aceita acessos a diretórios sem o rastreamento /.
CodesInChaos

Respostas:

50

Nada disso é autoritário (como REST não tem significado exato). Porém, no artigo original no REST, uma URL completa (que não termina em /) nomeia um recurso, enquanto uma terminada em uma barra '/' é um grupo de recursos (provavelmente não redigido dessa maneira).

Um GET de um URL com uma barra no final deve listar os recursos disponíveis.

GET http://example.com/dogs/          /* List all the dogs resources */

Uma PUT em uma URL com uma barra deve substituir todos os recursos.

PUT http://example.com/dogs/          /* Replace all the dogs resources */

Um DELETE em um URL com uma barra deve excluir todos os recursos

DELETE http://example.com/dogs/       /* Deletes all the dogs resources */

Um POST em uma URL com uma barra deve criar um novo recurso e pode ser acessado posteriormente. Para estar em conformidade, o novo recurso deve estar neste diretório (embora muitas arquiteturas RESTful trapaceiem aqui).

POST http://example.com/dogs/        /* Creates a new dogs resource (notice singular) */

etc.

A página wiki sobre o assunto parece explicar bem:

Veja o exemplo https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_Web_services .

Martin York
fonte
Ele também se encaixa no modelo caminho / url normal, onde os diretórios são muitas vezes escritos com uma fuga/
CodesInChaos
4
Então, o que deve acontecer se você acessar um grupo de recursos sem o rastreamento /?
Oberlies
11
@oberlies: Depende do contexto. Não há regras rígidas e rápidas, apenas práticas recomendadas. Sempre existem exceções à regra e ela deve significar o que você espera que ela signifique. No exemplo acima: GET http://example.com/dogspode retornar meta informações sobre os cães (não a lista em si, mas meta informações sobre a lista de cães). Talvez ou talvez seja um erro.
Martin York
11
As the last character within a URI’s path, a forward slash (/) adds no semantic value and may cause confusion. It’s better to drop them completely.Este não é o único lugar que sugerem a não usar barra de treinamento
LAIV
@ Laiv Não discordo do sentimento. Mas, por favor, vincule uma referência mais autorizada (que é um elo fraco).
Martin York
17
Does anyone know the definitive answer?

Não existe um, pois não existe um documento oficial sobre o que é necessário para um serviço ser considerado RESTful.

Dito isto, eu permitiria a barra final simplesmente para facilitar o uso. Enquanto tecnicamente falando, isso pode ser visto como uma tentativa de acessar um cão com um ID nulo; Não vejo um usuário fazendo esse salto, a menos que o tenha lido na sua documentação. Posso ver um usuário tentando escrever código na sua API e incluindo a barra à direita simplesmente por hábito e me perguntando por que eles recebem uma resposta 404 quando desejam uma lista de cães.

Mike
fonte
E o DELETE example.com/dogs ?
Benjamin Gruenbaum
Como cães é o pai de todos os cães individuais, a exclusão de cães excluirá todos os cães individuais e ele próprio. Se você não fizer isso, seu hipermídia vai quebrar
Gaz_Edge
@Gaz_Edge: No REST example.com/dogsé um recurso completamente independente de qualquer recurso example.com/dogs/X. Portanto, um DELETE on example.com/dogsnão precisa excluir todos os cães / * (embora possa ser essa semântica). Mas DELETE example.com/dogs/deve excluir todos os cães / *.
Martin York
3
Eu diria mais uma vez que, como não há um conjunto definitivo de regras sobre o que é RESTful, o que acontece quando você EXCLUI / dogs ou / dogs / seria baseado no que você espera que os consumidores de sua API esperem. É provável que eles realmente desejem excluir todos os cães com uma única solicitação? Em caso afirmativo, implemente-o assim, caso contrário, dê uma resposta 405 Método não permitido.
14553 Mike
11
Eu sei que esse é um tópico antigo, mas recentemente estive me perguntando sobre isso. Por que vale a pena, o OS X shell bash trata foo, foo/e foo////de forma idêntica. Basicamente, parece remover segmentos de caminho vazios. Portanto, se você seguir a mesma abordagem com o serviço REST dogse dogs/se referir à mesma coisa.
Greg Brown
2

Dois caminhos.

Método 1

Sempre use barras finais para qualquer recurso que possa conter filhos.

Considere "GET" em um diretório public_html com arquivos.

Não é possível quando hello.html é um arquivo:

/hello.html
/hello.html/youagain.html

Mas possível quando hello.html for um diretório:

/hello.html/     (actually /hello.html/index.html)
/hello.html/youagain.html

Portanto, se "hello.html" puder ter filhos, será sempre e para sempre "/hello.html/" e "/hello.html/index.html" (ou simplesmente /hello.html/) é uma lista desses filhos .

Método 2

Seja esperto".

$ find
.
./hello.html
./hello.html/index.html

O comando find não se importa com o tipo de hello.html. Diretório ou arquivo, quem se importa, é o nome de um objeto. Quando escrevemos "cp youagain.html hello.html", o cp pode descobrir como lidar com hello.html. cp é inteligente. Seu servidor da web também é inteligente. Possui uma biblioteca de manipulação de caminhos. Tem roteamento. Ele pode declarar e informar se um nome é um objeto ou um diretório. Ele pode redirecionar blá para blá / ou até mesmo servir a mesma resposta para ambos. Este é o incrível !!! maneira. Tanta tecnologia. Quem iria querer simplesmente concatenar cadeias de caminho quando pudéssemos fazer tudo isso ???

Samuel Danielson
fonte