REST API is no longer a strange concept to all dev brothers from frontend to backend. However, to understand and follow REST’s standard guidelines, many of you may still not know. So in this article, I will share these conventions.

What is REST API?

REST API (also known as RESTful API) is an application programming interface (API) that adheres to the REST architectural conventions and constraints used in client-server communication. REST stands for REpresentational State Transfer, it was created by computer scientist Roy Fielding.

REST APIs often still use the HTTP/1 protocol with previous definitions that both the client and the server need to adhere to. For example, the server provides an API to get the balance of an account, the method is GET, there should be an Authorization header, the response will be a text with the first part being the account number, the second part being the balance.

Well, the days of returning text like that are over, now REST APIs using JSON are more common. A few may still use XML.

Two components in REST API

API (Application Programming Interface) translates to application programming interface. Actually this interface is not for end users but for developers. Rather, it is a “surface” only, seeing only the declaration (name, parameters, return type), the body suit is unknown. “Knowing the face, not knowing the heart” is the API.

REST (REpresentational State Transfer) means a representation of data transformation. What the hell!! That is to say, in this architecture the client and server are completely independent, they do not know anything about each other. Each REST API request carries no previous state (stateless). So for the two parties to exchange state, they will force through resources. These resources represent the change in data.

State Transfer. Client. Server. request. a. a. b. c. d. e a. a. a. a. response. State of resource. (in different representations) Actual. Resources. The word Representational State Transfer (REST) comes from how the state of resources (in various representations) flow within the client application.

Request and Response in REST API

Methods

As mentioned above, to exchange state they will need to communicate resources through sending request responses via HTTP/1. Specifically how this communication is, they need to specify the corresponding methods including:

  • GET: Returns a Resource or a list of Resources.
  • POST: Create a new Resource.
  • PUT: Update information for Resource (the entire resource).
  • PATCH: Update information for resourse (part of resource).
  • DELETE: Delete a Resource.

If you’ve heard of CRUD APIs, they represent Create, Read, Update and Delete a resource.

Headers

Remember that REST API is stateless. Each request does not know any previous information. Unlike when we access the web, the browser will have a session and a cookie to help distinguish who the request is from and what the previous information is.

In REST, if a request needs to authenticate access, they will have to use additional information in the header. For example, the Authorization information will carry a user token. There are 3 main Authentication mechanisms:

  • HTTP Basic
  • JSON Web Token (JWT)
  • OAuth2

In addition, the Header also helps the client specify the type of content to return from the server – content type. This is done through the Accept section of the header. Its value is usually the MIME type:

  • image — image/png, image/jpeg, image/gif
  • audio — audio/wav, audio/mpeg
  • video — video/mp4, video/ogg
  • application — application/json, application/pdf, application/xml, application/octet-stream

Example request to get a list of posts:

GET /v1/posts
Accept: application/json

Status Code

The response in the REST API will include a status code that specifies each case. You can see the full list here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

Some popular statuses:

  • 200 OK – Returns success for the GET, PUT, PATCH or DELETE methods.
  • 201 Created – Returns when a Resouce has been successfully created.
  • 204 No Content – ​​Returns when the Resource is successfully deleted.
  • 304 Not Modified – Client can use cached data, resource server remains unchanged.
  • 400 Bad Request – Invalid Request
  • 401 Unauthorized – Request requires authentication.
  • 403 Forbidden – permission denied.
  • 404 Not Found – Resource not found from URI
  • 405 Method Not Allowed – The method is not allowed for the current user.
  • 410 Gone – Resource no longer exists, the old version is no longer supported.
  • 415 Unsupported Media Type – This Resource type is not supported.
  • 422 Unprocessable Entity – Data is not validated
  • 429 Too Many Requests – Request denied due to restriction

Support version

Usually REST API will have version like /v1, /v2 to support older data versions. This is especially important when we upgrade the API to higher versions, this upgrade can make a huge difference: changing the URL, the way the user is authenticated, or both the resource name and its structure.

