Cloud Computing‎ > ‎

REST API





What is REST


REST Methods


In a nutshell
  • GET should be Read Only i.e. have no effect on server state. 
  • POST is used to create a resource on the server. 
  • PUT is used to update or create a resource. 
  • DELETE is used to delete a resource.

In other words, if your API action changes the server state, REST advises us to use POST/PUT/DELETE, but not GET.

Idempotent Actions

  • If your action is not idempotent, then you MUST use POST. If you don't, you're just asking for trouble down the line.  GET, PUT and DELETE methods are required to be idempotent. 
  • Imagine what would happen in your application if the client was pre-fetching every possible GET request for your service -- if this would cause side effects visible to the client, then something's wrong.


Design uniform REST APIs


In real world, an API is never going to be completely stable. So it’s important how this change is managed. 
A well documented and gradual deprecation of API can be an acceptable practice for most of the APIs.

1. Handle Errors with HTTP status codes and Use error payloads

   Consistent HTTP Status Codes in response (around 4xx and 5xx)   
   It is hard to work with an API that ignores error handling. Pure returning of a HTTP 500 with a stacktrace is not very helpful.

   Use HTTP status codes

   The HTTP standard provides over 70 status codes to describe the return values. We don’t need them all, but  there should be used at least a mount of 10.

   200 – OK – Eyerything is working
   201 – OK – New resource has been created
   204 – OK – The resource was successfully deleted

   304 – Not Modified – The client can use cached data

   400 – Bad Request – The request was invalid or cannot be served. The exact error should be explained in the error payload. E.g. „The JSON is not valid“
   401 – Unauthorized – The request requires an user authentication
   403 – Forbidden – The server understood the request, but is refusing it or the access is not allowed.
   404 – Not found – There is no resource behind the URI.
   422 – Unprocessable Entity – Should be used if the server cannot process the enitity, e.g. if an image cannot be formatted or mandatory fields are missing in the payload.

   500 – Internal Server Error – API developers should avoid this error. If an error occurs in the global catch blog, the stracktrace should be logged and not returned as response.

   Use error payloads
   All exceptions should be mapped in an error payload. Here is an example how a JSON payload should look like.
{
  "errors": [
   {
    "userMessage": "Sorry, the requested resource does not exist",
    "internalMessage": "No car found in the database",
    "code": 34,
    "more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"
   }
  ]

2. API Versioning
   
   a. When to Version
      APIs only need to be up-versioned when a breaking change is made. Breaking changes include:
      - a change in the format of the response data for one or more calls
      - a change in the response type (i.e. changing an integer to a float)
      - removing any part of the API.

   b. Breaking changes 
      Breaking changes should always result in a change to the major version number for an API or content response type.

   c. Non-breaking changes
      Non-breaking changes, such as adding new endpoints or new response parameters, do not require a change to the major version number. 
      However, it can be helpful to track the minor versions of APIs when changes are made to support customers who may be receiving cached versions of data or may be experiencing other API issues.

   d. How-To Version
      URI Versioning
      Using the URI is the most straightforward approach (and most commonly used as well) though it does violate the principle that a URI should refer to a unique resource. 
      You are also guaranteed to break client integration when a version is updated.

      The version need not be numeric, nor specified using the “v[x]” syntax. 
      Alternatives include dates, project names, seasons or other identifiers that are meaningful enough to the team producing the APIs and flexible enough to change as the versions change.

      eg:
      http://api.example.com/v1
      http://apiv1.example.com

      Versioning using Custom Request Header
      A custom header (e.g. Accept-version) allows you to preserve your URIs between versions though it is effectively a duplicate of the content negotiation behavior implemented by the existing Accept header.

      e.g.
      Accept-version: v1
      Accept-version: v2

      Versioning using Accept header
      Content negotiation may let you to preserve a clean set of URLs but you still have to deal with the complexity of serving different versions of content somewhere. This burden tends to be moved up the stack to your API controllers which become responsible for figuring out which version of a resource to send. The end result tends to be a more complex API as clients have to know which headers to specify before requesting a resource.

      e.g.

      Accept: application/vnd.example.v1+json
      Accept: application/vnd.example+json;version=1.0


3. Response schema format (e.g. JSON only responses)

4. Response schema guidelines
   e.g. Structure of the response json and keeping it flexsible to accomodate future changes

5. API naming convention
   mvx/v1/submission
   mvx/v1/status

6. Use nouns but no verbs
   Use nouns
   /cars
   /cars/711

   Do not use verbs:

   /getAllCars
   /createNewCar
   /deleteAllRedCars

7. GET method and query parameters should not alter the state

8. Use plural nouns
   Do not mix up singular and plural nouns. Keep it simple and use only plural nouns for all resources.

   /cars instead of /car
   /users instead of /user
   /products instead of /product
   /settings instead of /setting

9. Use sub-resources for relations
   If a resource is related to another resource use subresources.

   GET /cars/711/drivers/ Returns a list of drivers for car 711
   GET /cars/711/drivers/4 Returns driver #4 for car 711

10. Use HTTP headers for serialization formats
    Both, client and server, need to know which format is used for the communication. The format has to be specified in the HTTP-Header.

    Content-Type defines the request format.
    Accept defines a list of acceptable response formats.

11. Provide filtering, sorting, field selection and paging for collections
    Filtering:

    Use a unique query parameter for all fields or a query language for filtering.

    GET /cars?color=red Returns a list of red cars
    GET /cars?seats<=2 Returns a list of cars with a maximum of 2 seats

    Sorting:
    Allow ascending and descending sorting over multiple fields.
    
    GET /cars?sort=-manufactorer,+model
    This returns a list of cars sorted by descending manufacturers and ascending models.

    Field selection
    Mobile clients display just a few attributes in a list. They don’t need all attributes of a resource. Give the API consumer the ability to choose returned fields. This will also reduce the network traffic and speed up the usage of the API.

    GET /cars?fields=manufacturer,model,id,color

    Paging
    Use limit and offset. It is flexible for the user and common in leading databases. The default should be limit=20 and offset=0

    GET /cars?offset=10&limit=5
    To send the total entries back to the user use the custom HTTP header: X-Total-Count.

12. URI case
    When it comes to naming resources in a program, there are 3 main types of case conventions: CamelCase, snake_case, and spinal-case. They are just a way of naming the resources to resemble natural language while avoiding spaces, apostrophes, and other exotic characters. This habit is universal in programming languages where only a finite set of characters is authorized for names.

    CamelCase
    CamelCase has been popularized by the Java language. It intends to emphasize the beginning of each word by making the first letter uppercase. E.g. camelCase, currentUser, etc. Aside from debates about its readability, its main drawback is to be ineffective in contexts which are not case sensitive.

    snake_case
    snakecase has been widely used for years by C programmers, and more recently in Ruby. Words are separated by underscores “”, thus letting a compiler or an interpreter understand it as a single symbol, but also allowing readers to separate words fluently. However, its popularity has decreased due to a lot of abuses in C programs with over-extended or too short names. Unlike camel case, there are very few contexts where snake case is not usable. Examples: snakecase, currentuser, etc.

    spinal-case
    spinal-case is a variant of snake case which uses hyphens “-” to separate words. The pros and cons are quite similar to those of snake case, with the exception that some languages do not allow hyphens in symbol names (for variable, class, or function naming). You may find it referred to as lisp-case because it is the usual way to name variables and functions in lisp dialects. It is also the traditional way of naming folders and files in UNIX and Linux systems. Examples: spinal-case, current-user, etc.

    According to RFC3986, URLs are “case sensitive” (except for the scheme and the host). 
    In practice, though, a sensitive case may create dysfunctions with APIs hosted on a Windows system.

    It is recommended to use spinal-case (which is highlighted by RFC3986), this case is used by Google, PayPal and other big companies.

13. HTTP Methods
    One of the key objectives of the REST approach is using HTTP as an application protocol in order to avoid shaping a homemade API. Hence, we should systematically use HTTP verbs to describe what actions are performed on the resources and facilitate the developer’s work handling recurrent CRUD operations.

    The following methods are usually observed:

   GET
   The GET method is used to retrieve information from the given server using a given URI. Requests using GET should only retrieve data and should have no other effect on the data.

   HEAD
   Same as GET but transfers the status line and header section only.

   POST
   A POST request is used to send data to the server, for example, customer information, file upload, etc. using HTML forms.

   PUT
   Replaces all current representations of the target resource with the uploaded content.

   DELETE
   Removes all current representations of the target resource given by a URI.

   OPTIONS
   Describes the communication options for the target resource.


14. API Gateway (Cloud Products)
   The uniform API Gateway (e.g. AWS AI Gateway or internal API Gateway) would be helpful in functionality evolution around rate-limit, burst-rate, quota-limit, threshold action, etc.

15. IAM authorization (Cloud Products)
   The uniform IAM (e.g. AWS IAM or internal IAM) would be helpful in funationality evolution

16. SSL everywhere (with TLS 1.2 and higher)

References















Comments