Book Image

RESTful Web API Design with Node.js - Second Edition

By : Valentin Bojinov
Book Image

RESTful Web API Design with Node.js - Second Edition

By: Valentin Bojinov

Overview of this book

In this era of cloud computing, every data provisioning solution is built in a scalable and fail-safe way. Thus, when building RESTful services, the right choice for the underlying platform is vital. Node.js, with its asynchronous, event-driven architecture, is exactly the right choice to build RESTful APIs. This book will help you enrich your development skills to create scalable, server-side, RESTful applications based on the Node.js platform. Starting with the fundamentals of REST, you will understand why RESTful web services are better data provisioning solution than other technologies. You will start setting up a development environment by installing Node.js, Express.js, and other modules. Next, you will write a simple HTTP request handler and create and test Node.js modules using automated tests and mock objects. You will then have to choose the most appropriate data storage type, having options between a key/value or document data store, and also you will implement automated tests for it. This module will evolve chapter by chapter until it turns into a full-fledged and secure Restful service.
Table of Contents (12 chapters)
RESTful Web API Design with Node.js - Second Edition
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface

REST fundamentals


It actually happened back in 1999, when a request for comments was submitted to the Internet Engineering Task Force (IETF: http://www.ietf.org/) via RFC 2616: "Hypertext Transfer Protocol-HTTP/1.1." One of its authors, Roy Fielding, later defined a set of principles built around the HTTP and URI standards. This gave birth to REST as we know it today.

Note

These definitions were given in Chapter 5, Representational State Transfer (REST), of Fielding's dissertation called Architectural Styles and the Design of Network-based Software Architectures. The dissertation is still available at http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm.

Let's look at the key principles around the HTTP and URI standards, sticking to which will make your HTTP application a RESTful-service-enabled application:

  • Everything is a resource
  • Each resource is identifiable by a unique identifier (URI)
  • Use the standard HTTP methods
  • Resources can have multiple representations
  • Communicate statelessly

Principle 1 - everything is a resource

To understand this principle, one must conceive the idea of representing data by a specific format and not by a physical file. Each piece of data available on the Internet has a format that could be described by a content type. For example, JPEG images; MPEG videos; HTML, XML, and text documents; and binary data are all resources with the following content types: image/jpeg, video/mpeg, text/html, text/xml, and application/octet-stream.

Principle 2 - each resource is identifiable by a unique identifier

Since the Internet contains so many different resources, they all should be accessible via URIs and should be identified uniquely. Furthermore, the URIs can be in a human-readable format, despite the fact that their consumers are more likely to be software programs rather than ordinary humans.

Human-readable URIs keep data self-descriptive and ease further development against it. This helps you to reduce the risk of logical errors in your programs to a minimum.

Here are a few sample examples of such URIs:

These human-readable URIs expose different types of resources in a straightforward manner. In the example, it is quite clear that the media types of these resources are as follows:

  • Images
  • Videos
  • XML documents
  • Some kinds of binary archive documents

Principle 3 - use the standard HTTP methods

The native HTTP protocol (RFC 2616) defines eight actions, also known as HTTP verbs:

  • GET
  • POST
  • PUT
  • DELETE
  • HEAD
  • OPTIONS
  • TRACE
  • CONNECT

The first four of them feel just natural in the context of resources, especially when defining actions for resource data manipulation. Let's make a parallel with relative SQL databases where the native language for data manipulation is CRUD (short for Create, Read, Update, and Delete) originating from the different types of SQL statements: INSERT, SELECT, UPDATE, and DELETE, respectively. In the same manner, if you apply the REST principles correctly, the HTTP verbs should be used as shown here:

HTTP verb

Action

Response status code

GET

Requests an existing resource

"200 OK" if the resource exists, "404 Not Found" if it does not exist, and "500 Internal Server Error" for other errors

PUT

Updates a resource or creates it as an identifier provided from the client

"201 CREATED" if a new resource is created, "200 OK" if updated, and "500 Internal Server Error" for other errors

POST

Creates a resource with an identifier generated at server side or updates a resource with an existing identifier provided from the client

"201 CREATED" if a new resource is created,"200 OK" if the resource has been updated successfully, "404 Not Found" if the resource to be updated does not exist, and "500 Internal Server Error" for other errors

DELETE

Deletes a resource

"200 OK"or "204 No Content" if the resource has been deleted successfully, "404 Not Found" if the resource to be deleted does not exist, and "500 Internal Server Error" for other errors

Note that a resource can be created by either of POST or PUT HTTP verbs. When a resource has to be created under a specific URI with an identifier provided by the client, then PUT is the appropriate action:

PUT /data/documents/balance/22082014 HTTP/1.1
Content-Type: text/xml
Host: www.mydatastore.com

<?xml version="1.0" encoding="utf-8"?>
<balance date="22082014">
<Item>Sample item</Item>
<price currency="EUR">100</price>
</balance>

HTTP/1.1 201 Created
Content-Type: text/xml
Location: /data/documents/balance/22082014   

However, in your application, you may want to leave it up to the server REST application to decide where to place the newly created resource, and thus create it under an appropriate but still unknown or non-existing location.

For instance, in our example, we might want the server to create the date part of the URI based on the current date. In such cases, it is perfectly fine to use the POST verb to the main resource URI and let the server respond with the location of the newly created resource:

POST /data/documents/balance HTTP/1.1
Content-Type: text/xml
Host: www.mydatastore.com

<?xml version="1.0" encoding="utf-8"?>
<balance date="22082014">
<Item>Sample item</Item>
<price currency="EUR">100</price>
</balance>

HTTP/1.1 201 Created
Content-Type: text/xml
Location: /data/documents/balance  

Principle 4 - resources can have multiple representations

A key feature of a resource is that it may be represented in a different form than the one it is stored. Thus, it can be requested or posted in different representations. As long as the specified format is supported, the REST-enabled endpoint should use it. In the preceding example, we posted an XML representation of a balance, but if the server supported the JSON format, the following request would have been valid as well:

POST /data/documents/balance HTTP/1.1
Content-Type: application/json
Host: www.mydatastore.com

{
  "balance": {
    "date": ""22082014"",
    "Item": "Sample item",
    "price": {
      "-currency": "EUR",
      "#text": "100"
    }
  }
}
HTTP/1.1 201 Created
Content-Type: application/json
Location: /data/documents/balance   

Principle 5 - communicate statelessly

Resource manipulation operations through HTTP requests should always be considered atomic. All modifications of a resource should be carried out within an HTTP request in isolation. After the request execution, the resource is left in a final state, which implicitly means that partial resource updates are not supported. You should always send the complete state of the resource.

Back to the balance example, updating the price field of a given balance would mean posting a complete JSON document that contains all of the balance data, including the updated price field. Posting only the updated price is not stateless, as it implies that the application is aware that the resource has a price field, that is, it knows its state.

Another requirement for your RESTful application is to be stateless; the fact that once deployed in a production environment, it is likely that incoming requests are served by a load balancer, ensuring scalability and high availability. Once exposed via a load balancer, the idea of keeping your application state at server side gets compromised. This doesn't mean that you are not allowed to keep the state of your application. It just means that you should keep it in a RESTful way. For example, keep a part of the state within the URI.

The statelessness of your RESTful API isolates the caller against changes at the server side. Thus, the caller is not expected to communicate with the same server in consecutive requests. This allows easy application of changes within the server infrastructure, such as adding or removing nodes.

Tip

Remember that it is your responsibility to keep your RESTful APIs stateless, as the consumers of the API would expect it to be.

Now that you know that REST is around 15 years old, a sensible question would be, "why has it become so popular just quite recently?" My answer to the question is that we as developers usually reject simple, straightforward approaches, and most of the time, prefer spending more time on turning already complex solutions into even more complex and sophisticated ones.

Take classical SOAP web services for example. Their various WS-* specifications are so many and sometimes so loosely defined, that in order to make different solutions from different vendors interoperable, a separate specification WS-Basic Profile has been introduced.It defines extra interoperability rules in order to ensure that all WS-* specifications in SOAP-based web services can work together.

When it comes to transporting binary data with classical web services over HTTP, things get even more complex—as SOAP-based web services provide different ways of transporting binary data. Each way is defined in other sets of specifications such as SOAP with Attachment References (SwaRef) and Message Transmission Optimization Mechanism (MTOM). All this complexity was caused mainly because the initial idea of the web service was to execute business logic remotely, not to transport large amounts of data.

Well, I personally think that when it comes to data transfer, things should not be that complex. This is where REST comes into play, by introducing the concept of resources and a standard means for manipulating them.