A rest api should be entered with no prior knowledge beyond the intial uri and set of standardized media types that are appropriate for the intended audience. From that point on, all application state transitions must be driven by client selection of server-provided choices that are present in the received representations or implied by the user's manipulation of those representations. The transition may be limited by the client's knowledge of media types and resource communication mechanisms, both of which may be improved on-the-fly.
Roy Fielding
REST: "Representational state transfer"
HATEOAS: "Hypermedia as the engine of application state"
Richardson's Maturity Model
- Level 0: POX (Plain Old Xml)
- Level 1: Resources
- Level 2: HTTP Verbs
- Level 3: Hypermedia (REST)
Misconception Forces: Network reliability, Latency, Bandwidth, Security, Network topology, Administration, Transport cost, Heterogeneous network, Complexity
Constraints: Client-Server, Stateless, Cache, Uniform Interface, Layered System, Code-On-Demand (optional)
Components: Origin server, User agent, Gateway, Proxy
Connectors: Client, Server, Cache, Resolver, Tunnel
Mapping Concepts to Entities
A resource should be a concept and only the mappings should change over time.
eg. /children /children/youngest /children/oldest /children/grace /children/sarah /children/abigail
Resource Types
- document: a singular noun should be used for document names. eg. .../leagues/seattle
- collection: a plural noun should be used for collection names. eg. .../leagues
- store: a plural noun should be used for store names. eg. .../users/1234/favorites/alonso
- controller: a verb or verb phrase should be used for controller names and the controllername should be as last segment in the uri path. eg. .../alerts/1234/resend
Resource Identifier
An aesthetically pleasing rest api design is a must have feature.
uri = scheme :// authority / path ? Query # fragment
- / in path must indicate a hierarchical relationship between resources
- A trailing forward slash should not be included in uris (do you hear this chrome?)
- Use hyphens - to improve readability
- Do not use underscores
- Lowercase letters should be preferred in uri paths.
- Case different in path then not same resource
- File extensions should not be included in uris
- The full domain name of an api should add a subdomain named api eg. http://api.somesite.be
- Client developer portal at http://developer.somesite.be
- Subpaths should be addressable
- Variable path segments may be substituted with identity based values
- Crud function names should not be used in uris
- The query component of a uri may be used to filter collections or stores, preferably using OData
- The query component should be used to paginate collection or store result using OData (read this wordpress)
- If needed a separated method can be assigned eg. Post /users/search + body + cacheheaders
Http Methods
GET
- Templated
- Get and post must not be used to tunnel other request methods.
- Get must be used to retrieve a representation of a resource
- Clients count on being able to repeat get requests without causing side effects
HEAD
- Head should be used to retrieve response headers.
PUT
- Idempotent (will return seem result over and over)
- The uri identifies the entity enclosed with the request
- Put must be used to both insert and update a stored resource.
- Put must be used to update mutable resources.
POST
- Non-Idempotent, the uri identifies the resource that will handle the enclosed entity
- Post must be used to create a new resource in a collection
- Post must be used to execute controllers
DELETE
- Delete must be used to remove a resource from its parent
- Soft deletes should use a post, delete should result in 404 afterwards.
OPTIONS
- Options should be used to retrieve metadata that describes a resources available interactions.
Response Status Codes
see http status codes explained
Http headers & Control Data
- Content type must be used.
- Content length should be used.
- Last modified should be used in responses.
- Etag should be used in responses. eg. if-none-match: "etag-guid"
- Stores must support conditional put requests. If unmodified since or if match headers.
- Location must be used to specify the uri of a newly created resource.
- Cache control, expires and date response headers should be used to encourage caching. Max age value in seconds. eg. Cache-Control: max-age=86400
- Expires and datetime for legacy
- Cache control, expires and pragma should be used to discourage caching. eg. Cache-control no-cache no-store pragma: no-cache expires:0
- Caching should be encouraged even by using a small max-age
- Set expiration headers in responses of succesful get and head requests
- Post is cacheble but most will not treat it that way
- Expiration caching headers may optionally be used with 3xx and 4xx responses. Known as negative caching reducing the amount of redirecting and error triggering
- Custom http headers must not.be used to change the behavior of http methods
Representational Design
A resource can have multiple available representations. Content negotiation is the process of selecting the best representation of a resource.
eg. Accept: application/json Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8 Accept-
Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
- Json should be supported for resource representation
- Json must be well formated
- Xml and other formats may optionally be used for resource representation
- Additional envelopes must not be created
Media types aka mime types
Type / subtype *(; parameter )
- application, audio, image, message, model, multipart, text, video
- Registering media types: IANA allows anyone to propose a new media type
- Vender specific media types. eg. Application/vnd.ms-excel
- Application specific media types should be used.
- The uri of a resource type current schema version always identifies the concept of the most recent version. A uri that ends with a number represents that version.
- Media type negotiation should be supported when multiple representations are available.
- Media type selection using a query parameter may be supported. eg. Get /bookmarks/mike?accept=application/xml Instead of using extentions in the uri.
Hypermedia
Coupling is reduced by reducing the number of URLs that the client needs to know about single entry point url
<a href="root/children/grace" rel="child">foo</a>
<form class="newchild" action="children" method="post"></form>
Types of Links
<img> - Embedded
<a> - Outbound
Example of a RESTful Service
Bug Tracking Workflow
What does the sticky note look like? What does the board look like?
Title, Description, Initials, State Icons
Backlog, Working, QA, Done + Icons
Allow to change service workflow without changing the client workflow.
List the requirements
(discover bugs, add new bugs, activate a bug, complete a bug)
Identify the state transitions
(client should be able to transition to all states + navigation and error states)
Identify the resources
/bugs - entry point (GET navigate and add new bug)
/bugs/backlog (GET fetch list of bugs POST add new bug to backlog)
/bugs/working (GET fetch POST activate a bug)
/bugs/done (GET fetch POST complete a bug)
Design the media type
Base format: XML, JSON, HTML, ...
State transfer: read only, predefined, ad-hoc
Domain style: specific, general (ATOM), agnostic (HTML)
Application flow: None, Intrinsic, Applied (using decorators rel and class)
We choose: HTML, Ad-Hoc, Agnostic, Applied
Need elements for: List of bugs, link template for moving a bug to backlog, ...
Mapping to Base Format
eg. id bugs DIV container for bugs state elements, class all UL list of bugs, ...
Add a sample representation (here a markup)
eg. class="move active next"
Before versioned service URIs look like: http://foo/services/v2/bla.svc
Now: versioning within representation, representation, resource
Use content negotiation to version media types
accept:text/vnd.howard.bugs.v1+html
RESTfull Clients
Runtime vs Development time
- Study the media type and sample documents
- Request entry point resource
- Inspect representation
- Write client code
- Follow links
navigationElements = _document.XPathSelectElements("//div[@id='{0}']/a", BugsMediaTypeConstatns.ID_LINKS)
CLOUD
- From kapital to operational expenditureIncrease resources should increase performance
- Operational efficiency
- Resilient to failure (spread the risk around)
- Realizes economy of scale
- Cost per unit goes down as the number of units goes up
- Cost goes down when requests by second goes up
Opportunities
Cloud overflow / failover : start on premise or go from one cloud to the other
Auto-tuning : etags, cache, representation inlining
More