loading...
Cover image for REST API with Node and Express in 5 minutes

REST API with Node and Express in 5 minutes

lennythedev profile image Lenmor Ld Updated on ãƒŧ4 min read

Part 2 of Node + Express series

Now that we have our first Node + Express server from Part 1
we can now get some REST!

Rest 🛌ðŸ˜ī ???
Not that rest, but REST (Representational state transfer), which is basically providing an API to clients via HTTP Methods.

rest_api

SPOILER ALERT ðŸ˜ąðŸ˜œ
We can map basic operations like CRUD to certain HTTP methods.
Skip if you don't like spoilers or looking at table confuses you ðŸ˜ĩ.

CRUD Operation HTTP method URL URL params Request body example
Create POST /items body: {...} POST /items body: {...}
Read One GET /items/:id :id (item id) GET /items/123
Read All GET /items GET /items
Update PUT /items/:id :id (item id) body: {...} PUT /items/123 body:{...}
Delete DELETE /items/:id :id (item id) DELETE /items/123

Note that this is a common way of doing this, but you can also implement, say POST for UPDATE and DELETE. Check out Idempotence in REST for details on that.

Let's get started!

Sample data

First, we need some sample data. Let's use some of the movies 🎞ïļ in IMDB's top 250, since my movie choices are probably not reliable ðŸĪŠ

Create data.js file. Feel free to add items, and item details.

// data.js
module.exports = [
    { "id": "tt0110357", "name": "The Lion King", "genre": "animation"},
    { "id": "tt0068646", "name": "The Godfather", "genre": "crime"},
    { "id": "tt0468569", "name": "The Dark Knight", "genre": "action"},
];

module.exports exposes this array to other files

Import file in our server.js file

// server.js
let data = require('./data');
...


// our API routes go here

GET

Get all items
GET /items

server.get("/items", (req, res) => {
   res.json(data);
});

Get one item identified by :id
GET /items/:id

We use Array.find to get the first item that matches the condition,
then display a message if not found.

Note that the item id is a string e.g. tt0110357, so we can compare it using=== directly.
You'll have to parse before comparing, if you are using an integer id.

server.get("/items/:id", (req, res) => {
   const itemId = req.params.id;
   const item = data.find(_item => _item.id === itemId);

   if (item) {
      res.json(item);
   } else {
      res.json({ message: `item ${itemId} doesn't exist`})
   }
});
$ curl http://localhost:4000/items
[{"id":"tt0110357","name":"The Lion King","genre":"animation"},{"id":"tt0068646","name":"The Godfather","genre":"crime"},{"id":"tt0468569","name":"The Dark Knight","genre":"action"}]

$ curl http://localhost:4000/items/tt0110357
{"id":"tt0110357","name":"The Lion King","genre":"animation"}

$ curl http://localhost:4000/items/blahblah
{"message":"item blahblah doesn't exist"}

POST

To encode the body of the request sent by client in a POST message, we need body-parser middleware.
This allows us to use req.body in our route handler

npm install body-parser

Then we import and use it. We'll just accept JSON-encoded body for now.

// server.js

const body_parser = require('body-parser');

// parse JSON (application/json content-type)
server.use(body_parser.json());

Post an item
POST /items

Here, we are getting entire item from req.body since it matches our data,
but note that it is also possible to just get, e.g. req.body.name

// server.js

...
server.post("/items", (req, res) => {
   const item = req.body;
   console.log('Adding new item: ', item);

   // add new item to array
   data.push(item)

   // return updated list
   res.json(data);
});
$ curl -X POST -H "Content-Type: application/json" --data '{"id": "tt0109830", "name": "Forrest Gump", "genre": "drama"}' http://localhost:4000/items

[..., {"id":"tt0109830","name":"Forrest Gump","genre":"drama"}]

PUT

To update an item, we expect client to pass item id in the URL param (req.params.id)
and the updated object in the body (req.body)

Here we simply replace the old one using forEach, but you could apply your own
algorithm to replace an object or an object's attribute in an array of objects.


// update an item
server.put("/items/:id", (req, res) => {
   const itemId = req.params.id;
   const item = req.body;
   console.log("Editing item: ", itemId, " to be ", item);

   const updatedListItems = [];
   // loop through list to find and replace one item
   data.forEach(oldItem => {
      if (oldItem.id === itemId) {
         updatedListItems.push(item);
      } else {
         updatedListItems.push(oldItem);
      }
   });

   // replace old list with new one
   data = updatedListItems;

   res.json(data);
});

Let's say you really think The Dark Knight is a drama ðŸ˜Ē instead of action,...

$ curl -X PUT -H "Content-Type: application/json" --data '{"id": "tt0468569", "name": "The Dark Knight", "genre": "drama"}' http://localhost:4000/items/tt0468569

...{"id":"tt0468569","name":"The Dark Knight","genre":"drama"}...

batman_drama

DELETE

Lastly for delete, we only need id URL param from client.
We filter the array, excluding the item to be deleted.

// delete item from list
server.delete("/items/:id", (req, res) => {
   const itemId = req.params.id;

   console.log("Delete item with id: ", itemId);

   // filter list copy, by excluding item to delete
   const filtered_list = data.filter(item => item.id !== itemId);

   // replace old list with new one
   data = filtered_list;

   res.json(data);
});
$ curl -X DELETE http://localhost:4000/items/tt0468569

[{"id":"tt0110357","name":"The Lion King","genre":"animation"},{"id":"tt0068646","name":"The Godfather","genre":"crime"}]

Complete Code in this link

Quick REST API with Node + Express

hackerman

"Okay, that was nice. But what can I do with this? "

Add a few more CRUD routes, and you have a nice REST API for your clients!

Although, you might have noticed that the changes are not persisted yet
when the server is restarted. ðŸ˜ą

We'll cover this in upcoming articles about File Read/Write and MongoDB. Stay tuned.

Next up:

This article is part of a Node+Express series I'm working on.

For the meantime, if you can't get enough of Node+Express ðŸĪ“,
checkout my Node workshop (Gihub repo and slides):

GitHub logo lenmorld / node_workshop

Build an API for your next web application, using Node, Express and MongoDB

Node workshop

to follow workshop:

$ git checkout dev
$ node server.js

to dev latest

$ git checkout master
$ npm start

Create a .env file on root

NODE_ENV=development
PORT=4000
MONGO_DB_CONNECTION_STRING=YOUR_CONNECTION_STRING_HERE
# API keys go here





Here we discussed:
  • Using Node and Express
  • Routing, request and response
  • Building a REST API
  • Server-rendered templates
  • Connecting to a NoSQL (mongo) database
  • Using external APIs, such as Spotify
  • and much more!

Happy server-ing!

Now, time to get some real rest.
Don't forget to get plenty! 🛌ðŸ˜ī

sleep

Posted on by:

lennythedev profile

Lenmor Ld

@lennythedev

webdev @ Autodesk | Someone used to call me "Learn more", and I'm spending forever to live up to it. You'll find me dabbling in random stuff ðŸ‘Ļ‍ðŸ’ŧ or missing a wide open shot in 🏀

Discussion

markdown guide
 

Great post, here is one more guide on how to do node js rest api codespot.org/how-to-build-rest-api...