REST API design conventions

Although the constraints and conventions on the developers do not need to adhere to. However, if done “right”, they will bring a lot of benefits.

Designing REST API URI

I have seen a lot of REST API designs written like this:

POST /create_post (create post)
GET /list_posts (get list of posts)
POST /feature_posts (list of featured posts)
POST /edit_post/:post_id (edit post with post_id)

REST APIs are not very well designed

These REST APIs are still working fine, no problem!! Only they don’t follow the convention. This leads to a hassle for the document maker (or the designer himself) to double check that the URL is correct. The API user side must also set up an API list as well.

Compare that with the following URL design:

POST /v1/posts (create a new post)
GET /v1/posts (get list of posts)
GET /v1/posts/:post_id (get post details with specific post_id)
PUT /v1/posts/:post_id (update posts with specific post_id)
DELETE /posts/:post_id (delete posts with specific post_id)

REST APIs are better designed, right convention

With this design, you will see that there is a very clear principle of using request methods to tell the mission of the API. The URI part can be the same, no need to contain verbs like: create, get, update, delete anymore. Resource name will be in the plural form (plural).

Some other examples:

GET /v1/posts/:post_id/liked-users (gets a list of users who liked a post with a specific post_id)
POST /v1/posts/:post_id/liked-users (like posts with specific post_id)
GET /v1/posts?page=2&limit=50 (use query string to filter or paginate)

Some REST APIs for other cases

Other conventions

  • Use the correct Status Code. If the API returns an error, please use the correct status, avoid always returning 2xx status when the body is an error message (this is a lot of you are doing it wrong).
  • Don’t use underscore (_), use hyphen (-) in URI
  • URIs are all lowercase letters.
  • Do not use file extensions (extensions) in URIs (eg .html, .xml, .json).

Full details of the REST API convention: https://restfulapi.net/resource-naming

Principles & Best practices of REST API Design

This best-practices article intends for developers interested in creating RESTful Web services that provide high reliability and consistency across multiple service suites; following these guidelines; services are positioned for rapid, widespread, public adoption by internal and external clients.

Here is the complete diagram to easily understand REST API’s principles, methods, and best practices.

Now, Let’s begin with elaborating on each box by starting with its principles.

The Six Principles / Constraints

  1. Client-Server: Separation of concerns is the principle behind the client-server constraints. By separating the user interface concerns from the data storage concerns, we improve the portability of the user interface across multiple platforms and improve scalability by simplifying the server components.
  2. Stateless: communication must be stateless, as in the client-stateless-server (CSS) style. Each request from the client to the server must contain all of the information necessary to understand the request. Session state is therefore kept entirely on the client.
  3. Cacheable: To improve network efficiency, we add cache constraints to form the client-cache-stateless-server style. Cache constraints require that the data respond to a request with the implicit or explicit label as cacheable or non-cacheable. If a response is cacheable, then a client cache is given the right to reuse that response data for later, equivalent requests.
  4. Layered System: A client cannot ordinarily tell whether it is connected directly to the end server or an intermediary along the way. Intermediary servers may improve system scalability by enabling load-balancing and by providing shared caches. Layers may also enforce security policies.
  5. Code-on-Demand: REST allows client functionality to extend by downloading and executing code in the form of applets or scripts. Simplifies clients by reducing the number of features required to be pre-implemented. It allows features to download after deployment improves system extensibility.
  6. Uniform Interface: By applying the software engineering principle of generality to the component interface, the overall system architecture becomes simplified, and the visibility of interactions is improved. Implementations decouple from the services they provide, which encourages independent evolvability. REST defines by four interface constraints: identification of resources, manipulation of resources through representations, self-descriptive messages, and Hypermedia as the engine of application state.
    Self-descriptive Messages: Each message includes enough information to describe how to process the message.
    Resource-Based: Individual resources are identified in requests using URIs as resource identifiers. The resources themselves are conceptually separate from the representations that return to the client.
    Manipulation of Resources Through Representations: When a client represents a resource, including any metadata attached, it has enough information to modify or delete the resource on the server, provided it has permission to do so.
    Hypermedia as the Engine of Application State (HATEOAS): Clients deliver state via body contents, query-string parameters, request headers, and the requested URI (the resource name). Services provide the state to clients via body content, response codes, and response headers.

