REST-ful URI Design _ 2PartsMagic Blog
-
Upload
george-mejia -
Category
Documents
-
view
223 -
download
0
Transcript of REST-ful URI Design _ 2PartsMagic Blog
-
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
1/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 1
REST-ful URI design
This post is about URI naming. Designing URI names. Some tips and rules and conventions that you can follow when figuring
out your applications URIs. The focus is on URIs for REST-ful applications. But many of the tips apply to any kind of
website or application.
REST-ful URIs and non-REST-ful URIs
A REST-ful URI is a URI that identifies a domain resource (like a book or a shelf or a book loan in a library application) rather
than an application resource (like a web page or a form in your application or website).
Typically REST-ful URIs are for APIs. For programmers. But in many cases they will serve just as well for a regular
website.
non-REST-ful URIs are more likely to identify application resources like web pages rather than domain resources:
/admin/updatebook.jsp?book=5
/bookview.jsp?book=5
/bookandreviews.jsp?book=5
PS: There can be confusion about URIs and URLs (and URNs!). To get a URL just tack on a server (example.com) and a
protocol (http or ftp) to a URI (/example): http://example.com/example. The URI identifies the resource. And a URL adds som
information about how to get it.
URIs do not matter with REST-ful applications
This is what some people say. See the comments below. But is not true: URIs do matter. URI design matters. And URI
design for REST-ful applications matters even more.
The reason is that REST-ful apps are all about domain resources (like books and shelves and loans in a library application) rathe
than application resources (like forms to reserve a book or pages displaying a book or who has loaned what).
With REST-ful applications the first thing you need to do is to identify the resources you are representing in your system. And
URI-design is all about how you can consistently name every one of those resources.
What are the criteria for a good REST-ful URI?
I assert a good REST-ful URI is:
Short (as possible). This makes them easy to write down or spell or remember.
Hackable up the tree. The user should be able to remove the leaf path and get an expected page back. e.g.
2PartsMagic BlogBlogging web software development
2PartsMagic REST-ful URI design About 2PartsMagic
http://2partsmagic.com/http://blog.2partsmagic.com/restful-uri-design/http://blog.2partsmagic.com/about/http://blog.2partsmagic.com/http://blog.2partsmagic.com/about/http://blog.2partsmagic.com/restful-uri-design/http://2partsmagic.com/http://blog.2partsmagic.com/ -
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
2/17
-
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
3/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 3
Good URIs improve your site usability.
Readable URIs increase your search engine traffic. People actually see and read URLs in Googles search results. And the
are more likely to go to a page if the name of the page matches what they are looking for.
How good URI design improves usability
Users can find their way around more easily when there are good URIs. They have a chance of getting themselves unstuck
inside the site structure. e.g. if they are at /conversations/conversation-10/todo-list-12 they can easily enough pop up to
/conversations where all the current conversations are displayed.
A good programmer looking at well designed URIs in a REST-ful API should be able to visualize your API merely by knowing
some of the URLs.
Non-REST-ful URLs
I have always aimed to create decent urls. In non-REST-ful apps they would be good solid urls like:
http://rimuhosting.com/ticket/startticket.jsp
https://pingability.com/cp/register.jsp
http://rimuhosting.com/order/startorder1.jsp?type=2&t-vps
Typically when there is a different kind of page I create an JSP for that page. And the page name will reflect whatever is
happening on that page.
Non-REST-ful URIs are fine, they are just non-REST-ful.
This post is nota debate about which is better out of REST-ful and non-REST-ful URIs. This post is about what makes a good
REST-ful URI. If your URI is non-REST-ful it is simply non-REST-ful, and I make no claim that it is good or bad.
REST-ful URIsThe RedRata team has recently started trying to create an application and we would like it to be a REST-ful application.
REST-ful applications do not implement a specification (like SOAP, or XML-RPC, or ATOM). There is no validation service th
will tell me if my REST-ful application is REST 1.0 compliant. There is no REST 1.0 BTW.
Instead REST-ful applications are applications that follow REST-ful conventions.
And there are conventions around what makes a REST-ful URI.
Ive found that coming up with REST-ful URIs that I, and others, think follows proper REST-ful conventions is difficult.
But the difficulty comes because of the importance of good URI design. Not so much that it follows some convention that a
bunch of technologists have come up with. But because it improves end user usability.
Examples of (possibly) REST-ful URIs
In a quickly-recognizable-as-REST-ful app we would possibly have URLs like. e.g.
http://rimuhosting.com/users/user-9/contact-details
http://rimuhosting.com/planstype=vps to show VPS plans
http://rimuhosting.com/plans/plan-miro2b to show the MIRO2B plan. Aside: this redrata.com WordPress blog runs on a
RimuHosting Miro2 plan.
http://rimuhosting.com/order/startorder1.jsp?type=2&t-vpshttps://pingability.com/cp/register.jsphttp://rimuhosting.com/ticket/startticket.jsphttp://www.useit.com/alertbox/990321.html -
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
4/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 4
http://rimuhosting.com/carts/cart-2/server-1 a server plan added to the cart, in preparation of checkout
5 developers an infinite selection of URLs chaos ensues
I came up with those sample URLs just now. If I were to come up with the same resources tomorrow would that list look the
same? What if another developer in my team attempted the same task?
Would the names be similar? Would we argue endlessly about which was the better way? Would there be any concrete guideline
on which we could select one set over another? Would we even be aware of the URI design importance to worry? Would usabilissues and development chaos ensue?
How to decide on which template or conventions do you use? How do you get everyone on the same page? How can you make
so two developers independently adding a new resource to the app would use the same or similar URI?
In order to try and get some consistency over how we design urls in RedRata REST-ful apps we have tried to come up with a
convention for us to use. That convention and a discussion of the alternatives follows.
Nouns, not verbs
REST-ish URLs identify resources. Nouns. They tell you what they are.
REST-ful URIs should not tell you what they do. No getPlan. Nor start-order.
The do comes when you apply a verb an HTTP method to the URL. e.g. a HTTP PUT to a URI means update that resource.
DELETE means to delete it. A POST typically means create something for me (e.g. a new order, or a shopping cart).
Stateless URIs
An example. On RimuHosting we have some long running operations. e.g. when we move a VPS from one host server across th
globe to a different data center. So we create a move status URL and give it a status id. And then we use Ajax to keep pushing
updates to that URL. Or the user can reload the page.
There is a problem. That URL only works for that user on that session. They could not bookmark it, go home, and see it at home
They cannot send it to a colleague and say Keep an eye on this move for me.
Good URIs (REST-ful or otherwise) should be stateless. If I am looking at a document I should be able to share that URL with
someone and they should be able to access the same resource.
What they see may differ from what I see. e.g. since I may be logged in as an admin on a site and see a few more options than
they do as a guest. But this is just a different representation of the same resource. Or they may even get a not authorized
response if they are a guest, or a logged in user without the authority to see the resource.
To get a stateless URI avoid reliance on session attributes. Transient things. If you need to store something, store it in a database
(where database is probably some SQL database, but anything that is accessible by someone with a different session ID will do)
Examples:
Hey, have I got all the things you needed in my shopping cart? A URL of http://example.com/shoppingcart would not be
something that the other person could easily see. If the URI was http://example.com/shoppingcarts/cart-12 then it could
potentially be visible (e.g. if you had set a public flag on the cart, or if you and a colleague had a login each to a purchasing
account on example.com).
Example:
Hey, what address do I need to set on my account? If the url is http://example.com/address then it likely represents the address
of the currently logged in person. And what I will see (my address) is a different resource from what you will see (your address)
-
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
5/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 5
Same type of resource (address). Different instance: mine vs. yours.
In this case consider a URI design of http://example.com/users/user-9/address.
Then it is clear that we are talking about the address of a specific person. Whether you can see my address is a different matter.
Stateless URLs can improve scalability
A beneficial side effect of stateless URIs, where you avoid storing attributes associated with a session is that your application cascale across hardware more easily. As it will not matter, or matter as much if they shift from one web server to another since the
URLs they see do no depend on some session state. e.g. worst case scenario they may just need to re-log in. To re-establish the
identity.
Personal URLs
There is value having a URI like http://example.com/contact-details (meaning my contact details). Or preferably something tha
indicates it belongs to the current user, like, http://example.com/users/user-me/contact-details.
e.g. you may have a static page that wants to link to the users contact details. And at the time you show the page they may not b
logged in.
In that case http://example.com/users/user-me/contact-details could prompt for a login. Or if the user is logged in they the page
could redirect to URL like, say, http://example.com/users/user-9-peter/contact-details
The redirect in this case is important. Since the page on which the user ends up is their contact details resource. Whereas
http://example.com/users/user-me/contact-details is a resource to findyour contact details location.
Summary: if a resource is context sensitive (e.g. to a current user) create a separate resource finder URL. Make it clear that
resource URI is context sensitive (e.g. including words like me or my in it). And have that resource redirect to the actual resourc
when it is used.
Further example: http://example.com/forecasts/cambridge/today redirects to, say, http://example.com/forecasts/cambridge/2009-
04-26
Extension or no extension
If you use JSP then your files probably have a .jsp extension. And similarly for PHP and other apps. In an ideal world the
technology you use on the back end should not force its way into the users face.
Some sites have a .en URI for an English version of the content and a different URI with a .fr extension for a French localized
version of the page. Would it not be better if a user could go to http://example.com/aboutus and get the page in their preferred
language. And then share that URL with someone else who sees it in their own language?
Some applications return different data if the user adds a different extension. e.g. they may ask for contacts.xml or contacts.json
But different URIs imply different resources. Are the two data formats really two different resources? Or just two different
representations of the same resource.
With HTTP there are other ways you can negotiate content. e.g. via the Accept header.
I assert that REST-ful URIs should identify a single resource. And different representations of that resource can be negotiated.
e.g. via HTTP headers. I assert that things like language localizations, data formats, read only views, HTML forms, summary
views, detail views, etc, are all just different representations of the same resource. I assert developers should work to keep all
those representations on the same URI.
I assert that we avoid extensions to indicate the representation of the resource.
-
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
6/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 6
Using Accept HTTP request headers to negotiate views.
Having all representations of a resource on a single URI can be a tricky task for developers to pull off. It requires having a lot of
control over receipt/dispatch of HTTP requests. And full and easy control of HTTP request and response headers. Not to mentio
being able to serve up different human and machine languages and views for resources.
Standard ways to negotiate the representation of a resource:
Accept: text/html will return a full web page with site navigation and other linksAccept-Language to control the localization of the resource between different human languages.
Accept: application/xml and application/json to get back data in these popular formats.
Standard Accept headers break down with some view types
But how do you negotiate other representations like a summary read only view of a resource /customer-9summary? Or a detail
view /customer-9?detail=Y. Or a form to edit that person: /customer-9/edit
These are introducing new URIs (suggesting these are therefore different resources). Yet I am asserting that these things are
mere representations of the same resource, not different resources.
But how else to solve the problem? These are all HTML pages (for argument sake). And weve only got the one text/html media
type.
Or have we?
Using vendor specific Accept headers
Instead, RedRata will be trialing a method to leave the URIs alone and just use a different Accept header for the odd/particular
representations we need. We will be using vnd vendor specific, made-up media types.
The RedRata vendor specific Accept types
RedRata uses the {type}/vnd.{company}{type}+{subtype} convention.
e.g. text/vnd.redrata.summary+html application/vnd.redrata.deep+json.
We will be using those types to differentiate between, say a regular Accept: text/html (returning a page with the resource and all
the site navigation) and say the following:
Accept: text/vnd.redrata.summary+html returns, say, a HTML div element containing a read only summary of a resource.
e.g. for a person maybe just their name. Or name and email. But not all their details: like address, phone, notes.
Accept: text/vnd.redrata.detail+html the full detail for, say, a person. But it would exclude the fluff like site navigation,
ads, and other things not directly related to the person resource.
Accept: text/vnd.redrata.edit+html returns, say, a HTML div element containing a form element for editing the resource.
With the form pre-populated with the resources current settings.
Accept: application/vnd.redrata.deep+json for a deep copy of a resources JSON and all its sub-resources. i.e. grabbing
everything in one HTTP request
Accept: application/vnd.redrata.shallow+json for a shallow copy of a resources JSON (excluding any sub-resources). i.e.
grabbing everything in one HTTP request
Accept: application/vnd.redrata.shallow+xml and application/vnd.redrata.deep+xml work the same way, but for XML
I am not aware of anyone else using this Accept approach with vnd (vendor-specific) media types.
If you think the approach makes sense, please use it in your apps and help make our non-conventional approach more
-
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
7/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 7
conventional. Heck, we may even go so far as to register those media types.
More available views of a resource => more usable API
One of the goals RedRata has is that the applications we create with our REST-ful APIs will be easily embedded into our
customers sites. e.g. with a quick Javascript/ajax call to yank a bit of information out of our app.
By offering a variety of views (in HTML and JSON/XML) we have a better chance of being able to return something most
suitable for our customers and users.
Do cool URIs ever change?
W3.org asserts that cool URIs do not change.
I assert that seems a good guideline in most cases.
Balance that against:
Keeping things backwards compatible adds extra effort.
Application resource structures change. And that should naturally cause URIs to change so they better reflect reality.
We can improve our URIs over time.
Good REST-ful applications should represent their state in their representations. For example by providing hyperlinks to
other resources. A good REST-ful application should be fully navigable to anyone if they start at the / URI.
If google can follow links on your site to get to the content, then the user will likely be able to find it again. 99% of the
pages I need to get back to I get back to by searching for content on that page/resource. Particularly when I remember th
domain it was on and I can slap a site:example.com into my google query.
URIs dobreak. It is just a fact of life. People, and web services cope. No one or no service should expect to rely on
unchanging URLs and get away with it for to long.
To avoid URIs-that-change as much as possible consider keeping changeable/variable information out of the URI. e.g. Avoid
using a users username in their home page URL if that username can change. Rather use something that will not change. e.g. a
database id.
More readable URIs using unique-id-plus-redundant-information (UPRI)
How do you balance URIs-that-dont-change (implemented using unique, immutable database ids) with nice readable URIs (wher
the readable bit for example a username or a conversation- or blog-post-subject is liable to change?
Consider using the database id plus some other redundant info (like a username or name). The redundant information is not
necessary to find the resource. If you have the unique, immutable id, like the database id, then you do not care about the other bi
in the URI.
e.g. /conversations/conversation-9-how-do-i-change-billing-details
Canonical urls: coping with different URIs for the same resource
With the unique-id-plus-redundant-information (UPRI) approach you could end up with different URIs for the same thing. And
that is not ideal.
In the case of different URIs pointing to the same resource (e.g. when you are using unique, immutable ids plus redundant bits
you should consider indicating in your response the canonical or preferred link for that resource.
You can do this inside HTMLs HEADs REL tag. Or in HTTP response headers. Using Location, Content-Location or Link
http://www.w3.org/Provider/Style/URIhttp://www.ietf.org/rfc/rfc4288.txt?number=4288 -
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
8/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 8
e.g. see Googles post on specifying canonical URLs or Mark Nottinghams Link header proposal. See also Ben Ramseys cool
URIs dont change post.
Redirects/Locations work, but who wants the HTTP latency overhead? Plus if you use a pretty URI that then goes straight to a
different location (and changes the browser address bar) then no one will get to appreciate your pretty, readable URI. And they
will likely feel less inclined to love it and bookmark it and tell their friends on social network websites about it.
Browser urls are user interface (UI)
URLs that appear in the browser address bar are part of the UI (user interaction). They MUST be hackable.
So any path used in a browser youd expect to produce a decent HTML page all the way up the tree. e.g. youd want there to b
no 404s. Nor any access denieds.
The digging-deeper-path-and-backspace convention
General rule: if you are on a page and you are clicking into an item on that page, drilling down into more detail on that item,
then the we would generally just add the extra path segment to the original URI. e.g. from conversation page to todo list item
would be /conversations/conversation-1 becomes /conversations/conversation-1/todo-list-5. Thus you can go back to where you
were by removing the end path segment.
General rule (rephrased): If you are clicking down a resource heirarchy (e.g from conversations to conversation to conversation
item to ) the back key SHOULD be the same in most cases as removing the URLs last path segment.
Similarly if you are on /conversations/conversation-1 and you click on the all todo lists in this conversation link you could end
up on /conversations/conversation-1/todo-lists. From there you click on a particular todo list. In this case you get to
/conversations/conversation-1/todo-lists/todo-list-5 . You can remove the last and end back up on the page you had come from,
satisfying the digging-deeper-path-and-backspace rule. But note that /conversations/conversation-1/todo-lists/todo-list-5 and
/conversations/conversation-1/todo-list-5 will point to the same resource. So you would want to use the HTML or response
headers to indicate the canonical url.
Putting our URI design thoughts into practice
The first step in URI design is to identify your resources. In the examples here we will be talking about a hypothetical applicatio
that manages conversations. OK, its not hypothetical. It is an actual application we are building. And this is the actual
document where we try to figure out what our URIs are going to look like.
The main resources/things in our application are conversations. Each conversation can have one or more conversation items like
message going back or forth or a todo list or a status update. And some of the conversation items can have collections of other
resources. e.g. a todo list can have a number of associated todo items.
Choosing a URI schemes for resource hierarchiesLet us look at what URIs we could use to represent our conversation-related resources.
plural-root-plus-singular-root: e.g. /conversations and /conversation/{id}
/conversations : all conversations
/conversation/{id} : a specific conversation (note singular not plural)
Cons: You cant hack the url. If you remove the id you get /conversation and not the list of conversations you were
expecting/hoping for (which is at /conversations)
http://benramsey.com/tag/cool-uris-dont-change/http://tools.ietf.org/html/draft-nottingham-http-link-header-04http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=139394 -
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
9/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 9
plural-singular-id: e.g. /conversations/conversation/{id}
/conversations : all conversations
/conversations/conversation/{id} : a specific conversation
Issue: what is the page at /conversations/conversation going to show? Do you want a page there? If you do not have a page th
made sense to show there then that URI is not really hackable.
Issue: it is kinda long
plural-id: e.g. /conversations/{id}
/conversations : all conversations
/conversations/{id} : a specific conversation
Pro: vs. option plural-root-plus-singular-root you can remove bits from the path and work up the ownership heirarchy
Cons: If you wanted to use a url like /conversations/new then youd need to be able to dissambiguate a conversation like
/conversations/5431. e.g. if all your conversation ids are numbers then this could work well. Else youd need to avoid naming
collisions in case you ever had a conversation id of new. If this could be the case you may be better off using the plural-name-
and-id template.
Option plural-id-id-id /conversations/{id}/{id}/{id}
What about when you have deeply nested resources?
/conversations : all conversations
/conversations/{id} : a specific conversation
/conversations/{id}/{id} : a specific conversation item
/conversations/{id}/{id}/{id} : e.g. a todo item on a todo list on a particular conversation
Disadvantage: with deeply nested hierarchies you lose meaning about what each path is
plural-name-id-name-id-name-id: e.g. /conversations/conversation/{id}/todo-lists/{id}/todos/{id}
/conversations/conversation/{id}/todo-lists/{id}/todos/{id} : e.g. a todo item on a todo list on a particular conversation
Advantage: you know what each id means.
Disadvantage: If you expose /conversations/conversation/{id}/todo-lists/{id}/todos/{id} in a browser url bar, then youd need to
support having a UI for having each part of that directory tree. e.g. /conversations/conversation/{id}/todo-lists/{id}/todos you
may want to do that, if so fine. Else if you dont want to provide a UI for that there would be an issue. e.g. user gets error page
Meaning the URI is not so hackable.
Option plural-name-and-id /conversations/conversation-{id}
/conversations : all conversations
/conversations/conversation-{id} : a specific conversation
Pros: similar to plural-id.
plural-name-and-id-name-and-id-name-and-id: e.g. /conversations/conversation-{id}/todo-list-{id}/todo-
-
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
10/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 10
{id}
We extend the plural-name-and-id for nested and deeply nested resources.
/conversations : all conversations
/conversations/conversation-{id} : a specific conversation
/conversations/conversation-{id}/todo-list-{id}/todo-{id} : e.g. a todo item on a todo list on a particular conversation
Advantages: hacking the url by removing a path will give you the todolist, the whole conversation, or a set of conversations
At RedRata we are opting to use this plural-name-and-id template for nested resources.
/conversations/conversation-{id}/todo-list-{id}/todo-{id} : e.g. a todo item on a todo list on a particular conversation. And if you
remove the last path you get /conversations/conversation-{id}/todo-list-{id}, the todo list and all its items. And if you remove th
last path from that you get /conversations/conversation-{id} the conversation.
In this example, there is no user interface to the URL to get an individual conversation item. Why not? Well what if we dont
want to provide that page? The resource exists. We just dont want a user to go there and get a hey, no content we want to show
you for this page message
Of course we may change our minds later on and want to have a page available that shows just a single conversation item. i.e. a
single message in a conversation. In that case we can expose a url like (just a slash has been added):
/conversations/conversation-{id}/todo-list-{id}/todo-{id}
name-plus-id-plus-redundant: e.g. /conversations/conversation-9-where-is-apache-installed
We can convert the unique, but opaque, /conversation/conversation-{id} to the just as permanent but more readable
/conversation/conversation-{id}-{subject}
We do the database lookup based on the id. We ignore the subject (as that could change over time).
On our response we indicate the canonical resource e.g. /conversation/conversation-{id}.
Pros: user friendly, permanent URI
Cons: a bit long, a bit of extra work to respond with the canonical resource location.
Sample URLs for the RedRata commapp
Hackable urls:
/conversations/conversation-{id}/todo-list-{id}/todo-{id}
/conversations/conversation-{id}/message-{id}
/conversations/conversation-{id}/email-{id}
/conversations/conversation-{id}/messages
/conversations/conversation-{id}/messages/message-{id}/conversations/conversation-{id}/message-new for creating new messages. After the message is created it will have an id. And
the url will be the same except the new becomes the id. Nice and neat.
Creating resources
Creating new resourcess (when that resources parent does not exist yet) presents a particular challenge with REST-ful
applications.
The REST-ful policing squads will knock on your door if you overtly offer verbs in your urls. Like /conversations/create-new-
conversation. That is seen as exposing a process not a resource. You could always have your defense lawyer argue the process i
-
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
11/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 11
the resource, I suppose.
You couldsend a HTTP POST to a URI like /conversations to create a resource with. But that could be ambiguous. What would
that create? A conversation? What if other things lived under conversations? Like staff? Or audit logs? Or billable hours?
Here are some examples of URIs we could use instead:
/conversations/conversatation-{id}/message-new existing conversation create message
/conversations/message-new create a new message and while we are at it it would also create a new conversation in which to
put it.
These URIs would return information (e.g. an HTML form, or a prototype JSON/XML representation on a HTTP GET). And
would create the new resource on a HTTP POST.
Here are some URIs we would likely notuse:
/conversations/conversatation-new/message-new implies /conversations/conversatation-new creates a new converstation. But
that isnt something we want to allow them to do. i.e. this URI is hackable in a way we do not want it to be
/conversations/conversatation/message-new implies the same as /conversations/message-new but if we had nothing to show at
/conversations/conversatation then this url would be hackable in a bad way.
Direct URLs vs. hackable URLs
With most deeply nested resources if you have the resources ID you can probably figure out the objects that own it up the tree
In this case you can have short/simple/direct urls like:
/conversation-{id}
/message-{id}
e.g. same resource:
/conversations/conversation-{id}/messages/message-{id} (which implies there is a meaningful page at
/conversations/conversation-{id}/messages, say one that listed all messages cf. todo lists, for a conversation)
/conversations/conversation-{id}/message-{id}
/message-{id}
These direct URLs may be easy/quick/handy for programmers. e.g. the makers of the REST-ful service, or developers using theREST-ful service as a client.
They are not easily hackable by end users. e.g. you cannot go from that direct url to the containing resource. So do not use them
in where you would need a hackable/discoverable/end-user-editable url.
As usual when there is a choice of URIs for a single resource select your canonical URI and report it in your response.
Some RedRata conventions
The main url is /conversations/conversation-{id}
There MAY be a link on individual conversation items. e.g. that goes to /conversations/conversation-{id}/message-{id}
IF you have a page that shows a list of message type items in a conversation have /conversations/conversation-{id}/messages
IF you click from that page to an individual page then that pages url SHOULD be /conversations/conversation-
{id}/messages/message-{id}
Apparently the theme I am using does not have user comments on pages, just posts, so if you have any thoughts on this page
youll need to make any comments over on this blog post.
http://addthis.com/bookmark.php?v=300http://redrata.com/2009/04/rest-ful-uri-design-verbs-vs-resource-nouns/ -
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
12/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 12
26 Comments
Greg
Posted May 30, 2012 at 10:02 | Permalink
This is a very interesting and vey good article !
I am wondering though how we can keep that nice URI design for a tree structure.
Lets say I want to manage some tasks lists. Each list can contain tasks and / or other lists (nodes and leaves in fact).
I am thinking about 3 designs :
1) /lists/{id_list1}/lists/{id_list2}/lists/{id_list3}/tasks/{id_task1}
I am afraid that such a design could lead to really long URIs if the tree has a lot of levels.
2) /lists/{id_list1}/{id_list_or_task1}/{id_list_or_task2}/{id_list_or_task3}
This one is shorter but less readable.
3) /lists/{id_list_parent}/{id_list_or_task_child}
This one is short and can describe thousands levels trees, but I feel like somethings missing
What would be your advice between these 3, or is it another smarter way ?
Danilo Recchia
Posted June 13, 2012 at 15:03 | Permalink
Great post!
j0kPosted June 18, 2012 at 05:49 | Permalink
In addition to this article, here is a really good presentation by David Zuelke about how designing http interface and restful webservice.
Pete
Posted June 18, 2012 at 08:14 | Permalink
Im going to pull a well actually here, I apologize in advance. Strictly speaking, a particular URI/URL design has little to do with REST-ful vs. Non-REST-ful. A
system can perfectly adhere to the ReST constraints with URLs like /my/moppets/a/b/cdef as long as things like statelessness, Hypermedia As The Engines Of
Application State (HATEOAS), etc as observed.
A good URL design certainly helps with SEO, human user URL changes like finding the parent collection for a particular item, but lets not conflate that with ReST.
John
Posted June 18, 2012 at 10:14 | Permalink
Theres no such thing as RESTful URIs. You may want to go back and read Roys thesis before you through around terms like that.
Michele
Posted June 18, 2012 at 11:08 | Permalink
I came across this article through twitter, had no I idea was bound to rimuhosting, of which I have been happy customer for years
Said this I must say I do not understand all this adversion for old opaque query string.
I think also that paths are hierarchical by nature while context might be not.
http://www.tenslashsix.com/http://www.slideshare.net/Wombert/designing-http-interfaces-and-restful-web-services-sfliveparis2012-20120608http://blog.wildtrip.net/ -
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
13/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 13
For example take an Employee that books a Room for a meeting, in the booking URL we need both a ref to the Employee and the Room, what would be the correct
path for this URL following your guidelines ? Would you force order on the segments ? You write about nested resources and level of nesting, but what is nested in
what, in this case ?
I think that all URL are restful and for me rest is more about sending links to change state to the clients (as usually happens in html apps but not in soap) than building
URI in some way or in an other.
Of course I might be wrong
Peter BryantPosted June 18, 2012 at 11:55 | Permalink
A restful URI identifies a resource (cf. a page, or a function or a form).
So in the case of an employee booking a meeting room the resource is the meeting (the resource is not the room or the employee).
So create a meeting with a POST to /meetings/new (with form data to identify employee, room id and time). Then view the resource at /meetings/meeting-982-john-
room5
Michele
Posted June 18, 2012 at 13:11 | Permalink
Hi Peter,
thanks for th e answer.
So if I get it well, query string is ok in this case.
My extremist old way idea was:
insertBooking.do?room=3&employee=2
yours,if I am correct, is
/bookings/new?room=3&employee=2
There is one piece of information more in your 2 segments path version that in mine is lost in the page name. Of course is much nicer your version and that piece of
information more can be used to hack the uri.
Sorry if I am long and taking the occasion of this nice article to make questions about rest-philosophy, but what I am trying to discover is this: are URI(s) written in one
or the other way really relevant for following rest architecture or are they just a plus ?
I am tempted to think they are just a plus, what i see essential instead is that the uri-represented *resource* must be a _rest-resource_, so it must expose to clients URI
representing other resources allowing client to perform state transition, then if the URIs are written in one URI syntax or the other it does not matter so much.
What you think about it, I am getting it right ?
Thanks
Michele Vivoda
David Zuelke
Posted June 19, 2012 at 03:00 | Permalink
In REST, it does not matter what your URLs look like, because all interactions are driven through links and their relations.
Or, in other words: you ve likely missed the HATEOAS/Hypermedia aspect of REST, which is the most important p art of the Uniform Interface constraint:
Also see Fieldings musings on the matter, e.g. http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
David Zuelke
Posted June 19, 2012 at 03:02 | Permalink
Also, a page or a function or a form are not resources, but merely *representations* of resources. Resources and their representations are conceptually separate. Hence
*Representational State Transfer*.
Recommended reading: REST in Practice, a really great book that step by step teaches what REST is about (Hypermedia and HATEOAS, not URIs or status codes or
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven -
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
14/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 14
headers) and shows the benefits of infrastructure that doesnt even rely on a specific structure for its URLs (REST is about distributed network applications, not about
HTTP or whatever else).
Peter Bryant
Posted June 19, 2012 at 10:58 | Permalink
+David Zuelke I agree: A REST-ful URI identifies a resource (rather than a page, or a function or a form).
This is an article about URI design. Particularly URIs that may be used in a REST-ful API. When you build REST-ful applicaitions you can often do a better job of it if
you think carefully about the design of your URIs.
Michele
Posted June 19, 2012 at 12:11 | Permalink
>In REST, it does not matter what your URLs look like, because all interactions are driven through links and their relations.
This is what I thought,is a plus. I will give a try to the book, thanks.
I read some time ago the article from Fielding, but I like to read it again from time to time, still not got it fully -).
Am I getting right that is essential that a representation of a resource in a rest architecture should provide -links- to the possible actions on the resource or related
resources (application state changes)?
Michele
Vicente Gallur Valero
Posted June 20, 2012 at 22:12 | Permalink
Great article, very interesting and well explained. The only subject I dont agree is dropping the language from the URI for resources in different languages.
I consider a translation a different resource and not a representation of the same thing in other format, as usually the translation is partial, localized, not exact, or simply
doesnt exist.
Also for practical reasons I find more useful you can link the resource in a concrete language, as it gives more control on what you want to link, and the user client may
not share any of its Accept-Languages with the resources languages. You can then provide a default language, but could be a different one the original linker wanted
to share and ending with ununderstandable content.
For PUT, POST and DELETE, altought you can specify the language on the body of the request I think it should go on the URI, as you are modifying just that language,
I see it as a different resource.
Darrel Miller
Posted June 27, 2012 at 17:16 | Permalink
and just one more time There is no such thing as a RESTful URL.
And I have found that designing by URI does not produce great results. It is much better to identify resources and the relationships between those resources. Once you
have done that, picking URIs to identify those resources is usually pretty trivial.
Sukant Hajra
Posted September 6, 2012 at 12:57 |Permalink
I believe theres some good advice in this post, but theres also unnecessary misinformation in the beginning about the difference between URIs, URLs, and URNs. I
understand that this has been a source of confusion for some time, but I think the dust is settling. Although we may still debate what these terms mean, I think we can be
more sure about what these terms do not mean.
Heres the problem. URIs are notthe tail part of a URL. URLs are a type of URI, as are URNs. URLs are designed more for resolving.
The Wikipedia page about thisis not too bad. But in case youre looking for a more official opinion, the W3 issued a nice retrospective report to help clarify the matter.
It doesnt resolve all confusion, but it does a good job acknowledging how semantics have morphed as the internet has morphed.
Daniel Halperin
http://www.halper.in/http://www.w3.org/TR/uri-clarification/http://en.wikipedia.org/wiki/Uniform_resource_identifier#Relationship_to_URL_and_URNhttp://www.vgcomunicacion.com/ -
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
15/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 15
Posted December 7, 2012 at 13:52 |Permalink
Hi Peter,
Helpful article. I wonder if you have any intuition on how the parser code for these URIs works. For instance, in JAX-RS you annotate each class and function with the
path that should call it. So the class representing a Conversation resource might be annotated with @Path("/conversations"). The function that handles an
individual conversation would be annotated with @Path("conversation-{conversationId}").
If there is an alternate URI to, e.g., /messages/message-1/conversations/conversation-1how would the annotation structures work? It would seem complicated
and error-prone to predict all possible combinations of URIs to put the same functions in every resource.
How do you design your parsers?
Peter Bryant
Posted December 7, 2012 at 14:03 |Permalink
It is probably best to avoid different paths where possible. And just use a single URI for each resource.
e.g. Id argue a conversation includes a message but not vice versa.
As far as the parsing go es I have a class per resource. For @Path annot ations I return an instance of the appropriate jaxrs class. The JAXRS class represents the resource. it
doesnt have to care about the path the user took to reach it.
Make sense?
Daniel Halperin
Posted December 8, 2012 at 08:04 |Permalink
Peter,
Thanks for the reply.
In your examples, you often have multiple ways to get to the same resource. Are you now saying that we shouldnt do that?
In any case, with a Google search inspired by your message, I found the Subresources technique described here, which seems to answer my question.
Thanks so much!
Dan
JV
Posted December 17, 2012 at 05:11 |Permalink
Hi,
Great article.
I whant to ask your opinion about URI Design.
I need to develop a REST API and I have doubts about the URI design.
Scenario:
1 Im developing one REST interface to a set of services.
2 each service is divided from the logical point of view in several parts ( not resources).
3 each resource can be accessed in two ways A and B
What is the most appropriate URI design?
/service1/part1/resource?{A|B}
/service1,part1,resource?{A|B}
espinete
Posted March 12, 2013 at 01:37 | Permalink
For separating parameters, are semicolons bet ter than ampersands?
https://cwiki.apache.org/WINK/jax-rs-resources-http-methods-and-paths.html#JAX-RSResources%252CHTTPMethods%252CandPaths-SubresourceLocatorhttp://www.halper.in/ -
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
16/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
http://blog.2partsmagic.com/restful-uri-design/ 16
Frogblatterbeast
Posted April 23, 2013 at 20:28 |Permalink
While I understand that REST isnt specific about URI design, I completely agree that good , semantic URI design is important for a good web application, just as
everyone takes it for granted that functions, classes and compilation units in traditional software engineering are given readable and descriptive names. It really doesnt
matter that much whether the URI is consumed by a human or a machine. If you spend some time thinking about your URI design, you will most certainly end up with a
better and more business-driven application design.
Doug Moscrop
Posted June 16, 2013 at 03:12 | Permalink
This is an article about URI design. Particularly URIs that may be used in a REST-ful API. When you build REST-ful applicaitions you can often do a
better job of it if you think carefully about the design of your URIs.
URI design is an oxymoron servers need to control their namespaces, and hierarchy has no meaning. I dont disagree with readable URIs, but thats purely for
human beings to muck about. From an API perspective, from a functional perspective, every resource could be mounted via some GUID and youre still as REST (or not)
as you are with well-designed URI syntax.
You should have written an article on relationship design because thats a key part of hypermedia -based state transition.
e.g. Id argue a conversation includes a message but not vice versa.
This is incredibly far off the point. Youre trying to think about your domain and your domain does not present itself directly through your API what matters is state
transition. From a representationof a given resource, what are my possible state transitions? You need to express those as hyperlinks. A conversation could be acollection-like resource of hyperlinks to individual messages. Those messages have hyperlinks too. What links? Well, thats the important part of the design. The part
you seem to have glossed over.
JohnPaul
Posted July 16, 2013 at 17:50 |Permalink
Nice information about URI naming
Caleb Cushing
Posted March 17, 2014 at 08:01 | Permalink
Im curious how Using vendor specific Accept headers has worked out? Im looking at that for a solution to thishttp://programmers.stackexchange.com/q/232556/2331
Caleb Cushing
Posted March 17, 2014 at 09:14 | Permalink
answers to this question about whether http clients check the mime type when determining to use a cached response seems relevant, if they dont then using the same uri
with differnent mime types wouldnt really work safely, as the cache should give you the same response regardless of a new mime type
http://stackoverflow.com/q/22441874/206466
Dave Schinkel
Posted April 9, 2014 at 07:50 |Permalink
@David Zuelke
Wrong, and this is the kind of half bake cowboy driven thinking that drives me crazy with some people (no offense David but I just had to say this).
This is like analogy to say we do TDD but we feel we can skip the blue step in TDD at times.
The URI matters as it ties to a RESOURCE, so its all tied into REST and in how you overall design your RESTful API. The URI tells the server what resource its
looking for and the convention MATTERSyou may do it slightly different but for the most part theres a pretty consistent pattern people follow with RESTful URIs.
What if youre coding for example ASP.NET MVC. You would want your URLs to still request resources and your route table to bind those to specific controllers for
processing. How can you do that if you dont have a pattern that promotes REST in your URL? meaning youre representing resources! (instead of RPC style).
Sure hypermedia is critical in the response but you dont take out the URI part saying its not critical or somehow doesnt relate or matter to REST.
http://code-zest.blogspot.com/http://stackoverflow.com/q/22441874/206466http://xenoterracide.com/http://programmers.stackexchange.com/q/232556/2331http://xenoterracide.com/http://www.fieldservicemanagement.org/ -
8/12/2019 REST-ful URI Design _ 2PartsMagic Blog
17/17
5/23/2014 REST-ful URI design | 2PartsMagic Blog
The 2PartsMagic writers work on the coal face of web-based-, software-as-a-service-, Java-focused developers. They work on sites like:
InboxHarmony, the collaborative email client for support teams
RimuHosting dedicated servers
RimuHosting VPS servers
Zonomi DNS hosting
Pingability website monitoring and alert service
Bakop, FTP-based o ffsite server b ackups
Blogging on customer service
2 Trackbacks
By REST-ful URI Design: verbs vs. resource nounson April 25, 2009 at 18:22
By Bra artikel o m RESTful URI:s Stacktrace.seon April 19, 2010 at 22:27
Post a Comment
Your email is neverpublished nor shared. Required fields are marked *
Name*
Email*
Website
Comment
You may use these HTML tags and attributes
Post Commen
Security Question:
What is 2 + 4 ?
IMPORTANT! To be able to proceed, you need to solve the following simple math (so we know that you are a human) :-)
http://stacktrace.se/2010/04/19/bra-artikel-om-restful-uris/http://redrata.com/2009/04/rest-ful-uri-design-verbs-vs-resource-nouns/