Best practices for designing pragmatic RESTful api
Upcoming SlideShare
Loading in...5
×
 

Best practices for designing pragmatic RESTful api

on

  • 11,984 views

This presentation teach how to design a real-world yet beautiful RESTful API. It draws from the experience Mario Cardinal have gained being involved in the design of the RESTful API for a task board. ...

This presentation teach how to design a real-world yet beautiful RESTful API. It draws from the experience Mario Cardinal have gained being involved in the design of the RESTful API for a task board. This presentation begins with a brief overview of what is a REST and continue with the design process. We conclude with a review of the best practices when designing RESTful API. Armed with skills acquired, you can expect to see significant improvements in your ability to design a pragmatic RESTful API.

Statistics

Views

Total Views
11,984
Views on SlideShare
11,959
Embed Views
25

Actions

Likes
13
Downloads
160
Comments
0

1 Embed 25

http://www.scoop.it 25

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • 8 minutesKeeps people from ‘making up’ verbs Don’t need to decide on the ‘correct’ method names for the API making up names is hard – see the annotated .Net Framework bookBreaking these rules can cause problems GET is supposed to not cause side-effects But if this is no true on your pages, then spidering causes problemsIdempotent – has a side effect, but the side effect is well knownPOST is used to create a resource where the server needs to define the URICachability lends itself to etagging Conditional GET implies a full get ONLY if the etags have changedCan’t get the same scale using SOAP

