79

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?

5
  • 2
    I thought the RESTful way was to distinguish between dog/id and dogs (meaning all dogs).
    – pdr
    Feb 13, 2013 at 12:54
  • From the book RESTful Web Services - subordinate resources: resources that exist in relation to some other “parent” resource i.e. dogs/{id} A web-enabled database may expose a table as a resource, and the individual database rows as its subordinate resources.
    – GWed
    Feb 13, 2013 at 13:04
  • It is accessing the dog resource, the trailing slash should be ignored which means it should get a forbidden response for trying to delete something that delete should not be applied to. I guess that 404 is also acceptable. Does it matter though? Feb 13, 2013 at 13:18
  • I don't follow - who said you can't delete dogs? If you delete dogs it deletes itself and all the individual dogs. That's why i think allowing calls to dogs/ is risky. What if the client meant to delete an individual dog, but accidentally left off the {id}. The result would be that all dogs would be deleted. Much safer to assume it is asking for {id} null and return 404
    – GWed
    Feb 13, 2013 at 14:12
  • I'd treat dogs and dogs/ as equivalent. For me it's clear that dogs/ is a directory containing the individual dogs. Its less clear what dogs is, but I'd treat it as equivalent, just like most webservers accept accesses to directories without the trailing /. Feb 13, 2013 at 18:44

3 Answers 3

62

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.

6
  • 1
    It also fits the normal path/url model, where directories are often written with a trailing / Feb 13, 2013 at 18:41
  • 5
    So what should happen if you access a resource group without the trailing /?
    – oberlies
    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. Jul 3, 2013 at 19:09
  • 2
    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. This's not the only place that suggest to don't use training slash
    – Laiv
    Aug 28, 2017 at 22:49
  • @Laiv I don't disagree with the sentiment. But please link a more authoritative reference (that's a weak link). Aug 28, 2017 at 23:11
18
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.

8
  • What about DELETE example.com/dogs ? 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 down
    – GWed
    Feb 13, 2013 at 13:54
  • @Gaz_Edge: In REST example.com/dogs is a resource completely independent of any resource example.com/dogs/X. Thus a DELETE on example.com/dogs does not have to delete all the dogs/* (though it can if that is the semantics). But DELETE example.com/dogs/ should delete all the dogs/*. Feb 13, 2013 at 18:41
  • 3
    I 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
    Feb 14, 2013 at 13:19
  • 1
    I 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/, and foo//// identically. It basically seems to strip out empty path segments. So, if you follow the same approach with your REST service, dogs and dogs/ would refer to the same thing.
    – Greg Brown
    Jun 17, 2016 at 20:06
2

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???

Not the answer you're looking for? Browse other questions tagged or ask your own question.