Build a REST API with Node JS & Express for Beginner
Tags: javascript, restapi, node, express
Published: 2022-12-07 06:45:43

---
title: Build a REST API with Node JS & Express for Beginner
published: true
description: Build a REST API with Node js & Express for Beginner
tags: javascript, restapi, node, express
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
---
### We can create web server using HTTP module

```
const http = require('http');

const server = http.createServer((req, res) => {
    if(req.url === '/'){
        res.write('Hellow world');
        res.end();
    }
    if(req.url === '/api/customers'){
        res.write(JSON.stringify([1,2,3]));
        res.end();
    }
});

server.listen(3000);
console.log('Listening on port 3000...')
```
Here we have a callback function that takes two parameters request and response and with this request object we can check the `URL` of of the incoming request we with this we can define various routes for our application. 

So if you have a request for let's say slash API slash customers this is how we're going to respond to the client. Now while this approach certainly works it's not very maintainable because as we defined more routes for our application we need to add more if blocks in this callback function. 

That's when a framework comes into the picture framework. A framework gives our application a proper structure so we can easily more routes while keeping our application code maintainable. Now there are various framework out there for building web application and web servers on top of note. The most popular one is `Express`. 

It's also very fast lightweight and perfectly documented.

Now create a `restapi` folder. Let's go inside this folder and run `npm init --yes`. So now we have a package JSON file. Finally we can install `npm i express`. 

### Build web server using Express
Create new file `index.js`. Express module so we use our require function give it the name our module which is `Express`. 

`require('express')` This returns a function we call that express.

```
const express = require('express')
``` 
We need to call this function like this and as you can see this returns an object of type Express by convention we call this object app so we store the result in a `constant` called  `app` 
 
```
const app = express();
```
So this represents our application now app object has bunch of useful methods we have methods like `get post put delete`  
```
app.get()
app.post()
app.put()
app.delete()
```
All these methods correspond HTTP verbs or HTTP methods. 

You want to HTTP post request to an endpoint you would use `app.post()`. 

HTTP GET request so this method takes two arguments the first arguments is the pass or the URL so here I'm going to use slash to represent the route of the website. Now the second argument is the `callback function` this is the function that will be called when we have an `HTTP GET` request to this endpoint. So callback function shall have two arguments request `request, response`. So this goes to a code block now this request object has a bunch of useful properties that gives us information about the incoming request.  
When we get an HTTP GET request to the root of our website you're gonna respond with Hello World message. So this is how we define a route we specify the path or the URL and callback function which is also called route handler. 

Now finally we need to listen on a given point so we call app that listen we give a port number like 3000 and optionally we can pass a function that will be called when the application stats listening on the given port so once again we use the `arrow function syntax` to display something on the console. 

```
app.listen(3000, () => console.log('Listening on port 3000'))
```  
Now back in the terminal and run `node index.js`

![Listening port](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/byt6svl2fjzqd8abyvc8.png)

Now let's define another route
```
app.get('/api/courses', (req, res) => {
    res.send([1,2,3])
})
```
I'm gonna simply return an array of numbers so response that's send and it passed an array of three numbers. 
> Back in the terminal we have to stop this process and started again. So press `ctrl + c` one more time `node index.js` 

In this implementation we don't have those if block we define new routes. 

Express gives our application is skeleton is structure. 

#### nodemon
So far you have noticed that every time we make a change to this code you have to go back in the terminal and stop this process and started again. I'm gonna show you better way we're gonna install node package called **nodemon**. Install the command `npm i -g nodemon`

Instead of running our application using node we use nodemon. 
Back to the terminal and run `nodemon index.js`

![using nodemon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mh13jm8v67uggxt794pa.png)

### Environment Variables
Now one thing we need to improve in this code is this hard-coded value for the port so we have used 3000 as number while this may work on you development machine it's unlikely that this gonna not work in production environment because when deploy this application to a hosting environment the port is dynamically assigned by the hosting environment. So we can't rely on 3000 to be available. So the way to fix this is by using an environment variable. 

Outside the application I'm gonna show you how that works. In this application we need to read the value of this port environment variable and the way we do that is by using `process object`. 

We have this global object called process this object has bunch of property. 

