I have been having a debate about what to do with a trailing slash in a RESTful API.
Lets say I have a resource called dogs and subordinate resources for individual dogs. We can therefore do the following:
GET/PUT/POST/DELETE http://example.com/dogs
GET/PUT/POST/DELETE http://example.com/dogs/{id}
But what do we do with the following special case:
GET/PUT/POST/DELETE http://example.com/dogs/
My personal view is that this is saying send a request to an individual dog resource with id = null
. I think the API should return a 404 for this case.
Others say the request is accessing the dogs resource i.e. the trailing slash is ignored.
Does anyone know the definitive answer?
3 Answers 3
None of this is authoritative (as REST has no exact meaning). But from the original paper on REST a full (not ending in /) URL names a resource, while one ending in a slash '/' is a resource group (probably not worded like that).
A GET of a URL with a slash on the end is supposed to list the resources available.
GET http://example.com/dogs/ /* List all the dogs resources */
A PUT on a URL with a slash is supposed to replace all the resources.
PUT http://example.com/dogs/ /* Replace all the dogs resources */
A DELETE on a URL with a slash is supposed to delete all the resources
DELETE http://example.com/dogs/ /* Deletes all the dogs resources */
A POST on a URL with a slash is supposed to create a new resource can then be subsequently accessed. To be conformant the new resource should be in this directory (though lots of RESTful architectures cheat here).
POST http://example.com/dogs/ /* Creates a new dogs resource (notice singular) */
etc.
The Wikipedia page on the subject seems to explain it well: https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services.
-
1It also fits the normal path/url model, where directories are often written with a trailing
/
CodesInChaos– CodesInChaos2013年02月13日 18:41:13 +00:00Commented Feb 13, 2013 at 18:41 -
5So what should happen if you access a resource group without the trailing
/
?oberlies– oberlies2013年07月03日 12:21:15 +00:00Commented Jul 3, 2013 at 12:21 -
1@oberlies: It depends on context. There are no hard and fast rules only best practices. There are always expcetions to the rule and it should mean what you expect it to mean. In the example above:
GET http://example.com/dogs
may return meta information about the dogs (not the list itself but meta information about the list of dogs). Maybe or maybe its an error.Loki Astari– Loki Astari2013年07月03日 19:09:49 +00:00Commented Jul 3, 2013 at 19:09 -
2
-
@Laiv I don't disagree with the sentiment. But please link a more authoritative reference (that's a weak link).Loki Astari– Loki Astari2017年08月28日 23:11:14 +00:00Commented Aug 28, 2017 at 23:11
Does anyone know the definitive answer?
There isn't one as there isn't an official document on what is required for a service to be considered RESTful.
That said I would allow the trailing slash simply for ease of use. While technically speaking this could be seen as attempting to access a dog with a null ID; I do not see a user making this jump unless they have read it in your documentation. I can see a user attempting to write code against your API and including the trailing slash simply from habit and wondering why they get a 404 response when they want a list of dogs.
-
What about DELETE example.com/dogs ?Benjamin Gruenbaum– Benjamin Gruenbaum2013年02月13日 13:21:26 +00:00Commented Feb 13, 2013 at 13:21
-
since dogs is the parent of all individual dogs, deleting dogs will delete all individual dogs and itself. If you don't do that, your hypermedia will break downGWed– GWed2013年02月13日 13:54:14 +00:00Commented Feb 13, 2013 at 13:54
-
@Gaz_Edge: In REST
example.com/dogs
is a resource completely independent of any resourceexample.com/dogs/X
. Thus a DELETE onexample.com/dogs
does not have to delete all the dogs/* (though it can if that is the semantics). But DELETEexample.com/dogs/
should delete all the dogs/*.Loki Astari– Loki Astari2013年02月13日 18:41:11 +00:00Commented Feb 13, 2013 at 18:41 -
3I would say once again that since there isn't a definitive set of rules on what is RESTful what happens when you DELETE /dogs or /dogs/ would be based on what you expect the consumers of your API to expect. Is it likely that they would actually want to delete all dogs with a single request? If so then implement it like that, if not then give a 405 Method Not Allowed response.Mike– Mike2013年02月14日 13:19:42 +00:00Commented Feb 14, 2013 at 13:19
-
1I know this is an old thread, but I've recently been wondering about this myself. For what it's worth, the OS X Bash shell treats
foo
,foo/
, andfoo////
identically. It basically seems to strip out empty path segments. So, if you follow the same approach with your REST service,dogs
anddogs/
would refer to the same thing.Greg Brown– Greg Brown2016年06月17日 20:06:12 +00:00Commented Jun 17, 2016 at 20:06
Two ways.
Method 1
Always use trailing slashes for any resource that may contain children.
Just consider "GET" on a public_html directory with files.
Not possible when hello.html is a file:
/hello.html
/hello.html/youagain.html
But possible when hello.html is a directory:
/hello.html/ (actually /hello.html/index.html)
/hello.html/youagain.html
So if "hello.html" can ever have children then it is always and forevermore "/hello.html/" and "/hello.html/index.html" (or simply /hello.html/) is a listing of these children.
Method 2
Be "smart".
$ find
.
./hello.html
./hello.html/index.html
The find command doesn't care about the type of hello.html. Directory or file, who cares, it is the name of an object. When we write "cp youagain.html hello.html", cp can figure out how to handle hello.html. cp is smart. Your webserver is smart too. It has a path handling library. It has routing. It can stat and tell you if a name is an object or a directory. It can redirect blah to blah/ or even just serve up the same response for both. This is the awesome!!! way. So much tech. Who'd ever want to simply concatenate path strings when we could do all that???
dogs
anddogs/
as equivalent. For me it's clear thatdogs/
is a directory containing the individual dogs. Its less clear whatdogs
is, but I'd treat it as equivalent, just like most webservers accept accesses to directories without the trailing/
.