Share
Embed
Transcript
138 slides
-
Building better Web APIs whoami • Hemant - (AKA Ruby
guy). • http://github.com/gnufied • http://www.codemancers.com Sunday, 30 September 12 -
Building better Web APIs What is REST? REST is a
software architectural style for network based application software. Sunday, 30 September 12 -
Building better Web APIs What is REST? REST is a
software architectural style for network based application software. Roy Fielding Sunday, 30 September 12 -
Building better Web APIs Few important things • It is
not a design pattern. Sunday, 30 September 12 -
Building better Web APIs Few important things • It is
not a design pattern. • It is not a library or framework. Sunday, 30 September 12 -
Building better Web APIs Using HTTP to its fullest to
interact with resources within certain Architectural constraints. Sunday, 30 September 12 -
Building better Web APIs A web page is a “representation”
of a resource. Loving husband to his wife Sunday, 30 September 12 -
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 -
Building better Web APIs REST anti-pattern • Each database model
is turned into a Resource. Sunday, 30 September 12 -
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 -
Building better Web APIs Identify resources in your Application •
Think about what your webservice provides. Sunday, 30 September 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 -
Building better Web APIs Why is that bad? Sunday, 30
September 12 -
Building better Web APIs • Tight coupling with Data model.
Why is that bad? Sunday, 30 September 12 -
Building better Web APIs • Tight coupling with Data model.
• You are on a slippery slope now. Why is that bad? Sunday, 30 September 12 -
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 -
Building better Web APIs What was wrong? • Any guesses
why creating a company via API required so many parameters? Sunday, 30 September 12 -
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 -
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 -
Building better Web APIs Thats how we built APIs using
Rails Sunday, 30 September 12 -
Building better Web APIs Sadly it is still RESTful architecture
for many Rails developers. Sunday, 30 September 12 -
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 -
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 -
Building better Web APIs Recap • Identify resources to expose.
• Expose the workflow not the data model. Sunday, 30 September 12 -
Building better Web APIs REST is not specific to building
APIs Sunday, 30 September 12 -
Building better Web APIs • GET • POST Sunday, 30
September 12 -
Building better Web APIs • GET • POST • PUT
Sunday, 30 September 12 -
Building better Web APIs • GET • POST • PUT
• DELETE Sunday, 30 September 12 -
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 -
Building better Web APIs How do I do this in
Ruby? Sunday, 30 September 12 -
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 -
Building better Web APIs So what is the big fuss
about verbs? Sunday, 30 September 12 -
Building better Web APIs Only support GET & POST Sunday,
30 September 12 -
Building better Web APIs GET • Anything that is safe.
Does not have side effects. Sunday, 30 September 12 -
Building better Web APIs GET • Anything that is safe.
Does not have side effects. • Can be cached, bookmarked, linked, proxied. Sunday, 30 September 12 -
Building better Web APIs POST • It can do anything.
Sunday, 30 September 12 -
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 -
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 -
Building better Web APIs PUT • Updates a resource. Sunday,
30 September 12 -
Building better Web APIs PUT • Updates a resource. •
Is idempotent. Sunday, 30 September 12 -
Building better Web APIs PUT • Updates a resource. •
Is idempotent. DELETE Sunday, 30 September 12 -
Building better Web APIs PUT • Updates a resource. •
Is idempotent. DELETE • Deletes a resource. Sunday, 30 September 12 -
Building better Web APIs PUT • Updates a resource. •
Is idempotent. DELETE • Deletes a resource. • Ist idempotent. Sunday, 30 September 12 -
Building better Web APIs PUT • Updates a resource. •
Is idempotent. DELETE • Deletes a resource. • Ist idempotent. Sunday, 30 September 12 -
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 -
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 -
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 -
Building better Web APIs application/json • Preferred mime-type for APIs.
• Formatting your hypermedia is most important thing. Sunday, 30 September 12 -
Building better Web APIs Warning signs A REST API should
not define fixed resource names. Sunday, 30 September 12 -
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 -
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 -
Building better Web APIs Warning Sign API versioning is a
Anti-Pattern. Sunday, 30 September 12 -
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 -
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 -
Building better Web APIs Hypermedia as Engine of Application State
Sunday, 30 September 12 -
Building better Web APIs 99% of APIs out there are
RESTlike Sunday, 30 September 12 -
Building better Web APIs Book an appointment with Doctor Sunday,
30 September 12 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
Building better Web APIs Why aren’t people doing this? Sunday,
30 September 12 -
Building better Web APIs Usage of Hypermedia Controls? • Tooling
• Lack of education among programmers. Sunday, 30 September 12 -
Building better Web APIs Widely deployed REST system The Web
Sunday, 30 September 12 -
Building better Web APIs Lack of Hypermedia Controls forces us
to have versioning Sunday, 30 September 12 -
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 -
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 -
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