Basic HTTP Server Using NodeJS From Scratch
Tags: javascript, beginners
Published: 2020-06-14 04:46:31

<link rel="canonical" href="[https://medium.com/@codesprintpro/basic-http-server-using-nodejs-from-scratch-637f9d15ca3f](https://medium.com/@codesprintpro/basic-http-server-using-nodejs-from-scratch-637f9d15ca3f)" />
_In this blog, we will see how to create an HTTP Server to handle GET, POST, PUT, DELETE request method type from scratch._

We need to have Node.js installed in our machine for the code to work. We will be using ‘**_http_**’ module provided out of the box to get the request and response object. We will not use any other custom library.

### Steps For Creating A HTTP Server

1.  Create Server using **_http_** module and add a listener
2.  Do the necessary entry check for the request
3.  Extract request method type
4.  Writing handler for Http GET request
5.  Writing handler for Http POST request
6.  Writing handler for Http PUT request
7.  Writing handler for Http DELETE request

----------

#### 1. Create Server using http module and add a listener

First of all, we need to create a server that will listen to some particular port. So that if any request comes to that port the listener will be called.

We can do this using [http](https://nodejs.org/api/http.html) module.

    const server = http.createServer(requestListener);  
    server.listen(8090);

**createServer** method accepts the listener as an argument. **listen** method takes the port number where it will keep listening.

Let’s see what empty **requestListener** method looks like.

    const requestListener = function (req, res) {  
     //all the code goes inside it  
    }

----------

#### 2. Do the necessary entry check for the request

Suppose we want our server to support REST API, and we want to have the following checks on request object:

-   Content-Type is application/json
-   Accept is application/json.

We will be using req object to get headers details and check the required values.

    const REQUIRED_CONTENT_TYPE = 'application/json';  
    const ACCEPT_ENCODING_1 = 'application/json';  
    const ACCEPT_ENCODING_2 = '*/*';
    
    const entryCheck = function (req) {  
      const contentType = req.headers["content-type"];  
      if (!contentType.includes(REQUIRED_CONTENT_TYPE)) {  
        throw new Error("Sorry we only support content type as json format.");  
      }  
        
      const accept = req.headers["accept"];  
      if (!(accept.includes(ACCEPT_ENCODING_1) ||  
    accept.includes(ACCEPT_ENCODING_2))) {  
        throw new Error("Sorry we only support accept json format.");  
      }  
    }

Let’s understand what’s going on.

-   First, we declare constant for content-type and accept header which our server will support
-   Next **entryCheck** is the method where we will check if the request headers have the required and matching details.
-   If either Content-type or Accept is not matching we will throw an error.

Now let’s see how we will call this method from type listener.

    const requestListener = function (req, res) {  
      try {  
        entryCheck(req);  
      } catch (error) {  
        res.writeHead(400);  
        res.end(error.message);  
    }

-   [**writeHead**](https://nodejs.org/api/http.html#http_response_writehead_statuscode_statusmessage_headers) method takes the HTTP Status code, it could be any valid status code. It has some optional parameters too, the second is a status message and the third is headers.
-   **end** method takes the response body which will be shown to the user. After this method, the response is sent back and the whole request-response process is done.

**Note**: We can add multiple entry checks depending on our condition like a cookie, hostname/IP address, a particular header etc.

----------

#### 3. Extract request method type

We need to know HTTP method type to handle each one of them separately.

    const requestListener = function (req, res) {  
      try {  
        entryCheck(req);  
        const methodType = req.method.toUpperCase();  
        ......

method property of request object gives us the Http method type like GET, POST, PUT, DELETE.

Next, we can use switch to handle different Http requests type differently

    ....  
    switch(methodType){  
      case 'GET':  
        break;  
      case 'POST':  
        break;  
      case 'PUT':  
        break;  
      case 'DELETE':  
        break;  
    }

----------

#### 4. Writing handler for Http GET request

Http GET requests are generally for finding an existing object by sending unique details

We can simply return a generic response in every kind of Http method type.

    case 'GET':  
      res.writeHead(200);  
      res.end(`We received ${methodType} type request`);  
      break;

But instead of just returning simple response let’s create some object and apply operations on it.

Let us consider an employee object with the following fields:

    {   
      "_id": "5ec02a534587193b1c607e2c",  
      "name": {  
        "first": "Pace",  
        "last": "Simmons"  
      },  
      "company": "MOLTONIC",  
      "email": "pace.simmons@moltonic.co.uk",  
      "phone": "+1 (941) 562-2930",  
      "address": "274 Dikeman Street, Somerset, Nevada, 6375"  
    }

We will have an object containing an array of above employee objects.

    let employeeData = [  
     {   
      "_id": "5ec02a534587193b1c607e2c",  
      "name": {  
        "first": "Pace",  
        "last": "Simmons"  
      },  
      "company": "MOLTONIC",  
      "email": "pace.simmons@moltonic.co.uk",  
      "phone": "+1 (941) 562-2930",  
      "address": "274 Dikeman Street, Somerset, Nevada, 6375"  
     },  
     ......  
    ]

Consider GET request where we will ask for particular employee detail by providing the **_id** value.

    localhost:8090/5ec02a53d8ba79b6992ba757

Now we will need one method which will search for the request **_id** in the array of objects. We will write one method to search employee based on **_id**:

    let findEmployee = (id) => {  
      return employeeData.find((employee) => {  
        if (employee._id === id)  
          return employee;  
      });  
    }

Let’s rewrite the GET Http handler code

    const requestListener = function (req, res) {  
      ....  
      case 'GET':  
        getMethodHandler(url, req, res);  
        break;  
      ....  
    }
    
    const getMethodHandler = (url, req, res) => {  
      const employeeId = url.substring(1);  
      const employee = findEmployee(employeeId);  
      if (!employee) {  
        res.writeHead(400);  
        res.end(`The employee with id ${employeeId} is not present.`);  
        return;  
      }  
      res.writeHead(200);  
      res.end(JSON.stringify(employee));  
    }

We have written a separate method

-   First, we found the requested **_id**
-   We pass that **_id** to **findEmployee** method to get the employee object
-   Next, we check if an employee object is found or not if not we throw an error.
-   If everything goes fine we return the employee object in the response body.

----------

#### 5. Writing handler for Http POST request

Http POST requests are generally for inserting the new objects. In our case, we will add the received employee object to the array. Let’s write code for that method

    let addEmployee = (employee) => {  
      employeeData.push(employee);  
    }

Next, we need to handle the POST request and parse the request body to get the employee object we need to insert:

    const requestListener = function (req, res) {  
      ....  
      case 'POST':  
        getRequestBodyAndGenerateResponse(req, res, postMethodHandler);  
        break;  
      ....  
    }
    
    const getRequestBodyAndGenerateResponse = (req, res, callback) => {  
      let body = '';  
      req.on('data', chunk => {  
        body += chunk.toString();  
      });  
      req.on('end', () => {  
        callback(res, JSON.parse(body));  
      });  
    }
    
    const postMethodHandler = (res, body) => {  
      try {  
        let reqBody = body;  
        addEmployee(reqBody)  
        res.writeHead(200);  
        res.end(`The Employee object with id is ${reqBody._id} added.`);  
    }

Let’s understand what we did here.

-   We defined a method **getRequestBodyAndGenerateResponse**(req, res, postMethodHandler).
-   This method reads the data from req object by listening for ‘**data**’ event and append it to one variable body.
-   Once the ‘**end**’ event is triggered means the request body read completely, it parses the string into JSON and calls the callback function passed to it.
-   This callback function is the one that prepares the response object.
-   In the callback function first, we add the employee to employee array.
-   Then prepare a response and sent it to the user.

----------

#### 6. Writing handler for Http PUT request

Http PUT requests are generally for updating the old objects. In our case, we will update the received employee object if present inside the array. Let’s write code for that method

    let findAndReplace = (employee) => {  
      let employeeFound = findEmployee(employee._id);  
      if (employeeFound) {  
        for (var key in employee) {  
          employeeFound[key] = employee[key];  
        }  
      return true;  
      } else {  
        return false;  
      }  
    }

Next, we need to handle PUT request and parse the request body to get the employee object we need to update:

    const requestListener = function (req, res) {  
      ....  
      case 'PUT':  
        getRequestBodyAndGenerateResponse(req, res, putMethodHandler);  
        break;  
      ....  
    }
    
    const putMethodHandler = (res, body) => {  
      let reqBody = body;  
      findAndReplace(reqBody);  
      res.writeHead(200);  
      res.end(`The Employee object with id is ${reqBody._id} replaced.`);  
    }

Let’s understand what we did here.

-   We defined a method **getRequestBodyAndGenerateResponse**(req, res, putMethodHandler).
-   This method reads the data from req object by listening for ‘**data**’ event and append it to one variable body.
-   Once the ‘**end**’ event is triggered means the request body read completely, it parses the string into JSON and calls the callback function passed to it.
-   This callback function is the one that prepares the response object.
-   In the callback function first, we update the received employee object inside the employee array.
-   Then prepare a response and sent it to the user.

----------

#### 7. Writing handler for Http DELETE request

Http DELETE requests are generally for deleting an existing object. In our case, we will delete the received employee object **_id** from the array. Let’s write code for that method

    let deleteEmployee = (id) => {  
      let length = employeeData.length;  
      while (length--) {  
        if (employeeData[length]  
        && employeeData[length]["_id"] === id) {  
          employeeData.splice(length, 1);  
          return true;  
        }  
      }  
      return false;  
    }

Next, we need to handle the DELETE request, get **_id** of the employee, and delete that object from the array.

    const requestListener = function (req, res) {  
      ....  
      case 'PUT':  
        deleteMethodHandler(url, req, res);  
        break;  
      ....  
    }
    
    const deleteMethodHandler = (url, req, res) => {  
      const employeeId = url.substring(1);  
      const response = deleteEmployee(employeeId);  
      res.writeHead(200);  
      res.end(`The employee with id ${employeeId} is deleted.`);  
    }

Let’s understand what we did here.

-   First, we found the requested **_id**
-   We pass that **_id** to **deleteEmployee** method to delete the employee object
-   If everything goes fine we delete the employee object.
-   Then prepare a response and sent it to the user.

You can find the above code [here](https://github.com/codesprintpro/jshttpserverusingnodejs). I tried to convert it into a modular format by separating data, methods, and using a module export-import feature of JS.

_If you enjoyed reading this, don’t forget the like. 👏  
Thank you._