Best practices for designing pragmatic RESTful api Best practices for designing pragmatic RESTful api Presentation Transcript

  • Best practices for designing pragmatic REST API Mario Cardinal Agile Coach & Software Architect www.mariocardinal.com Version April 10
  • • Agile Coach & Software architect • Co-Founder of Slingboards Lab • www.mariocardinal.com Who am I? http://www.slideshare.net/mario_cardinal
  • 3 1. HTTP – How it works? 2. REST – What is it? 3. RESTful or Resource APIs? 4. Resource APIs – Best practices Content
  • Pragmatic REST API Application Programming Interface (API)  It should be simple, intuitive and consistent to make adoption not only easy but pleasant  It should be friendly to the developer and be explorable via HTTP tools  It should use web standards where they make sense 4 API
  • HTTP – How it works?  Resources  Request Messages  Response Messages  Connections
  • Ressources: URL
  • Uniform Resource Locator  <scheme>://<host>:<port>/<path>?<query>#<fragment>  http://amazon.com:80/gp/product/B00D3UDMEU  URL Scheme : http,  Host: amazon.com  Port : 80  URL path: /gp/product/B00D3UDMEU  http://www.google.com/search?q=kindle  Query string: ?q=kindle  http://www.foo.com?first=Mario&last=Cardinal  Query string: ?first=Mario&last=Cardinal  http://server.com/homepage.html#ingredients  Fragment: #ingredients  refers to the element with id=“ingredients“  <div id=ingredients> </div>.
  • URL Encoding  http://someserver.com/%5Emy%20resume.txt  URL encoding: "^my resume.txt"
  • HTTP Request and response  A client sends an HTTP request to a server using a carefully formatted message that the server will understand.  A server responds by sending an HTTP response that the client will understand.  The request and the response are two different message types that are exchanged in a single HTTP transaction.  An HTTP message is a simple, plain text message.
  • HTTP Request Message  A full HTTP request message consists of the following parts: [method] [URL] [version] [headers] [body] GET http://mariocardinal.com/Articles/741.aspx HTTP/1.1 Accept-Language: fr-CA Date: Fri, 9 Aug 2013 21:12:00 GMT
  • HTTP Request Method Method Description GET Retrieve a resource PUT Store a resource DELETE Remove a resource POST Update a resource HEAD Retrieve the headers for a resource
  • HTTP Header Header Description Referer When the user clicks on a link, the client can send the URL of the referring page in this header. User-Agent Information about the user agent (the software) making the request. Many applications use the information in this header, when present, to figure out what browser is making the request (Internet Explorer 9 versus Chrome, etc.). Accept Describes the media types the user agent is willing to accept. This header is used for content negotiation. Accept-Language Describes the languages the user agent prefers. Cookie Cookie information generally helps a server track or identify a user. If-Modified-Since Will contain a date of when the user agent last retrieved (and cached) the resource. The server only has to send back the entire resource if it's been modified since that time.
  • POST HTTP request message <form action="/account/create" method="POST"> <label for="firstName">First name</label> <input id="firstName" name="firstName" type="text" /> <label for="lastName">Last name</label> <input id="lastName" name="lastName" type="text" /> <input type="submit" value="Sign up!"/> </form> POST http://server.com:1060/account/create HTTP/1.1 Host: server.com firstName=Mario&lastName=Cardinal
  • HTTP Response Message  A full HTTP response message consists of the following parts: [version] [status] [reason] [headers] [body] HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Server: Microsoft-IIS/7.0 X-AspNet-Version: 2.0.50727 X-Powered-By: ASP.NET Date: Sat, 14 Jan 2012 04:00:08 GMT Connection: close Content-Length: 17151 <html> <head> <title>Hello</title> </head> <body> ... content ... </body> </html>
  • HTTP Response Status Code Range Category 100–199 Informational 200–299 Successful 300–399 Redirection 400–499 Client Error 500–599 Server Error
  • Resources and media types  When a host responds to an HTTP request, it returns a resource (content)  Host also specifies the content type (also known as the media type) of the resource  Defined using Multipurpose Internet Mail Extensions (MIME)  "text/html"  "image/jpeg"  "text/xml"  "application/json"
  • Content negotiation  Content negotiation is part of what makes HTTP great  Request message  Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8  Response message  Content-Type: text/html; charset=utf-8
  • Time-Based Caching HTTP/1.1 200 OK Last-Modified: Wed, 25 Jan 2012 17:55:15 GMT Expires: Sat, 22 Jan 2022 17:55:15 GMT Cache-Control: max-age=315360000,public Content-Length: 208 <html> <head> </head> <body> </body> </html>
  • Content-Based Caching HTTP/1.1 200 OK Last-Modified: Fri, 06 Jan 2012 18:08:20 GMT ETag: "8e5bcd-59f-4b5dfef104d00" Content-Type: text/xml Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 437 <html> <head> > </head> <body> </body> </html>
  • HTTP Request and Caching Request GET … HTTP/1.1 If-Modified-Since: Wed, 25 Jan 2012 17:55:15 GMT Response HTTP/1.1 304 Not Modified Expires: Sat, 22 Jan 2022 17:16:19 GMT Cache-Control: max-age=315360000,public
  • Cookies HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Set-Cookie: fname=Mario$lname=Cardinal; expires=Monday, 09-July-2012 21:12:00 GMT domain=.mywebsite.com; path=/ ; HttpOnly
  • Identification and Cookies  There is a size limitation of 4 KB  Many websites only put in a unique identifier for a user HTTP/1.1 200 OK Set-Cookie: GUID=00a48b7f6a4946a8adf593373e53347c; domain=.msn.com; path=/ ; HttpOnly
  • Identification and Cookies  Assuming the browser is configured to accept cookies, the browser will send the cookie to the server in every subsequent HTTP request. GET msn.com HTTP/1.1 Cookie: GUID=00a48b7f6a4946a8adf593373e53347c;
  • Downsides to cookies  They interfere with caching  Any response with a Set-Cookie header should not be cached, at least not the headers, since this can interfere with user identification and create security problems  They transmit data with every request  Large cookie raise demand for network bandwidth  A cookie should never store sensitive information
  • Connection
  • Network Debugging  Observe TCP handshake and IP headers http://www.wireshark.org/  Observe and manipulate HTTP request and response http://www.telerik.com/fiddler
  • REST – What is it?  An architectural style (extends client-server) introduced by Roy Fielding  Defines a set of constraints influenced from the architecture of the Web  URLs represent resources  Clients interact with resources via a uniform interface  Messages are self-descriptive (ContentType)  Services are stateless  Hypermedia (i.e. href tags) drive application state27
  • A more lightweight way to build services (API)  Using URLs to build on Web experience  http://myservice.com/api/resources  http://myservice.com/api/resources/{id}  http://myservice.com/api/resources/{id}/relation  HTTP verbs  GET, POST, PUT, PATCH, DELETE  Manage errors at the transport level 28
  • Uniform Interfaces (HTTP Verbs) POST DELETE GET PUT Retrieves a resource Guaranteed not to cause side-effects (SAFE) Results are cacheable Creates a new resource (process state) Unsafe: effect of this verb isn’t defined by HTTP Updates an existing resource Used for resource creation when client knows URI Can call N times, same thing will always happen (idempotent) Removes a resource Can call N times, same thing will always happen (idempotent) PATCH Updates an existing resource (partially) Can call N times, same thing will always happen (idempotent)
  • Resources come from the business domain  Task Board 30 Sticky Notes
  • Resources are nouns  http://myservice.com/api/stickyNotes  Verb: GET  Action: Retrieves a list of sticky notes  http://myservice.com/api/stickyNotes/12  Verb: GET  Action: Retrieves a specific sticky note  http://myservice.com/api/stickyNotes  Verb: POST  Action: Creates a new sticky note 31
  • Resources are nouns  http://myservice.com/api/stickyNotes/12  Verb: PUT  Action: Updates sticky notes #12  http://myservice.com/api/stickyNotes/12  Verb: PATCH  Action: Partially updates sticky note #12  http://myservice.com/api/stickyNotes/12  Verb: DELETE  Action: Deletes sticky note #12 32
  • Most so-called RESTful APIs are not RESTful at all and that’s not a bad thing at all
  • Rather, most “RESTful APIs” are really “Resource APIs” http://ServiceDesignPatterns.com/WebServiceAPIStyles/ResourceAPI again, not a bad thing at all. Resource APIs totally rock !!!
  • REST Constraint Resource APIs Client/Server Yes Stateless Not required Cacheable Responses Not required (Generic) Uniform Interface Yes Unique URIs Yes Resources manipulated through Representations Yes Hypermedia as the Engine of Application State Not required Copyright © 2012 Rob Daigneau, All rights reserved
  • Hypermedia constraint  Hypermedia as the Engine of Application State (HATEOAS)  Hypermedia constraint states that interaction with an endpoint should be defined within metadata returned with the output (URL)  Apply state transitions (at run time) by following links  HATEOAS is not required  Decisions are made when code is written, not at run time 36
  • 37 1. Documentation 2. URL EndPoint  Resources  Version 3. Message Body  Content-Type 4. Error handling  HTTP Status Code 5. Security Resource APIs – Best practices
  • Documentation  An API is only as good as its documentation  Docs should be easy to find  http://myservice.com/api/help  Docs should show examples of complete request/response cycles  Be sure to document the state transitions by out-of-band information  Include resource identifiers in the documentation which the API consumer will use when crafting links 38
  • URL identifies a resource  Endpoint name should be plural  stickyNotes, collaborators  Do not forget relations (business domain)  GET /api/stickynotes/12/collaborators - Retrieves list of collaborators for sticky note #12  GET /api/stickynotes/12/collaborators/5 - Retrieves collaborator #5 for sticky note #12  POST /api/stickynotes/12/collaborators - Creates a new collaborator in sticky note #12  PUT /api/stickynotes/12/collaborators/5 - Updates collaborator #5 for sticky note #12 39
  • Verbs (actions) as resources  Actions that don't fit into the world of CRUD operations can be endpoint  Change state with ToDo, InProgress or Done action  Mark a sticky note in progress with PUT /stikyNotes/:id/inProgress  GitHub's API  star a gist with PUT /gists/:id/star  unstar with DELETE /gists/:id/star 40
  • Use Query to simplify resources  Keep the base resource URLs lean by implementing query parameters on top of the base URL  Result filtering, sorting & searching  GET /api/stickyNotes?q=return&state=ToDo&sort=- priority,created_at  Limiting which fields are returned by the API  GET /api/stickyNotes?fields=id,subject,state,collaborator,up dated_at&state=InProgress&sort=-updated_at 41
  • Paginate using link headers  Return a set of ready-made links so the API consumer doesn't have to construct links themselves  The right way to include pagination details today is using the ‘Link header’ introduced by RFC 5988 42 Link header: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next", <https://api.github.com/user/repos?page=50&per_page=100>; rel="last"
  • Versioning  Version via the URL, not via headers  http://api.myservice.com/v1/stickynotes  http://myservice.com/v1/stickynotes  Benefits  Simple implementation  Ensure browser explorability  Issues  URL representing a resource is NOT stable across versions 43
  • Message (Content-type)  JavaScript Object Notation (JSON) is the preferred resource representation  It is lighter than XML but as easy for humans to read and write  No parsing is needed with JavaScript clients  Requiring Content-Type JSON  POST, PUT & PATCH requests should also require the Content-Type header be set to application/json or throw a 415 Unsupported Media Type HTTP status code 44
  • Message (Content-type)  A JSON object is an unordered set of name/value pairs  Squiggly brackets act as 'containers'  Square brackets holds arrays  Names and values are separated by a colon.  Array elements are separated by commas 45 var myJSONObject = { "web":[ { "name": "html", "years": "5" }, { "name": "css", "years": "3" }] "db":[ { "name": "sql", "years": "7" }] }
  • Message (Content-type)  camelCase for field names  Follow JavaScript naming conventions  Do not pretty print by default  Gzip by default  Gzipping provided over 60% in bandwidth savings  Always set the Accept-Encoding header 46 {“customerData" : {"id" : 123, "name" : "John" }} Header: Accept-Encoding: gzip
  • Message (Post, Put and Patch)  Updates & creation should return a resource representation  To prevent an API consumer from having to hit the API again for an updated representation, have the API return the updated (or created) representation as part of the response  In case of a POST that resulted in a creation, use a HTTP 201 status code and include a Location header that points to the URL of the new resource 47
  • HTTP caching header  Time-based (Last-Modified)  When generating a request, include a HTTP header Last-Modified  if an inbound HTTP requests contains a If- Modified-Since header, the API should return a 304 Not Modified status code instead of the output representation of the resource  Content-based (ETag)  This tag is useful when the last modified date is difficult to determine 48
  • HTTP Rate limiting header  Include the following headers (using Twitter's naming conventions as headers typically don't have mid-word capitalization):  X-Rate-Limit-Limit - The number of allowed requests in the current period  X-Rate-Limit-Remaining - The number of remaining requests in the current period  X-Rate-Limit-Reset - The number of seconds left in the current period 49
  • HTTP status codes  200 OK - Response to a successful GET, PUT, PATCH or DELETE. Can also be used for a POST that doesn't result in a creation.  201 Created - Response to a POST that results in a creation. Should be combined with a Location header pointing to the location of the new resource  204 No Content - Response to a successful request that won't be returning a body (like a DELETE request)  304 Not Modified - Used when HTTP caching headers are in play 50
  • HTTP status codes  400 Bad Request - The request is malformed, such as if the body does not parse  401 Unauthorized - When no or invalid authentication details are provided. Also useful to trigger an auth popup if the API is used from a browser  403 Forbidden - When authentication succeeded but authenticated user doesn't have access to the resource  404 Not Found - When a non-existent resource is requested  405 Method Not Allowed - When an HTTP method isn't allowed for the authenticated user 51
  • HTTP status codes  409 Conflict - The request could not be completed due to a conflict with the current state of the resource  410 Gone - Indicates that the resource at this end point is no longer available. Useful as a blanket response for old API versions  415 Unsupported Media Type - If incorrect content type was provided as part of the request  422 Unprocessable Entity - Used for validation errors  429 Too Many Requests - When a request is rejected due to rate limiting 52
  • Security  Never encode authentication on the URI  Always identify the caller in the HTTP header  Each request should come with authentication credentials  HTTPS (SSL) everywhere - all the time  Support basic authentication over HTTPS 53
  • Basic Authentication Request GET http://localhost /demo/ HTTP/1.1 Host: localhost Response HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm="localhost"  The WWW-Authenticate header tells the client to collect the user credentials and try again  The realm attribute gives the user agent a string it can use as a description for the protected area  What happens next depends on the user agent, but most browsers will display a UI for the user to enter credentials.
  • Basic Authentication Request GET http://localhost/Demo/ HTTP/1.1 Authorization: Basic bm86aXdvdWxkbnRkb3RoYXQh  The value of the authorization header is the client's username and password in a base 64 encoding.  Basic authentication is insecure by default,
  • Digest Authentication  Digest authentication is an improvement over basic authentication because it does not transmit user passwords using base 64 encoding  The client must send a digest of the password. Request GET http://localhost /demo/ HTTP/1.1 Host: localhost Response HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm="localhost« , qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"  Still vulnerable to man-in-the-middle attacks in which someone is sniffing network traffic
  • Windows Authentication  Windows Authentication depends on the underlying authentication protocols supported by Microsoft Windows Request GET http://localhost /demo/ HTTP/1.1 Host: localhost Response HTTP/1.1 401 Unauthorized WWW-Authenticate: Negotiate  Windows Authentication has the advantage of being secure even without using secure HTTP  Require Microsoft products and servers (Active Directory)
  • Form-based Authentication  Forms authentication is the most popular approach to user authentication over the Internet.  It is not a standard authentication protocol and doesn't use WWW- Authenticate or Authorization headers Request GET http://localhost /demo/ HTTP/1.1 Host: localhost Response HTTP/1.1 302 Found Location: /Login.aspx?ReturnUrl=/demo/ Response HTTP/1.1 302 Found Location: /demo/ Set-Cookie: .ASPXAUTH=9694BAB... path=/demo/; HttpOnly  Still vulnerable to session hijacking in which someone is sniffing network traffic
  • Secure HTTP (SSL)
  • Secure HTTP (SSL)  All traffic over HTTPS is encrypted in the request and response  HTTPS requires a server to have a cryptographic certificate.  Administrators have to purchase and install certificates from the certificate authorities like Verisign.  The server is authenticated to the client thanks to the server certificate  The certificate is sent to the client during setup of the HTTPS communication.  The certificate enable to validate that the client is truly talking to the server it thinks it is talking to.  The validation is all made possible using public key cryptography and the existence of certificate authorities that will sign and vouch for the integrity of a certificate.  HTTPS does not authenticate the client  Applications still need to implement forms or Basic authentication
  • Basic authentication over HTTPS  Create a string with username and password in the form ”username:password”  Convert that string to a base64 encoded string  Prepend the word “Basic” and a space to that base64 encoded string  Set the HTTP request’s Authorization header with the resulting string 61 Header: Authorization: Basic anNtaXRoOlBvcGNvcm4=
  • API key authentication over HTTPS Best way to protect a key is not to transmit it. Use a scheme, where every "API key" has two parts: A non-secret ID (e.g. 1234) and a secret key (e.g. byte[64]).  If you give out an API key, store it (salted and hashed) in you service's database.  If you give out user accounts (protected by password), store the passwords (salted and hashed) in your service's database Now when a consumer first accesses your API, to connect, have him  Send a "username" parameter ("john.doe" not secret)  Send a "APIkeyID" parameter ("1234", not secret) and give him back  the salts from your database (In case one of the parameters is wrong, just give back some repeatable salt - eg. sha1(username+"notverysecret").  The timestamp of the server The consumer should store the salt for session duration to keep things fast and smooth, and he should calculate and keep the time offset between client and server. The consumer should now calculate the salted hashes of API key and password. This way the consumer has the exact same hashes for password and API key, as what is stored in your database, but without anything secret ever going over the wire. 62
  • API key authentication over HTTPS Now when a consumer subsequently accesses your API, to do real work, have him  Send a "username" parameter ("john.doe" not secret)  Send a "APIkeyID" parameter ("1234", not secret)  Send a "RequestSalt" parameter (byte[64], random, not secret)  Send a "RequestTimestamp" parameter (calculated from client time and known offset)  Send a "RequestToken" parameter (hash(passwordhash+request_salt+request_timestamp+apikeyhash)) The server should not accept timestamps more than say 2 seconds in the past, to make this safe against a replay attack. The server can now calculate the same hash(passwordhash+request_salt+request_timestamp+apikeyhash) as the consumer, and be sure, that  the client knows the API key,  the client knows the correct password 63