Node.js is runtime environment for Javascript.
It became quite popular from its inception in 2009.
For detailed history you can read it here
Express.js is unopinionated web development framework. It’s built on top of the Node.js. We could ideally write our code in pure Node.js code but we might end up building another express.js. Because express.js is already quite popular and well tested, we will use its power and capability to build APIs faster.
Download the node.js installer from this link.
To verify that node is installed successfully, type node in the terminal or console. It should enter to node console where you can run write javascript code snippets and run it.
Arvinds-MacBook-Pro:cscamp.org arvind$ node >
If you see anything else then there is some problem with your setup.
Before building the actual APIs, let define the contract. Contract is nothing but agreeing product’s interface and what it will return.
// CRUD POST /todos // C --> Create GET /todos // R --> Read GET /todos/:id // R --> Read PUT /todos/:id // U --> Update DELETE /todos/:id // D --> Delete
a. Create a directory called todo-app
mkdir todo-app
b. Go inside the directory
$ cd todo-app
c. Create a npm project using npm init command. Provide on screen inputs.
$ npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg>` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. package name: (todo-app) version: (1.0.0) description: todo app entry point: (index.js) app.js test command: git repository: keywords: author: Arvind Pandey license: (ISC) About to write to /Users/arvind/Documents/todo-app/package.json: { "name": "todo-app", "version": "1.0.0", "description": "todo app", "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Arvind Pandey", "license": "ISC" }
This will create a file called package.json This file is a kind of manifest of the application.
If you look at the content of the package.json, it would similar to below file content.
{ "name": "todo-app", "version": "1.0.0", "description": "todo app", "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Arvind Pandey", "license": "ISC" }
The interesting thing here is the entry point app.js We will come to that very soon.
We need to add express.js to the project before we proceed further. Run below command.
npm install express --save
It will install latest stable express version and it will add express as dependency in package.json.
Now is the time to write some code. Create app.js and write below code.
const express = require('express'); const app = express(); const PORT = 4000; app.listen(PORT, ()=>{ console.log(`Listening on port ${PORT}`); })
Let’s go line by line to see what’s happening.
Line 1: It’s very similar to import statement in Java.
We are getting the reference of express library. That we will use to create the app.
Line 2: Creating the app by invoking the express().
Line 3: Defining a variable PORT that we will use to run our app on.
Line 4: Invoking listen() function to bind a port to the app.
Line 5: listen() function accepts 2 arguments.
First argument is the port and second is a call back function. Line 5 is the body of the call back function.
Not doing anything fancy, just printing some message on the console.
Start the server with below command.
node app.js
If you see below message on the console then your server started successfully. Yay!
$ node app.js Listening on port 4000
If we understand the first route, others will be quite similar.
Let’s add root route to our app. When some hits the root path what do we want to return.
app.get('/', (req, res) => { res.send({'path':'home page'}); });
Let’s see what is happening.
The first argument is the request object and second is the response object. We are not expecting anything from request object so, we are not bothering it.
We are just sending back the sample json response.
Stop the server and restart again.
node app.js
Go to the browser and hit the url http://localhost:4000/
You should see the below json response on your browser.
{ "path": "home page" }
That concludes the first route. It was quite minimal and easy to digest. (I hope so!).
We are going to cover remaining routes. Before that install an API client like postman to test the rest interface.
The typical todos just contain the list of tasks to accomplish. For us just one field is enough to store the data, the task field. Because we are not dealing with database here, we expect id also to be passed when creating the To-Do.
Below is the sample POST request body.
{ 'id': '1', 'task': 'write article on javascript' }
We will store all the To-Dos in an array of objects.
Add below code snippet to app.js file. Restart the server.
app.use(express.json()); let todos = []; app.post('/todos', (req, res) => { todos.push(req.body); res.send({ 'message':'success' } ); })
This does the very minimum thing. If you try doing a post call using postman client, you should be able to post the todos.
There are so many things wrong about the code above. Here are few of them.
Keeping that in the mind, here is few things, we should do to make it more robust.
Below code snippet does the basic house keeping that is mentioned above.
app.use(express.json()); let todos = []; app.post('/todos', (req, res) => { try { if(req.body.id == null || req.body.task == null) { res.json({'message':'id and task fields are mandatory to pass in the body'}); return; } if (todos.filter((item) =>req.body.id == item.id).length > 0) { res.status(500); res.json({'error':'use unique id'}); } else { todos.push(req.body); res.json({ 'message':'success' } ); } } catch (error) { res.status(500); res.json({'error':'something went wrong'}); } }) app.listen(PORT, ()=>{ console.log(`Listening on port ${PORT}`); })
Now, our POST API is in good shape. You can try with postman. Test both positive and negative scenarios.
That concludes the first route.
Now that we have created the todos, we need API to get all the todos. We need define a GET API call.
Copy and paste below code snippted and restart the server.
app.get('/todos', (req, res) => { res.send(todos); });
Now, restart you server. Using postman perform below steps.
We can retrieve a todo by its id. Below is the code snippted. You can copy and past to app.js
app.get('/todos/:id', (req, res) => { try { if (todos.filter((item) =>req.params.id == item.id).length > 0) { let r = todos.find(item => item.id == req.params.id); res.send(r); } else { res.send({'message': `no result found with id: ${req.params.id}`}); } } catch (error) { res.status(500); res.json({'error':'something went wrong'}); } });
app.put('/todos/:id', (req, res) => { try { if(req.body.task == null) { res.json({'message':'id and task fields are mandatory to pass in the body'}); return; } if (todos.filter((item) =>req.params.id == item.id).length > 0) { todos.find(item => item.id == req.params.id).task = req.body.task res.json({'message':'update successful'}); } else { res.json({'message': `no todo found with id: ${req.params.id}`}); } } catch (error) { res.status(500); res.json({'error':'something went wrong'}); } })
app.delete('/todos/:id', (req, res) => { try { if(todos.filter(item => item.id == req.params.id).length > 0) { let r = todos.filter(item => item.id != req.params.id); todos = [...r]; res.json({'message':'success'}); } else { res.json({'message': `no todo found with id: ${req.params.id}`}); } } catch (error) { res.status(500); res.json({'error':'something went wrong'}); } })
We have covered all the routes. Let’s test each route one by one.
I hope you have already installed Postman client.
You can find complete source code at Github. Here is the link.
Happy Learning!
Quick Links
Legal Stuff