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

Building RESTful APIs

Hemant Kumar
September 30, 2012

Building RESTful APIs

Using REST conventions to build better APIs

Hemant Kumar

September 30, 2012
Tweet

More Decks by Hemant Kumar

Other Decks in Programming

Transcript

  1. Building better Web APIs whoami • Hemant - (AKA Ruby

    guy). • http://github.com/gnufied • http://www.codemancers.com Sunday, 30 September 12
  2. Building better Web APIs What is REST? REST is a

    software architectural style for network based application software. Sunday, 30 September 12
  3. Building better Web APIs What is REST? REST is a

    software architectural style for network based application software. Roy Fielding Sunday, 30 September 12
  4. Building better Web APIs Few important things • It is

    not a design pattern. Sunday, 30 September 12
  5. Building better Web APIs Few important things • It is

    not a design pattern. • It is not a library or framework. Sunday, 30 September 12
  6. Building better Web APIs Using HTTP to its fullest to

    interact with resources within certain Architectural constraints. Sunday, 30 September 12
  7. Building better Web APIs A web page is a “representation”

    of a resource. Loving husband to his wife Sunday, 30 September 12
  8. Building better Web APIs Resource as abstract entity Any information

    that can be named is a resource. For example - document, images. Sunday, 30 September 12
  9. Building better Web APIs REST anti-pattern • Each database model

    is turned into a Resource. Sunday, 30 September 12
  10. Building better Web APIs REST anti-pattern • Each database model

    is turned into a Resource. • Trying hard to model API after your database design. Sunday, 30 September 12
  11. Building better Web APIs Identify resources in your Application •

    Think about what your webservice provides. Sunday, 30 September 12
  12. Building better Web APIs Identify resources in your Application •

    Think about what your webservice provides. • And work backwards from that. Sunday, 30 September 12
  13. Building better Web APIs • Tight coupling with Data model.

    Why is that bad? Sunday, 30 September 12
  14. Building better Web APIs • Tight coupling with Data model.

    • You are on a slippery slope now. Why is that bad? Sunday, 30 September 12
  15. Building better Web APIs POST "/company.json" Params : { "user_attributes":

    { "name": "Hemant Kumar", "password": "password", "password_confirmation": "password", "email": "[email protected]" }, "company_attributes": { "name": "Codemancers Technologies", "address": "blah blah" } "payment_attribtutes": { "credit_card": { "number": "4242" }, "amount": "42" } } Sunday, 30 September 12
  16. Building better Web APIs What was wrong? • Any guesses

    why creating a company via API required so many parameters? Sunday, 30 September 12
  17. Building better Web APIs What was wrong? • Any guesses

    why creating a company via API required so many parameters? • Not clear we are dealing with which “resource” exactly there. Sunday, 30 September 12
  18. Building better Web APIs def create @company = Company.new(params[:company]) respond_to

    do |format| format.html { if @company.save ... else ... end } format.json { if @company.save .... else ... end } end end HTML request JSON request Sunday, 30 September 12
  19. Building better Web APIs Sadly it is still RESTful architecture

    for many Rails developers. Sunday, 30 September 12
  20. Building better Web APIs REST Anti-Pattern A REST API must

    not define fixed resource names or hierarchies (an obvious coupling of client and server). Sunday, 30 September 12
  21. Building better Web APIs REST Anti-Pattern A REST API must

    not define fixed resource names or hierarchies (an obvious coupling of client and server). /users/1/posts/1/comments.json Sunday, 30 September 12
  22. Building better Web APIs Recap • Identify resources to expose.

    • Expose the workflow not the data model. Sunday, 30 September 12
  23. Building better Web APIs • GET • POST • PUT

    • DELETE Sunday, 30 September 12
  24. Building better Web APIs # API for posts @app.route('/',methods =

    'GET') def index(): .. @app.route('/', methods = 'POST') def create(): .. @app.route('/post/<int:post_id>', methods = 'PUT') def update(): .. @app.route('/post/<int:post_id>', methods = 'DELETE') def destroy(): .. Sunday, 30 September 12
  25. Building better Web APIs How do I do this in

    Ruby? Sunday, 30 September 12
  26. Building better Web APIs resources :devices do get do #

    /devices/1 .. end post do # /devices .. end put do # /devices/1 .. end delete do # /devices/1 .. end end https://github.com/intridea/grape Sunday, 30 September 12
  27. Building better Web APIs So what is the big fuss

    about verbs? Sunday, 30 September 12
  28. Building better Web APIs GET • Anything that is safe.

    Does not have side effects. Sunday, 30 September 12
  29. Building better Web APIs GET • Anything that is safe.

    Does not have side effects. • Can be cached, bookmarked, linked, proxied. Sunday, 30 September 12
  30. Building better Web APIs POST • It can do anything.

    • You do not pre-fetch it, you don’t bookmark it, you don’t cache it. Sunday, 30 September 12
  31. Building better Web APIs POST • It can do anything.

    • You do not pre-fetch it, you don’t bookmark it, you don’t cache it. • You do not build Web protocols on it. (*hint*) Sunday, 30 September 12
  32. Building better Web APIs PUT • Updates a resource. •

    Is idempotent. Sunday, 30 September 12
  33. Building better Web APIs PUT • Updates a resource. •

    Is idempotent. DELETE Sunday, 30 September 12
  34. Building better Web APIs PUT • Updates a resource. •

    Is idempotent. DELETE • Deletes a resource. Sunday, 30 September 12
  35. Building better Web APIs PUT • Updates a resource. •

    Is idempotent. DELETE • Deletes a resource. • Ist idempotent. Sunday, 30 September 12
  36. Building better Web APIs PUT • Updates a resource. •

    Is idempotent. DELETE • Deletes a resource. • Ist idempotent. Sunday, 30 September 12
  37. Building better Web APIs Use HTTP response codes wisely •

    200 - OK • 201 - created • 202 - accepted • 409 - conflict • 422 - Unprocessable entity • 401 - Unauthorized • 404 - Resource not found Sunday, 30 September 12
  38. Building better Web APIs Media Type A REST API should

    spend almost all of its descriptive effort in defining the media type(s) used Roy Fielding Sunday, 30 September 12
  39. Building better Web APIs Examples • Well known - text/html,

    application/json, text/ xml • Custom or vendor specific - application/ vnd.github+json Sunday, 30 September 12
  40. Building better Web APIs application/json • Preferred mime-type for APIs.

    • Formatting your hypermedia is most important thing. Sunday, 30 September 12
  41. Building better Web APIs Warning signs A REST API should

    not define fixed resource names. Sunday, 30 September 12
  42. Building better Web APIs Warning Sign A REST API should

    be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types. Sunday, 30 September 12
  43. Building better Web APIs Warning Sign A REST API should

    be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types. You should never have to document API end points. Sunday, 30 September 12
  44. Building better Web APIs Warning Sign API versioning is a

    Anti-Pattern. Sunday, 30 September 12
  45. Building better Web APIs Warning Signs Allow servers to instruct

    clients on how to construct appropriate URIs, such as is done in HTML forms and URI templates, by defining those instructions within media types and link relations. Sunday, 30 September 12
  46. Building better Web APIs Warning Signs Allow servers to instruct

    clients on how to construct appropriate URIs, such as is done in HTML forms and URI templates, by defining those instructions within media types and link relations. What to do next should be part of media type Sunday, 30 September 12
  47. Building better Web APIs 99% of APIs out there are

    RESTlike Sunday, 30 September 12
  48. Building better Web APIs GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 <slots> <slot id

    = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234" method="POST"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678" method="POST"/> </slot> </slots> Date Sunday, 30 September 12
  49. Building better Web APIs GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 <slots> <slot id

    = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234" method="POST"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678" method="POST"/> </slot> </slots> Date Sunday, 30 September 12
  50. Building better Web APIs GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 <slots> <slot id

    = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234" method="POST"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678" method="POST"/> </slot> </slots> Date Sunday, 30 September 12
  51. Building better Web APIs GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 <slots> <slot id

    = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234" method="POST"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678" method="POST"/> </slot> </slots> Date Sunday, 30 September 12
  52. Building better Web APIs GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 <slots> <slot id

    = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234" method="POST"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678" method="POST"/> </slot> </slots> Date Sunday, 30 September 12
  53. Building better Web APIs GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 <slots> <slot id

    = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234" method="POST"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678" method="POST"/> </slot> </slots> Date Description Sunday, 30 September 12
  54. Building better Web APIs GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 <slots> <slot id

    = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234" method="POST"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678" method="POST"/> </slot> </slots> Date Description Sunday, 30 September 12
  55. Building better Web APIs GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 <slots> <slot id

    = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234" method="POST"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678" method="POST"/> </slot> </slots> Date Description URI Sunday, 30 September 12
  56. Building better Web APIs GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 <slots> <slot id

    = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234" method="POST"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678" method="POST"/> </slot> </slots> Date Description URI Sunday, 30 September 12
  57. Building better Web APIs GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 <slots> <slot id

    = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234" method="POST"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678" method="POST"/> </slot> </slots> Date Description URI Verb Sunday, 30 September 12
  58. Building better Web APIs <appointment> <slot id = "1234" doctor

    = "mjones" start = "1400" end = "1450"/> <patient id = "jsmith"/> <link rel="/linkrels/appointment/cancel" uri="/slots/1234/appointment" method=”DELETE”/> <link rel="/linkrels/appointment/addTest uri="/slots/1234/appointment/tests" method=”POST”/> </appointment> <appointmentRequest> <patient id = "jsmith"/> </appointmentRequest> Sunday, 30 September 12
  59. Building better Web APIs <appointment> <slot id = "1234" doctor

    = "mjones" start = "1400" end = "1450"/> <patient id = "jsmith"/> <link rel="/linkrels/appointment/cancel" uri="/slots/1234/appointment" method=”DELETE”/> <link rel="/linkrels/appointment/addTest uri="/slots/1234/appointment/tests" method=”POST”/> </appointment> <appointmentRequest> <patient id = "jsmith"/> </appointmentRequest> Sunday, 30 September 12
  60. Building better Web APIs <appointment> <slot id = "1234" doctor

    = "mjones" start = "1400" end = "1450"/> <patient id = "jsmith"/> <link rel="/linkrels/appointment/cancel" uri="/slots/1234/appointment" method=”DELETE”/> <link rel="/linkrels/appointment/addTest uri="/slots/1234/appointment/tests" method=”POST”/> </appointment> <appointmentRequest> <patient id = "jsmith"/> </appointmentRequest> Sunday, 30 September 12
  61. Building better Web APIs <appointment> <slot id = "1234" doctor

    = "mjones" start = "1400" end = "1450"/> <patient id = "jsmith"/> <link rel="/linkrels/appointment/cancel" uri="/slots/1234/appointment" method=”DELETE”/> <link rel="/linkrels/appointment/addTest uri="/slots/1234/appointment/tests" method=”POST”/> </appointment> <appointmentRequest> <patient id = "jsmith"/> </appointmentRequest> Sunday, 30 September 12
  62. Building better Web APIs <appointment> <slot id = "1234" doctor

    = "mjones" start = "1400" end = "1450"/> <patient id = "jsmith"/> <link rel="/linkrels/appointment/cancel" uri="/slots/1234/appointment" method=”DELETE”/> <link rel="/linkrels/appointment/addTest uri="/slots/1234/appointment/tests" method=”POST”/> </appointment> <appointmentRequest> <patient id = "jsmith"/> </appointmentRequest> Sunday, 30 September 12
  63. Building better Web APIs What does HATEOAS provide? • You

    never have to version your API. • You never have to worry about changing resource names. • Beyond initial URL, never have to worry about keeping old endpoints intact. Sunday, 30 September 12
  64. Building better Web APIs Usage of Hypermedia Controls? • Tooling

    • Lack of education among programmers. Sunday, 30 September 12
  65. Building better Web APIs Lack of Hypermedia Controls forces us

    to have versioning Sunday, 30 September 12
  66. Building better Web APIs Two dominant ways • github.com/api/v3/users.json •

    Mime-type based versioning : application/ vnd.github[.version].param[+json] Sunday, 30 September 12
  67. Building better Web APIs Using Mime-Type class Twitter::API < Grape::API

    version 'v1', :using => :header, :vendor => 'pycon' end curl -H Accept=application/vnd.pycon-v1+json http://localhost:9292/users Sunday, 30 September 12
  68. Building better Web APIs Using PATH class Twitter::API < Grape::API

    version 'v1', :using => :path end curl -H Accept=application/json http://localhost:9292/v1/users Sunday, 30 September 12