Simple Http Server Using Nodejs Net Module
Tags: node, javascript, codenewbie, beginners
Published: 2022-05-04 23:02:08

---
title: Simple Http Server Using Nodejs Net Module
published: true
description: TCP HTTP Server Using Only Net Module
tags: Nodejs, Javascript, codenewbie, beginners
//cover_image: https://direct_url_to_image.jpg
---

In this post we will build a HTTP Server using [Nodejs net module] (https://nodejs.org/api/net.html) which will help you understand HTTP basics. The server will be very simple and serve html files in a directory.

First, let's create a tcp server that greets clients using net module so that we can understand how HTTP works.

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

const server = net.createServer();

server.on('connection', (socket) => {
  console.log('client connected');

  socket.on('data', (data) => {
    console.log(data.toString());
    socket.write('hello');
    socket.end();
  });
});

server.listen(9090, () => {
  console.log('Listening 9090');
});
```

Here we created a server that listens PORT 9090. After the client makes a connection, it prints `client connected`. When the client sends data, it prints the data and sends `hello` to client. When it is done `socket.end();` closes the connection.

Let's try with netcat. We will use netcat as a TCP client. If you do not have netcat you can use anything you want.

Run the server. Open up new terminal tab for netcat. `nc localhost 9090` will create a connection and you will immediately see `client connected` message on the server. Go to netcat terminal tab and write `TEST` and press enter. You will see `hello` message that coming from server. Anytime you send a message from client to server you will see `hello` message. 

![Client](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68rwn4q5yernaw5oqk61.png)

Now, go to server terminal tab and you should see the message you sent from client. 

![Server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nbkf4girojmzidbjes7w.png)

Let's test this on a browser. You can use your default browser but I will use safari. Open localhost:9090 on the browser. 

![Browser request](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/npqsgv14fyaezzx2d3zr.png)

We see client made a connection and sent some data but on the browser we see `can not connect to server` error. 

![Browser can not connect to server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkw8ogt96z3klu2qlbpa.png)

Why 🤔. Because the message that server is returning is not a valid HTTP response yet. We should apply Hypertext Transfer Protocol (HTTP) so browser can understand the message and render it.

Basically, what HTTP saying is;
> message consist of a start-line, zero or more header fields (also known as "headers"), an empty line (i.e., a line with nothing preceding the CRLF) indicating the end of the header fields, and possibly a message-body.

[More info] (https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4)

So our response message should look like this:

1. Status line. It consists of three items:
   * HTTP version number. `HTTP/1.1`
   * Status code. `200`
   * Reason phrase. `OK`
2. Headers
3. Body

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

const server = net.createServer();

server.on('connection', (socket) => {
  console.log('client connected');

  socket.on('data', (data) => {
    console.log(data.toString());
    const statusLine = 'HTTP/1.1 200 OK\n';
    socket.write(statusLine);

    const header = 'Server: SimpleHTTPServer Nodejs\nContent-type: text/html\n\n';
    socket.write(header);

    const body = 'Hello World';
    socket.write(body);

    socket.end();
  });
});

server.listen(9090, () => {
  console.log('Listening 9090');
});
```

Notice that there is one `\n` at the end of the `statusLine` and between the headers (Server:, Content-type:), but there are two `\n` after the headers. This indicates that the body begins.

Let's open `localhost:9090` on a browser one more time. 

![Successful HTTP Response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rvhr2snkt8sofpqxvt83.png)

Tadaa 🎉. 

## Serve HTML Files

Now we can create a program that will serve HTML files. It will understand which HTML file client wants from request header.  For example if the client goes to localhost:9090/contact, we should see `GET /contact HTTP/1.1` in the request header. So we will parse the request header, try to find that file (eg contact.html) and respond to client. If client goes to the homepage we will respond with index.html.

Like HTTP response, HTTP request follows the same rules. Each HTTP header is followed by a carriage return line feed (CRLF). After the last of the HTTP headers, an additional CRLF is used (to give an empty line), and then any message body begins.

```
socket.on('data', (data) => {
    const [requestHeader] = data.toString().split('\n\n');

    const [requestLine] = requestHeader.split('\n');

    const [method, path, httpVersion] = requestLine.split(' ');

    const header = 'HTTP/1.1 200 OK\nServer: SimpleHTTPServer Nodejs\n\n';
    socket.write(header);

    const body = `${method} ${path} ${httpVersion}`;
    socket.write(body);

    socket.end();
  });
```

`data.toString().split('\n\n')` splits the header and the body from request. We get first element of array after split (which is the header) and assign it to `requestHeader`

We know that headers are divided by new lines. `.split('\n')`splits all headers and put each header into an array, but we only get the first header which tells us the method, path and version (`GET /contact HTTP/1.1`) assign it to `requestLine`.

We are splitting `requestLine` by empty spaces, and getting `method, path, httpVersion`

Lastly we are returning those values to client. If you go to the browser you should see `GET /contact HTTP/1.1` on the screen.

Now, let's create two HTML files, index.html and contact.html. You can put anything you want in them!

Before connection listener, create a new function called `handleRequest`. It will get the path as a parameter. 

```
const handleRequest = async (path) => {
  let requestedFile = `${path}.html`;
  if (path === '/') {
    requestedFile = '/index.html';
  }
  const fileData = await fs.promises.readFile(`.${requestedFile}`);
  return fileData;
};
```

If client requested homepage, requested file is index.html, if not, requested file is the path (eg: localhost:9090/contact). It will read the requested file and assign data to `fileData` with promises (We could also use `.pipe()` instead promises). 

```
// ...
const fileData = await handleRequest(path);

const header = 'HTTP/1.1 200 OK\nServer: SimpleHTTPServer Nodejs\n\n';
socket.write(header);

socket.write(fileData);
socket.end();
//...
```
We are sending the HTML file data that returned from `handleRequest` with `socket.write` to client.

![Homepage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1wlwvgop5m7siwph1x8.png)

To understand better, we can use netcat again. Open a terminal. While server is running, write `nc localhost 9090`. This will connect to the server. Now, we should send a message to the server. We want the contact.html file. So if we send /contact path in header, the server should respond with contact.html. To do that, write `GET /contact HTTP/1.1\r\n`. 

![netcat http request](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9ouhuj85z9p6qcoywp9.png)

Now you have built a simple HTTP server using nodejs net module.

Thank you for reading. You can find the source code on [Github](https://github.com/osmanmrtacar/simple-http-server/blob/main/index.js)