Building REST service with Express.js
Submitted by admin on Tuesday, December 6, 2016 - 21:41.
REST services became a de-facto standard of data exchange for public APIs. Twitter, GitHub, Parse are just few examples that rely on REST to exchange data with the clients.
Before we start to write our first REST service with Node, let's see what exactly is REST and how it works. REST stands for 'REpresentational State Transfer'. It leverages the semantics of HTTP protocol to express operations over a some collection of items (data). REST typically uses JSON to send and receive data.
NOTE: This is a common misconception to call every HTTP-based JSON service REST. This is not correct RESTful service can exchange data using any format: JSON, XML, YAML or anything else. JSON turned out to be the most popular format but it is in no way a dogma.
REST relies on HTTP methods to express what you do with data.
This app is not doing much, so let's add a route to get the whole collection of books. Also, I'll create an array to hold book objects. In a real-world scenario, REST services are backed up by databases (or other upstream services) but for the sake of this example, an array will be a perfect fit.
Now we can test the service with curl - a command line HTTP client (download curl if it is not available on your system).
Our code has just become much cleaner as we are not using pre-defined "magic" IDs, but instead relying on a function to generate and ID each time it is needed. We could also swap the implementation to use UUID instead of sequential integers, for example.
Now its time to add a route:
And test it:
Here's how you would test the route:
This route is also trivial, it finds the index of the book in array by its ID and then removes it from the array.
Let's test if we can really delete books:
As you see, it took less than 40 lines of code to create a simple REST service with express.js. For production use you would add more features like error checking and reporting, logging, authentication, integration with database. However this code will be a good starting point for your experiments.
GET
to retrieve an item (or collection), POST
to add new item to collection, PUT
to update the whole item, DELETE
to remove an item. Sometimes PATCH
is also used to update *part* of an item but this is rather rare.
Now let's implement a simple REST service with Node.js and Express.js framework. Our goal is to expose a collection of books.
In the new folder run npm init
, and create package.json
as you usually do for every fresh Node project. Now let's install the dependencies:
> npm install --save express body-parser
Now we are ready to build our main.js file. Let's start from initializing express, and adding body-parser
middleware.
- const express = require('express');
- const bodyParser = require('body-parser');
- const app = express();
- app.use(bodyParser.json());
- app.listen(3000, () => {
- console.log('Book REST is on 0.0.0.0:3000!');
- });
- const books = [
- {
- id: 1,
- title: 'The Time Machine'
- },
- {
- id: 2,
- title: 'Atlas Shrugged'
- }
- ];
- app.get('/books', (req, res) => {
- res.json(books);
- });
$ curl localhost:3000/books
If everything is set correctly, the server should respond with:
[{"id":1,"title":"The Time Machine"},{"id":2,"title":"Atlas Shrugged"}]
Now let's see how to add a new book. Besides making a new route, we'll have to create a function that generates the new ID for a book each time you add one. This is a great place to use EcmaScript-2016 generators feature. Let's write a `getId()` generator function and then use in places where we need to get new ID.
- const idGenerator = function* () {
- let max = 0;
- while(true) {
- yield ++max;
- }
- };
- const gen = idGenerator();
- const books = [
- { id: gen.next().value, title: 'The Time Machine' },
- { id: gen.next().value, title: 'Atlas Shrugged' }
- ];
- app.post('/books', (req, res) => {
- const book = Object.assign({ id: nextId() }, req.body);
- books.push(book);
- res.json(book);
- });
curl -X POST -H "Content-Type: application/json" -d "{\"title\": \"Three Comrades\"}" localhost:3000/books
Next, we'll make the books editable. To do that, we have to implement PUT route:
- app.put('/books/:id', (req, res) => {
- const book = books.find((b) => b.id === +req.params.id);
- Object.assign(book, req.body);
- res.json(book);
- });
curl -X PUT -H "Content-Type: application/json" -d "{\"title\": \"Edited Title\"}" localhost:3000/books/1
Finally, to complete the set of basic operations, we need to create DELETE route:
- app.delete('/books/:id', (req, res) => {
- const idx = books.findIndex((b) => b.id === +req.params.id);
- const book = books.splice(idx, 1);
- res.json(book);
- });
curl -X DELETE localhost:3000/books/1
The returned book is the one that you just deleted!
Here's the full source code of our node.js application:
- const express = require('express');
- const bodyParser = require('body-parser');
- const idGenerator = function* () {
- let max = 0;
- while(true) {
- yield ++max;
- }
- };
- const gen = idGenerator();
- const books = [
- { id: gen.next().value, title: 'The Time Machine' },
- { id: gen.next().value, title: 'Atlas Shrugged' }
- ];
- const app = express();
- app.use(bodyParser.json());
- app.get('/books', (req, res) => {
- res.json(books);
- });
- app.post('/books', (req, res) => {
- const book = Object.assign({ id: nextId() }, req.body);
- books.push(book);
- res.json(book);
- });
- app.put('/books/:id', (req, res) => {
- const book = books.find((b) => b.id === +req.params.id);
- Object.assign(book, req.body);
- res.json(book);
- });
- app.delete('/books/:id', (req, res) => {
- const idx = books.findIndex((b) => b.id === +req.params.id);
- const book = books.splice(idx, 1);
- res.json(book);
- });
- app.listen(3000, () => {
- console.log('Book REST is on 0.0.0.0:3000!');
- });
Add new comment
- 91 views