Friday, July 30, 2021

RESTful Web Services – Supporting CRUD Operations

Welcome to part 2 of this series on RESTful Web Services! In part 1 we set up a basic Web service using Node.js and the Express framework. In this tutorial we’ll learn what makes a service RESTful by adapting our Web server that we built in part 1 to handle different request types.

REST Service Request Types

As mentioned in part 1, REST stands for REpresentational State Transfer. This means there is no state between the client and the server. This is the whole point of using REST – it makes the connection stateless so that any client that utilizes the HTTP protocol can access the data. The client can then iterate through the data and display it anywhere he/she chooses. Moreover, our server isn’t restricted to browsers only. Native apps and IoT devices can also access the service so long as they implement the HTTP protocol.

There are a few types of HTTP methods that we need to know before building a REST API. These are the methods that correspond to the CRUD (Create, Read, Update, and Delete) operations:

  • POST: Used to submit data, typically used to Create new entities or edit already existing ones.
  • GET: Used to request data from the server, typically used to Read data.
  • PUT: Used to completely replace the resource with the submitted resource, typically used to Update data.
  • DELETE: Used to Delete an entity from the server.

Note that you can use either POST or PUT to edit stored data. You’re free to choose whether you even want to use PUT since it may be omitted. In order to stay consistent with the HTTP verbs you use, if you’re using POST to both create and update, you probably shouldn’t implement the PUT method at all.

What’s the Difference Between REST and an API?

API – short for Application Programming Interface – is a very broad term that dictates how one piece of code talks to another. In web development, API often refers to the way in which we retrieve information from an online service. The API documentation should give you a list of URLs, query parameters and other information on how to make a request from the API, and inform you as to what sort of response will be provided from each endpoint.

Meanwhile, REST is a set of rules/standards/guidelines for how to build a web API. Since there are many ways to do so, having an agreed upon system of structuring an API saves time in making decisions when building one, as well as in understanding how to use it.

Hence, REST is a type of API, and while not all APIs are REST, all REST services are APIs.

Refactoring the Demo to Handle CRUD Operations

The server that we built in Part 1 of this series was only a bare-bones web server that responded to GET requests. Now we’ll turn it into a true RESTful Web service by adding endpoints for CRUD operations that we’ll apply to a collection of vehicles. Normally, the service would persist data in a database or perhaps even send the data along to another service. For our app, we’ll keep things simple by employing an object variable:

let vehicles = {
  1: {
    id: 1,
    make: "Honda",
    model: "Accord",
    year: 2020,
    color: "grey",
    plateNumber: "ES6 3G6",
    vin: "1G1ZT51806F128009"
  },
  2: {
    id: 2,
    make: "Infiniti",
    model: "G37",
    year: 2009,
    color: "blue",
    plateNumber: "RW4 993",
    vin: "JH4KA3240HC002301"
  },
  3: {
    id: 3,
    make: "Porsche",
    model: "Macan",
    year: 2019,
    color: "red",
    plateNumber: "6HG 2ER",
    vin: "JH4KA3160KC018606"
  }
};

Implementing Express Routes

In Web apps the term “Routing” refers to how an application’s endpoints (URIs) respond to client requests. Express routes are define using methods of the Express app object that correspond to HTTP methods; for example, app.get() handles GET requests and app.post() handles POST requests. The application then listens for requests that match the specified route(s) and method(s), and when it detects a match, it calls the specified callback function.

Previously we implemented one Express route for GET requests that match the “/” root URI. Let’s set up more routes to accommodate a RESTful API. Add the following routes to your Express application whereby the URI itself doesn’t change. Instead, the method invoked from your Express instance is bound to the request type:

app.get("/vehicles", (req, res) => {
  return res.send("GET HTTP method on user resource");
});

app.post("/vehicles", (req, res) => {
  return res.send("POST HTTP method on user resource");
});

app.put("/vehicles", (req, res) => {
  return res.send("PUT HTTP method on user resource");
});

app.delete("/vehicles", (req, res) => {
  return res.send("DELETE HTTP method on user resource");
});

Some of the above endpoints are easier than others to hit with a browser. Here’s the response for the “/vehicles” route:

get response

Fetching Vehicle Details

With our vehicle data in place, there’s no reason why we can’t return vehicle details inside of the GET handler:

app.get("/vehicles", (req, res) => {
  return res.send(Object.values(vehicles));
});

We can also retrieve a specific vehicle to the user by specifying a key – in this case, the id. In REST, this is accomplished using a parameterized URL. By adding a colon (:) to the path, we can define a variable that we can access via the req.params array:

app.get("/vehicles/:vehicleId", (req, res) => {
  return res.send(vehicles[req.params.vehicleId]);
});

Based on the above endpoint, if a user visits localhost:3000/vehicle/3 the vehicleId parameter will be 3.

We can accept more than one parameter in the URL if it makes sense to do so. In fact, I recently had to do that by defining an endpoint of theme-details/:themeId/theme-holdings/:exchange, where the parameters were available via req.params.themeId and req.params.exchange respectively.

Here is the response for the /vehicles endpoint:

all vehicles

And here are the details for the 2nd vehicle using endpoint /vehicles/2:

2nd vehicle

Conclusion

In part 2 of this series on RESTful Web Services we learned what makes a service RESTful by adapting our web server that we built in part 1 to handle a several different request types. The updated server now includes fully functional GET handlers as well as stubs for other request types. Give them a try by clicking on the links in the demo below. You can get back to the demo page after a request by refreshing the built-in demo browser.

Rob Gravelle
Rob Gravelle
Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.

Popular Articles

Featured