```
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}`))
```
The name of our environment variable in this case port so if this is set we're gonna use this otherwise we're gonna use 3000. Now we can store the result in a `constant` called port. 

Finally let's delete this and finally we need to replace with port and also change message accordingly.  

### Handling GET request
Create a route to get a single course. 

```
app.get('/api/courses/:id', (req, res)=> {
    res.send(req.params.id)
})
```
Could be course ID or courseId but ID is shorter and more conventional now we had our route handler function. 

Now we have two endpoints what to get all the courses and the other two get a single course. 

```
app.get('/api/courses', (req, res) => {
    res.send([1,2,3])
})
// /api/courses/1
app.get('/api/courses/:id', (req, res)=> {
    res.send(req.params.id)
})
``` 

```
app.get('/api/courses/:id', (req, res)=> {
    // res.send(req.params.id)
   const course = courses.find(c => c.id === parseInt(req.params.id))
   if(!course){
       res.status(404).send('The course with the give ID was not found')
   }
   res.send(course)

})
```

### Handling POST request 
So far we have created two routes that respond HTTP GET request and use this route to get all the courses as well as single course. 

We use an HTTP POST request to create a new course. 
```
app.post('/api/courses', (req, res) => {

})
```
In this route handler we need to read the course object that should be in the body of the request  use these properties to create a new course object and then add that course object to our courses array. 

```
app.post('/api/courses', (req, res) => {
    const course = {
        id: courses.length + 1,
        name: req.body.name
    }
})
```
We need to call app that `app.use(express.json())`. Adding a piece of middleware. To use this middleware in the request processing pipeline again. 

```
app.post('/api/courses', (req, res) => {
    const course = {
        id: courses.length + 1,
        name: req.body.name
    }
    courses.push(course)
})
```
> And finally by convention when we post an object to the server when the server creates a new object or new resources you should return that object in the body of the response. 

```
app.post('/api/courses', (req, res) => {
    const course = {
        id: courses.length + 1,
        name: req.body.name
    }
    courses.push(course)
    res.send(course)
})
```
![Post request](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z9lcqpp3xuczr2fxm4af.png)
we can see the status of the request is 200 which means the request was handled successfully. Also see body of the response.

We send to the server so this is how we test HTTP service is in Postman. 

> We have assumed that there is an object with name property in the body of the request what if the client forgets to send this property or send an invalid name.  

### Input validation

As a security best practice you should never ever ever trust what client send you. You should always validate the input. 

```
app.post('/api/courses', (req, res) => {
    if(!req.body.name || req.body.name.length < 3){
    }
})
``` 
Doesn't exist or request that body the name that length is less than 3 then we're gonna an error to the client.
 
> The restful convention is to return a response with the HTTP status code or 400 that means bad request. 

```
app.post('/api/courses', (req, res) => {
    if(!req.body.name || req.body.name.length < 3){
        res.status(400).send('Name is required and should be minimum 3 character.')
    }   
    return;
    const course = {
        id: courses.length + 1,
        name: req.body.name
    }
    courses.push(course)
    res.send(course)
})
```
**validation with joi** `npm i joi`
Store it in a constant called `Joi`
```
const Joi = require('joi')
```
So we have this `Joi` class now packing our route handler now with `Joi` first we need to define a schema. Schema defines the shape of our objects. 
```
const schema = {
        name: Joi.string().min(3).required();
    }
    Joi.validate(req.body, schema)
```
This validate method returns an object let's store that in a constant `result`

### Handling PUT request
Update a course so let's add a new route handler app we use the put method for updating resources. 

```
app.put('/api/courses/:id', (req, res)=> {
    // look up the course
    // if not existing, return 404
    const course = courses.find(c => c.id === parseInt(req.params.id))
    if(!course){
        res.status(404).send('The course with the give ID was not found')
    }
    // validate the coruse
    // if invalid, return 400 - Bad request
    if(!req.body.name || req.body.name.length < 3){
        res.status(400).send('Name is required and should be minimum 3 character.');
        return;
    } 

    // update course
    // return the update course
   course.name = req.body.name;  
   res.send(course)
})
```

### Handling DELETE request
It is very simple and similar to what we have done so far. We need to find the index of this course in our courses array. We can use this splice method to remove and object from our courses array.

```
app.delete('/api/courses/:id', (req, res)=> {
    // look up the course
    // if not existing, return 404
    const course = courses.find(c => c.id === parseInt(req.params.id))
    if(!course){
        res.status(404).send('The course with the given ID was not found')
    }
    // delete course
    const index = courses.indexOf(course)
    console.log(index)
    courses.splice(index, 1)
    // if not delete otherse return the same course
   res.send(course)
})
``` 

![Delete course](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/co9f7m3g5ayw1alxmvrx.png)

**index.js file**

```
const Joi = require('joi')
const express = require('express');
const app = express();
app.use(express.json())

const courses = [
    {id: 1, name: 'course1'},
    {id: 2, name: 'course2'},
    {id: 3, name: 'course3'},
]

app.get('/', (req, res) => {
    res.send('Hello World!!')
})
app.get('/api/courses', (req, res) => {
    res.send(courses)
})
// /api/courses/1
app.get('/api/courses/:id', (req, res)=> {
    // res.send(req.params.id)
   const course = courses.find(c => c.id === parseInt(req.params.id))
   if(!course){
       res.status(404).send('The course with the given ID was not found')
   }
   res.send(course)

})
//http://localhost:3000/api/courses/2018/1
app.get('/api/courses/:year/:month', (req, res)=> {
    res.send(req.params)
})
// Query params:  http://localhost:3000/api/courses/2018/1?sortBy=name
app.get('/api/posts/:year/:month', (req, res)=> {
    res.send(req.query)
})

app.post('/api/courses', (req, res) => {
    // const schema = {
    //     name: Joi.string().min(3).required()
    // }
    // const result = Joi.validate(req.body, schema);
    // console.log(result);

    if(!req.body.name || req.body.name.length < 3){
        res.status(400).send('Name is required and should be minimum 3 character.');
        return;
    }   
    
    const course = {
        id: courses.length + 1,
        name: req.body.name
    }
    courses.push(course)
    res.send(course)
})


app.put('/api/courses/:id', (req, res)=> {
    // look up the course
    // if not existing, return 404
    const course = courses.find(c => c.id === parseInt(req.params.id))
    if(!course){
        res.status(404).send('The course with the given ID was not found')
    }
    // validate the coruse
    // if invalid, return 400 - Bad request
    if(!req.body.name || req.body.name.length < 3){
        res.status(400).send('Name is required and should be minimum 3 character.');
        return;
    } 

    // update course
    // return the update course
   course.name = req.body.name;  
   res.send(course)
})

app.delete('/api/courses/:id', (req, res)=> {
    // look up the course
    // if not existing, return 404
    const course = courses.find(c => c.id === parseInt(req.params.id))
    if(!course){
        res.status(404).send('The course with the given ID was not found')
    }

    // delete course
    const index = courses.indexOf(course)
    console.log(index)
    courses.splice(index, 1)
    // if not delete otherse return the same course
   res.send(course)
})


// port
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}...`))
```