IT:AD:REST
Background
- Stands for
REpresentational State Transfer
- Attributed to Roy Fielding's doctoral dissertation in 2000.
- Six Constraints:
- Client/Server
- SOC: Client doesn't concern itself with storage, etc.
- Stateless.
- No server state. Only Client State.
- Cacheable
- Clients can cache resources, per server' instructions on its staleness.
- Layered system
- Code on demand (optional)
- Uniform interface; resource identifier (e.g URL) , methods (e.g. GET, POST), media types (e.g. XML, JSON)
* -
Use HTTP Verbs instead of Subjective Operation Names
The crux of it all is mostly:
- HTTP already defines Verbs: GET|PUT|POST|DELETE, etc.
- Whereas RPC, WCF, etc. encourage the invention of arbitrary Operation names (getUsers(), saveNewUser(), deleteUser(x), (both of which are using POST, rather than POST and DELETE….)
- This additive operations name is reinventing is the issue. Instead of inventing arbitrary names, change the method.
Therefore, move your Operation Names out of the Url, and move them to the Http Verb.
COMMON MISTAKE: do not confuse with Http Form POST verb, which is used to process data as seen, as not RESTful.
Protocol
- REST is an architecture, not a protocol (like SOAP).
- So it doesn't dictate XML|JSON|etc.
- Content-Negotiation is generally handled via
Accepts
header.
Browser Support
Support PUT and DELETE:
- Desktop:
- IE7+ (notably, IE6 = NO)
- FF3+
- Safari
- Opera
- Mobile
- Non-conclusive as to what fails: http://bit.ly/IVKVJl
- -
Concepts:Friendly Urls
There's often a common miscomprehension that
http://localhost/client/1002/invoice/13
is a RESTful url. It isn't. It's just a friendly url.
What makes it RESTful is:
0. unique resource url, and 0. the changing of the VERB.
Urls in REST are unique addresses of Resources. If they are friendly/pretty, that's all the better.
Concepts: REST Resources
Resources are usually Domain objects.
- Business Domain Objects:
* Services (remember, you don't have to implement all verbs)
- http://localhost/cacheService/someKey (POST|PUT|GET|DELETE)
- -
Then again, maybe those friendly urls could be expressed as :
- http://localhost/service/cache/someKey (POST|PUT|GET|DELETE)
Hum…
Concepts: REST Resource IDs
The resource ids are urls, which are are unique network (read “server”, above) resource identifiers, that hide implementation.
In other words, an Invoice Domain Entity may have a unique DBMS Identifier of
12 (an implementation issue),
but that is not to be confused with the unique Network Identifier:
`http://localhost/client/234/invoice/123`
Note: A check is that we do not talk about INVOICE 123, but about RESOURCE http://localhost/client/234/invoice/123
Concepts: Idempotency
- As per HTTP 1.1 specification, GET, HEAD, PUT and DELETE are idempotent, POST is not.
- You can repeat the Idempotent operations (HEAD, GET, PUT, and DELETE) over and over again, and you get back the same results.
- POST you cannot.
- Hence why when the browser, when you back up/forward prompts with a warning before resubmitting the post.
- -
VERB + Friendly Url = Unique Id Examples
Retrieve: GET
- List:
http://localhost/client/234/invoice/
http://localhost/client/234/invoice/page/3/
http://localhost/client/234/invoice/page/3/records/20
http://localhost/client/234/invoice/16-24
http://localhost/client/234/invoice/16/to/24
http://localhost/client/234/invoice/id/16/to/24
http://localhost/client/234/invoice/date/gt/2010-01-01
- etc.
- Item:
http://localhost/client/234/invoice/112
* Responses:
- 200: OK
- HTTP 401 Unauthorized (ie, Not Authenticated). See why: http://stackoverflow.com/a/6937030/1052767
- HTTP 403 Forbidden (ie, Not Authorized). See why: http://stackoverflow.com/a/6937030/1052767
- 404: Not found
Create: POST
- List:
- N/A
* Item:
http://localhost/client/234/invoice/
- Note: Response contains Id of new Resource (eg:
http://localhost/client/234/invoice/209
)
- Responses:
- HTTP 201: Created+ Location Header defining GET resource address.
- AVOID 302: OK. PRG Pattern is a Browser pattern, not REST.
- Although the following link suggests using it as 302 Found (ie, can't create new record).
- AVOID 409: Although tempting to use for “Conflict - record exists”, it implies the user can do something to unconflict it. But that's not the case for Create.
- Yet…it is used here: https://groups.google.com/forum/#!topic/api-craft/zs88tpXzyD0
- HTTP 401 Unauthorized (ie, Not Authenticated). See why: http://stackoverflow.com/a/6937030/1052767
- HTTP 403: Forbidden (ie, Not Authorized). See why: http://stackoverflow.com/a/6937030/1052767
- HTTP 50x: Server errors - try again.
HEAD
Same as GET but just headers.
Update: PUT
* List:
- Update a range of records with common settings.
* Item:
- Update a single record.
- Convention is that it creates a record at the Id, if none exists. But throw an Exception.
http://localhost/client/234/invoice/112
- Note: creates a new one with given id, or replaces existing one.
* Response:
- HTTP 200 (OK), with content depending on the method, or
- HTTP 202 (Accepted)
- HTTP 201 (Created). Maybe…but I wouldn't recommend this as it obfuscates POST mechanism.
- HTTP 204 (No Content) Resource Updated Successfully.
- HTTP 304 (Content not Modified). No changes?
- HTTP 401 Unauthorized (ie, Not Authenticated). See why: http://stackoverflow.com/a/6937030/1052767
- HTTP 403 Forbidden (ie, Not Authorized). See why: http://stackoverflow.com/a/6937030/1052767
- HTTP 404 (Not found) . No record to update.
Delete: DELETE
* List:
- Delete a range of Records
http://localhost/client/234/invoice/date/lt/2010-01-01
- etc.
* Item:
http://localhost/client/234/invoice/112
- HTTP 200 (OK), with content depending on the method, or
- HTTP 202 (Accepted) could be used to imply 'marked for deletion', or
- HTTP 204 (No Content) Resource Updated Successfully.
- HTTP 401 Unauthorized (ie, Not Authenticated). See why: http://stackoverflow.com/a/6937030/1052767
- HTTP 403 Forbidden (ie, Not Authorized). See why: http://stackoverflow.com/a/6937030/1052767
- HTTP 404 Resource not found.
Concepts: PRG: Post - Redirect - Get
After POSTing a new record to http://localhost/invoice/
(ie, Create), the server sends back a Redirect code of 302, which tells the browser to GET the new invoice at http://localhost/invoice/1023
PUT doesn't need the same method as the invoice id is in the url.
Security
- REST is Stateless.
- Therefore, authentication has to be sent each and every time (unlike straight WCF, which could have State if so desired).
FAQ
- If the operation is suppossed to leave you always in the same state, what does doubling a DELETE do? Error second time? Say fine again?
- It's not a Browser request, so doesn't need a page response, just an Ack code.
* Not sure if DELETE should redirect to the the list.
- Same: It's not a Browser request, so doesn't need a page response, just an Ack code.
Pitfalls
Where REST is not that great is batch changes.
Examples might be:
- Update the Status of all Students Where Age < 14
You have to think of the UpdateStudentStatus
Operation as a StudentStatusUpdate
Resource that can only be PUT'ed with a StudentStatusUpdate object (the filter). I agree it's less intuitive and verbose. But it is also specific, and fits well into SOC Principles.
Resources
- Concepts:
- -
- How do I raise Exceptions that JQuery can use:
- How do I get rid of the .svc? * http://bit.ly/iVq3F0 References: