Upgrade to Pro — share decks privately, control downloads, hide ads and more …

For the REST of US

For the REST of US

The largest implementation of REST as described by Roy Fielding is the internet - that thing that we use every day. Even with all of the information out there on this useful tool, as developers we often struggle to get API design and architecture "right."

This deck focuses on how to avoid being a Restafarian and focus on how to design an API with the developer in mind while still sticking to RFC 2616 (since all implementations are left up to serendipity). It covers the high topics such as what does a domain model look like in REST, making elegant and repeatable requests to make happy devs even more happy, to the deep opinion topics such as pluralization and URI versioning of your API.

Nick Floyd

June 03, 2012
Tweet

More Decks by Nick Floyd

Other Decks in Programming

Transcript

  1. All REST interactions are stateless But what about storing information

    about the consumer or application that will help the implementation & the developer? 1. Is it secure? 2. Does it break the fundamentals? 3. Does it help the dev? Sunday, June 3, 12
  2. How do I represent this in an API? THINK about

    your DOMAIN Sunday, June 3, 12
  3. THINK about your DOMAIN /GetProducts /GetPriceForProducts /GetESRBRatingForGame /UpdateProduct /CreateProduct /CreateProductComment

    /AddProductScreenshot /UpdateProductDetails /ListCategories /DeleteProduct /AddProductReview Sunday, June 3, 12
  4. THINK about your DOMAIN /GetProducts /GetPriceForProducts /GetESRBRatingForGame /UpdateProduct /CreateProduct /CreateProductComment

    /AddProductScreenshot /UpdateProductDetails /ListCategories /DeleteProduct /AddProductReview Negative..., those interfaces are essentially trash in a REST API Sunday, June 3, 12
  5. THINK about your DOMAIN /GetProducts /GetPriceForProducts /GetESRBRatingForGame /UpdateProduct /CreateProduct /CreateProductComment

    /AddProductScreenshot /UpdateProductDetails /ListCategories /DeleteProduct /AddProductReview Leave the verbs to HTTP & keep them out of your URIs Negative..., those interfaces are essentially trash in a REST API Sunday, June 3, 12
  6. THINK about URIs Action HTTP Method URI Description List GET

    [resource] Gets a collection Show GET [resource]/[id] Gets a single resource Edit GET [resource]/[id]/edit Gets a form to edit resources identified by id Delete GET [resource]/[id]/delete Deletes the resource identified by id (LOW) New GET [resource]/new Gets form to a create a new resource Create POST [resource] Creates the new resource Update PUT [resource]/[id] Updates the resource identified by id Update POST [resource]/[id] Updates the resource identified by id (LOW) Destroy DELETE [resource]/[id] Deletes the resource identified by id Sunday, June 3, 12
  7. Action HTTP Method URI Description Index GET [resource] Gets a

    collection Show GET [resource]/[id] Gets a single resource Edit GET [resource]/[id]/edit Gets a form to edit resources identified by id Delete GET [resource]/[id]/delete Deletes the resource identified by id (LOW) New GET [resource]/new Gets form to a create a new resource Create POST [resource] Creates the new resource Update PUT [resource]/[id] Updates the resource identified by id Update POST [resource]/[id] Updates the resource identified by id (LOW) Destroy DELETE [resource]/[id] Deletes the resource identified by id POST | GET | PUT | DELETE = CRUD THINK about URIs Sunday, June 3, 12
  8. Action HTTP Method URI Description List GET [resource] Gets a

    collection Show GET [resource]/[id] Gets a single resource Edit GET [resource]/[id]/edit Gets a form to edit resources identified by id Delete GET [resource]/[id]/delete Deletes the resource identified by id (LOW) New GET [resource]/new Gets form to a create a new resource Create POST [resource] Creates the new resource Update PUT [resource]/[id] Updates the resource identified by id Update POST [resource]/[id] Updates the resource identified by id (LOW) Destroy DELETE [resource]/[id] Deletes the resource identified by id Low REST = Your language isn’t awesome enough, but we still love you enough to support it. THINK about URIs Sunday, June 3, 12
  9. Action HTTP Method URI Description List GET [resource] Gets a

    collection Show GET [resource]/[id] Gets a single resource Edit GET [resource]/[id]/edit Gets a form to edit resources identified by id Delete GET [resource]/[id]/delete Deletes the resource identified by id (LOW) New GET [resource]/new Gets form to a create a new resource Create POST [resource] Creates the new resource Update PUT [resource]/[id] Updates the resource identified by id Update POST [resource]/[id] Updates the resource identified by id (LOW) Destroy DELETE [resource]/[id] Deletes the resource identified by id “Helper” URIs = hey you’re thinking about your consumers again! Thanks! THINK about URIs Sunday, June 3, 12
  10. All you “really” need is the 4 HTTP verbs and

    2 URIs URI GET POST PUT DELTE /products Gets a list Creates a new resource Throws 400 or 405 Deletes all /products/123 Gets a single Throws 400 or 405 Updates resource Deletes single THINK about URIs Sunday, June 3, 12
  11. Use pluralized nouns (Semantically it just feels / sounds right

    ) Twillio REST API /2010-04-01/Accounts/{AccountSid} /2010-04-01/Accounts/{AccountSid}/OutgoingCallerIds/{OutgoingCallerIdSid} /2010-04-01/Accounts/{AccountSid}/Calls/{CallSid} HopToad Airbrake /errors/1000.xml /errors/1000/notices/3456789.xml /projects/55/deploys.xml Fellowship One /v1/Households/{householdID}/People /v1/People/{personID}/Addresses THINK about URIs Sunday, June 3, 12
  12. THINK about URIs Avoid abstract naming Don’t name a resource

    an item if it is really a product Sunday, June 3, 12
  13. THINK about URIs Avoid abstract naming Embrace shallow routes(2 deep

    - opinion ) Don’t name a resource an “thing” if it is really a “product” Sunday, June 3, 12
  14. THINK about URIs Avoid abstract naming Don’t name a resource

    an “thing” if it is really a “product” Embrace shallow routes(2 deep - opinion ) Search and other terse operations Sunday, June 3, 12
  15. Status codes Take note of when to return a body

    & when not to HTTP/1.1 200 OK Content-Length: 29265 HTTP/1.1 204 NO CONTENT Content-Length: 0 Sunday, June 3, 12
  16. Status codes Use the code in combination with the headers

    (x. 405 should return a response header accept ) 405 Example - [POST] products/1/manufacturers <- an attempt to create a manufacturer when only GET is available HTTP/1.1 405 NOT ALLOWED ACCEPT: GET Sunday, June 3, 12
  17. Status codes Implement more than just the basics (200, 400,

    500 ) 201 - Resource created [POST] ▪ Response Header - Location will contain the canonical URI ▪ Entity body - the new resource ▪ Example - [POST] Products 204 - No Content [DELETE] ▪ Response Header - Response message will contain the canonical URI of the resource that has been deleted ▪ Entity body - will be empty ▪ Example - [DELETE] /Products/1636208/Comments/29717636 301 - Moved Permanently ▪ Response Header - Location will contain the new permanent canonical URI ▪ Entity body - will be empty ▪ Example - [GET] Products/1 has been merged and no longer exists the new URI is Products/2 Sunday, June 3, 12
  18. Status codes Have fun with them. (Remember if your consumers

    are getting anything other than a 200 they will be in a frustrated frame of mind ) Sunday, June 3, 12
  19. Headers Always use content-location & location headers (when appropriate) Content-Location

    : absoluteURI | relativeURI Example - Content-Location : http://api/v1/Products/22114944 Notes - Sent back with each GET request Location : absoluteURI Example - Location: http://api/v1/Products/22114944 Notes - Applies to 201 and 301 only Sunday, June 3, 12
  20. Headers Use COMPRESSION & support the top 3 Content-Encoding :

    content-coding Example - Content-Encoding : gzip Notes - This will tell the client what type of compression was used on the resource Return values - deflate, compress, gzip Sunday, June 3, 12
  21. Headers Use the ACCEPT header Accept : type/subtype Example -

    Accept : application/xml Notes - Defaults to application/xml if one is not passed in, and when a user sends application/* the resulting content sub type will be XML. Multiple types/sub types can be sent in but as per the specification the first match in degree of specificity will be the first used. i.e. if user sends in: application/*, application/xml, / the order would be as follows: 1. application/xml 2. application/* 3. */* Sunday, June 3, 12
  22. The fringe, the edge & the like Warning: this is

    a high opinion zone Sunday, June 3, 12
  23. Versioning Use simple URI based versioning • Get the version

    as close to your domain pointer as possible • Use v syntax with no major / minor dot notation Why? • Most readable • Defines an explicit scope • Slightly deviates from REST and HATEOAS (watch yourself restifarian) Ex. https://t.restapi.com/v1/products/345 https://t.restapi.com/v2/products/345 Sunday, June 3, 12
  24. Resources Use simple resource structures Ex. { "product": { "@id":

    "22114941", "@uri": "https://t.restapi.com/v1/products/345", }} https://t.restapi.com/v1/products/345 { "product": { "@id": "22114941", "@uri": "https://t.restapi.com/v1/products/345", "comments": [{ "@id": "1", "@uri": "https://t.restapi.com/v1/products/comments/1", "comment": "Best product ever!" }] }} https://t.restapi.com/v1/products/345?include=comments • Resource expanded response Sunday, June 3, 12
  25. Resources Use simple resource structures • Resource partial response (google)

    Ex. { "product": { "@id": "345", "@name": "Hitchhikers Guide to REST APIs" }} https://t.restapi.com/v1/products/345?fields=id, name { "product": { "@id": "345", "@name": "Hitchhikers Guide to REST APIs", "@desc": "Hitchhikers Guide to REST APIs book on how awesome REST APIs can be!", }} https://t.restapi.com/v1/products/345?fields=id, name, desc Sunday, June 3, 12
  26. Resource formats • If possible choose one to start with

    then expand to others • Implement at least json & xml (json first) - but it depends on your consumer base • Simplify your interface by using file extensions on your URIs (.json, .xml) Sunday, June 3, 12
  27. Resource formats - paging & counts HTTP/1.1 200 OK Cache-Control:

    private Content-Type: application/json; charset=utf-8 Server: Microsoft-IIS/7.0 X-AspNetMvc-Version: 1.0 X-AspNet-Version: 2.0.50727 X-Powered-By: ASP.NET Date: Fri, 01 May 2009 20:59:11 GMT Content-Length: 54997 { ! "@count": "20" "@pageNumber": "1", "@totalRecords": "908", "@additionalPages": "45", "products": [ { "@id": "1635797", "@uri": "https://t.api.com/v1/products/1635797", "@name": "Nick's book" ! ! ! }! ! ! ! { "@id": "1635798", "@uri": "https://t.api.com/v1/products/1635798", ! "@name": "Another book from the mad-cap mind of Nick" ! ! ! } ! ! ! ... ! ! ] } Sunday, June 3, 12
  28. Consumer flair • Build test harnesses for your consumers to

    use to verify an implementation • Override behavior such as auth switches, response code hooks & build in help • Provide client libs for the top languages • Create a dev community site (dev.site.com, developer.site.com, so on) Sunday, June 3, 12
  29. More on REST Post on review of tech for REST

    APIs http://bit.ly/ac_rest_tech Roy Fielding dissertation http://bit.ly/fielding_dissertation RFC2616 http://www.w3.org/Protocols/rfc2616/rfc2616.html Developing a REST based web service http://bit.ly/floyd_rest_article @nickfloyd | nickfl[email protected] Sunday, June 3, 12