rest/urls: Difference between revisions

From Microformats Wiki
Jump to navigation Jump to search
m (en-US)
m (Added note on/link to Atompub)
 
(44 intermediate revisions by 7 users not shown)
Line 1: Line 1:
= URL Conventions =
= URL Conventions =


The Simply Restful plugin for Rails, which will soon become part of Rails Core, has gone with the following scheme:
These are the recommended conventions for [http://bitworking.org/news/How_to_create_a_REST_Protocol RESTful] [http://www.softiesonrails.com/2007/4/10/rest-101-part-3-just-call-me-the-repo-man URLs], based on work pioneered by [http://topfunky.com/clients/peepcode/REST-cheatsheet.pdf Ruby on Rails], which again is closely modelled over [http://www.ietf.org/rfc/rfc5023.txt Atompub] . Following these conventions for both HTTP method names and URL construction will allow your application to be consumed by ActiveResource,  Jester, and other RESTful clients. Note that Rails 1.x used ";edit" and ";new" in place of the simpler "/edit" and "/new" recommended going forward.


/people
== Methods ==
/people/1
One of the key aspects of REST is using the [http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html HTTP Verbs] to implement the standard Create-Retrieve-Update-Delete ([http://en.wikipedia.org/wiki/Create%2C_read%2C_update_and_delete CRUD]) database semantics. The primary ones are:


We recommend that other implementations follow the same conventions, since that is the first concrete example of such explicitly RESTful URLs in the wild.
;POST:'''C'''reate a resource within a given collection
;GET:'''R'''etrieve a resource
;PUT:'''U'''pdate a resource
;DELETE:'''D'''elete a resource


Most browsers do not currently support PUT and DELETE (HTML forms only allow "get" and "post", links are always "get").  The other methods can be emulated by providing a "method" parameter with a value of "PUT" and "DELETE", respectively.


= ARCHIVE =
== Routing ==
The principal unit of operation is the "collection", which typically corresponds to a database table or (in Rails) an ActiveRecord class.
For a collection named "people", the primary routes would be:


There is nothing that says you must organise resources hierarchically,
=== Operate on the Collection ===
although many people prefer to do so. There are advantages to separating
;GET /people: return a list of all records
your containment hierarchies from your components. It makes it trivial
;GET /people/new: return a form for creating a new record
to add new containers and the containers can accept search parameters.
;POST /people: submit fields for creating a new record


== Example URLs ==
=== Operate on a Record ===


You could organise your URIs like this:
;GET /people/1: return the first record
;DELETE /people/1: destroy the first record
;POST /people/1?_method=DELETE: alias for DELETE, to compensate for browser limitations


* The second widget
;GET /people/1/edit: return a form to edit the first record
http://example.org/widget/2
;PUT /people/1: submit fields for updating the first record
;POST /people/1?_method=PUT: alias for PUT, to compensate for browser limitations


* A form describing how to create a widget
=== Follow a Relationship ===
http://example.org/widget


* The list of the first N (say N=25) widgets
;GET /people/1/phones: return the collection of phone numbers associated with the first person
http://example.org/widgets
;GET /people/1/phones/23: return the phone number with id #23 associated with the first person
;GET /people/1/phones/new: return a form for creating a new phone number for the first person
;POST /people/1/phones/: submit fields for creating a new phone number for the first person


* The list of the next N widgets starting at 26
=== Invoke Custom Actions ===
  http://example.org/widgets/26
It isn't always possible to map ''everything'' into CRUD. Thus, there is also a syntax for specifying custom actions:
;POST /people/1/promote: run the "promote" action against the first record
These should be used sparingly, as they are unlikely to be supported by most clients.


== Example Actions ==
== File Formats ==  


Then consider a sequence of hypertext style actions:
Data types are extremely important in REST.  While it is ideal to specify the appropriate [http://en.wikipedia.org/wiki/Internet_media_type MIME type] as an HTTP header, developers are encouraged to follow Rails in allowing extension-based typing, e.g.:


* Retrieve a list of widgets
=== HTML ===
GET http://example.org/widgets
;GET /people/1: return the first record in HTML format
;GET /people/1.html: return the first record in HTML format
=== XML ===
;GET /people/1.xml: return the first record in [http://en.wikipedia.org/wiki/XML XML] format
=== JSON ===
;GET /people/1.json: return the first record in [http://en.wikipedia.org/wiki/JSON JSON] format


* Retrieve details of the second one
While the JSON mapping should be trivially obvious, the best practice for XML is to:
GET  http://example.org/widget/2
# use the column name as the element name
# include an appropriate "type" field


* Replace some of the details
See the [http://developer.37signals.com/highrise/reference.shtml Highrise reference] for an example of how this works in practice.
POST  http://example.org/widget/2


* Retrieve a form (resource parameter decription)
== Response Codes ==
* or whatever you want to call it, for creating widgets
Another important aspect of REST is returning the appropriate [http://en.wikipedia.org/wiki/List_of_HTTP_status_codes HTTP Response Codes]. Some common ones are:
GET http://example.org/widget
=== Successful ===
;200 OK: The request has succeeded.
;201 Created: The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field.
;204 No Content: The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.
=== Redirection ===
;303 See Other:The response to the request can be found under a different URI and SHOULD be retrieved using a GET method on that resource. This method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource.


* Create a new widget
=== Client Error ===
POST  http://example.org/widget
;400 Bad Request: The request could not be understood by the server due to malformed syntax.
<= LOCATION: //example.org/widget/123
;401 Unauthorized: The request requires user authentication. The response MUST include a WWW-Authenticate header field ([http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 14.47]) containing a challenge applicable to the requested resource.
;404 Not Found: The requested resource could not be found([http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5 section 10.4.5]).
;405 Method Not Allowed: The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested resource.
; 422 Unprocessable Entity: The server understands the media type of the request entity, but was unable to process the contained instructions.


* Get the new widget
= Examples in the Wild =
  GET  http://example.org/widget/123
== Ruby ==
* [http://guides.rubyonrails.org/routing_outside_in.html Ruby on Rails]
* [http://developer.37signals.com/highrise/ Highrise]


* Delete the Widget
== PHP ==
DELETE  http://example.org/widget/123


== Notes ==
* [http://github.com/shuber/restful_rails/tree/master RestfulRails] An extendable PHP library to communicate with RESTful rails applications


This organisation is similar to that of the rest-discuss
== Perl ==
html interface. But you cannot use PUT, POST and DELETE in
that interface.


Using the  http://example.org/widget URI for creating new widgets is
* [http://dev.catalyst.perl.org/wiki/crud/crud_and_rest Catalyst CRUD and REST]
similar to the Prototype design pattern while still adhering to the
expected behavior of a POST, ie. create a subordinate resource.


Whatever you do, be sure to ''tell'' clients what structure they use, so they don't have to guess
== Java ==
(which would violated HTTP [[rest/opacity]].
* [http://weblogs.java.net/blog/bleonard/archive/2007/08/rails_to_java_v.html Java]
== Python ==
* [http://routes.groovie.org/manual.html#restful-services  Python Routes]
* [http://pylonshq.com/docs/module-pylons.decorators.rest.html Pylons REST Decorators]
 
== JavaScript ==
* [http://giantrobots.thoughtbot.com/2007/4/2/jester-javascriptian-rest Jester] (JavaScript)
* [http://code.google.com/p/dom-resource/ DOM-Resource] (JavaScript)
* ....

Latest revision as of 12:28, 7 May 2009

URL Conventions

These are the recommended conventions for RESTful URLs, based on work pioneered by Ruby on Rails, which again is closely modelled over Atompub . Following these conventions for both HTTP method names and URL construction will allow your application to be consumed by ActiveResource, Jester, and other RESTful clients. Note that Rails 1.x used ";edit" and ";new" in place of the simpler "/edit" and "/new" recommended going forward.

Methods

One of the key aspects of REST is using the HTTP Verbs to implement the standard Create-Retrieve-Update-Delete (CRUD) database semantics. The primary ones are:

POST
Create a resource within a given collection
GET
Retrieve a resource
PUT
Update a resource
DELETE
Delete a resource

Most browsers do not currently support PUT and DELETE (HTML forms only allow "get" and "post", links are always "get"). The other methods can be emulated by providing a "method" parameter with a value of "PUT" and "DELETE", respectively.

Routing

The principal unit of operation is the "collection", which typically corresponds to a database table or (in Rails) an ActiveRecord class. For a collection named "people", the primary routes would be:

Operate on the Collection

GET /people
return a list of all records
GET /people/new
return a form for creating a new record
POST /people
submit fields for creating a new record

Operate on a Record

GET /people/1
return the first record
DELETE /people/1
destroy the first record
POST /people/1?_method=DELETE
alias for DELETE, to compensate for browser limitations
GET /people/1/edit
return a form to edit the first record
PUT /people/1
submit fields for updating the first record
POST /people/1?_method=PUT
alias for PUT, to compensate for browser limitations

Follow a Relationship

GET /people/1/phones
return the collection of phone numbers associated with the first person
GET /people/1/phones/23
return the phone number with id #23 associated with the first person
GET /people/1/phones/new
return a form for creating a new phone number for the first person
POST /people/1/phones/
submit fields for creating a new phone number for the first person

Invoke Custom Actions

It isn't always possible to map everything into CRUD. Thus, there is also a syntax for specifying custom actions:

POST /people/1/promote
run the "promote" action against the first record

These should be used sparingly, as they are unlikely to be supported by most clients.

File Formats

Data types are extremely important in REST. While it is ideal to specify the appropriate MIME type as an HTTP header, developers are encouraged to follow Rails in allowing extension-based typing, e.g.:

HTML

GET /people/1
return the first record in HTML format
GET /people/1.html
return the first record in HTML format

XML

GET /people/1.xml
return the first record in XML format

JSON

GET /people/1.json
return the first record in JSON format

While the JSON mapping should be trivially obvious, the best practice for XML is to:

  1. use the column name as the element name
  2. include an appropriate "type" field

See the Highrise reference for an example of how this works in practice.

Response Codes

Another important aspect of REST is returning the appropriate HTTP Response Codes. Some common ones are:

Successful

200 OK
The request has succeeded.
201 Created
The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field.
204 No Content
The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.

Redirection

303 See Other
The response to the request can be found under a different URI and SHOULD be retrieved using a GET method on that resource. This method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource.

Client Error

400 Bad Request
The request could not be understood by the server due to malformed syntax.
401 Unauthorized
The request requires user authentication. The response MUST include a WWW-Authenticate header field (14.47) containing a challenge applicable to the requested resource.
404 Not Found
The requested resource could not be found(section 10.4.5).
405 Method Not Allowed
The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested resource.
422 Unprocessable Entity
The server understands the media type of the request entity, but was unable to process the contained instructions.

Examples in the Wild

Ruby

PHP

  • RestfulRails An extendable PHP library to communicate with RESTful rails applications

Perl

Java

Python

JavaScript