Best Practices

Now, Let’s change the gear to understand REST’s essential best practice, which every engineer should know.

AWS re:invent 2021
  1. Keep it Simple and Fine-Grained: Create APIs that mimic your system’s underlying application domain or database architecture of your system. Eventually, you’ll want aggregate services — services that utilize multiple underlying resources to reduce chattiness.
  2. Filtering & Ordering: For large data sets, limiting the amount of data returned is vital from a bandwidth standpoint. Additionally, we may want to specify the fields or properties of a resource to be included in the response, thereby limiting the amount of data that comes back. We eventually want to query for specific values and sort the returned data.
  3. Versioning: There are many ways to break a contract and negatively impact your clients in API development. If you are uncertain of the consequences of your change, it is better to play it safe and consider Versioning. There are several factors to consider when deciding if a new version is appropriate or if a modification of an existing representation is sufficient and acceptable. Since maintaining many versions becomes cumbersome, complex, error-prone, and costly, you should support no more than two versions for any given resource.
  4. Cache: Caching enhances scalability by enabling layers in the system to eliminate remote calls to retrieve requested data. Services improve cache-ability by setting headers on responses such as Cache-Control, Expires, Pragma, Last-Modified, etc
  5. Pagination: One of the principles of REST is connectedness — via hypermedia links. At the same time, services are still helpful without them. APIs become more self-descriptive when links return in the response. For collections returned in a response that supports Pagination, ‘first’, ‘last’, ‘next’, and ‘prev’ links at a minimum are beneficial.
  6. Resource-Naming: An API is intuitive and easy to use when resources are named well. Done poorly, that same API can feel klutzy and be challenging to use and understand. RESTful APIs are for consumers. The name and structure of URIs should convey meaning to those consumers. It’s often difficult to know what the data boundaries should be, but with the understanding of your data, you most likely are equipped to take a stab and what makes sense to return as a representation to your clients. Design for your clients, not for your data.
    Pluralization: The commonly-accepted practice is always to use plurals in node names to keep your API URIs consistent across all HTTP methods. The reasoning is that `customers` are a collection within the service suite and the ID (e.g., 33245) refers to one of those customers in the collection.
  7. Monitoring: Make sure to add all kinds of monitoring to improve the quality or performance of your API. Data points can be Response Time (P50, p90, P99), Status Codes (5XX, 4XX, etc.), Network Bandwidth, and many more.
  8. Security:
    Authorization / Authentication: Authorization for services is no different than authorization for any application. Ask this question, “Does this principal have the requested permission on the given resource?”
    CORS: Implementing CORS on a server is as simple as sending an additional HTTP header in the response, such as Access-Control-Allow-Origin, Access-Control-Allow-Credentials, etc
    TLS: All authentication should use SSL. OAuth2 requires the authorization server and access token credentials to use TLS.
    Idempotence: an operation that will produce the same results if executed once or multiple times. It may have a different meaning depending on the context in which it applies. In the case of methods or subroutine calls with side effects, for instance, it means that the modified state remains the same after the first call.
    Input Validation: Validate all input on the server. Accept “known” good input and reject bad input, Protect against SQL and NoSQL injection, Restrict the message size to the exact length of the field, Services should only display generic error messages, and many more.
    Rate limiting: is a strategy for limiting network traffic. It puts a cap on how often someone can repeat an action within a certain timeframe — for instance, trying to log in to an account.
    Logging: Make sure you do not accidentally log any Personally identifiable information (PII).

With that I conclude this learning, I hope you have learned something new today.

References:

Leave a Reply

Your email address will not be published. Required fields are marked *