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.
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"}...
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
"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:
Article No Longer Available
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):
lenmorld / node_workshop
Build a server and API for your next web application, using Node, Express and MongoDB
Node workshop
Create a server + REST API for your next web application!
In this workshop, we’ll discuss concepts and put them to practice with activities, all about web servers The code and concepts here would be a great foundation for your next web project Topics include, but not limited to:
- Using Node and Express to build a web server and REST API
- Understanding routing, request and response
- Implementing CRUD with HTTP methods
- Building a server-rendered website using templates
- Connecting to a Cloud NoSQL database: MongoDB Atlas DB
- User authentication with sessions, cookies and tokens
- Using external APIs, such as Github Jobs, Giphy, Spotify
Previous Events
Material
Preview slides: Google Drive document
Material: Notion link
Code
to follow workshop:
$ git checkout dev
$ node server.js
to dev latest
$ git checkout master
$
…
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! 🛌😴
Top comments (1)
Great post, here is one more guide on how to do node js rest api codespot.org/how-to-build-rest-api...