# HTTP & Building a Server From Scratch (Using Core http)

if you really want to understand **how servers work**, you need to go one level lower. You need to touch the raw metal. You need to build a server using the **core** `http` module. That’s what this post is about.

In this we are gonna -

* Understand what HTTP actually is
    
* Build a server from scratch
    
* Parse routes manually
    
* Read headers
    
* Handle request bodies using streams
    
* Send proper status codes
    

### what is HTTP ?

Starting with the most important/basic thing, what http is actually ? HTTP is just a **conversation protocol**.

Every HTTP request has:

* **Method** (GET, POST, PUT, etc etc)
    
* **URL**
    
* **Headers**
    
* **Body** (optional)
    

Every HTTP response has:

* **Status code** (200, 404, 500…)
    
* **Headers**
    
* **Body**
    

### Creating the smallest possible HTTP server

starting with most basic one

```javascript
const http = require("http");

const server = http.createServer((req, res) => {
  res.end("Hello World");
});

server.listen(3000, () => {
  console.log("Server running on port 3000");
});
```

## Understanding `req` and `res`

### `req` (Incoming Message)

And it mostly contains -

* `req.method`
    
* `req.url`
    
* `req.headers`
    
* request body as a stream
    

### `res` (Server response)

It is Used to -

* set status codes
    
* set headers
    
* send response body
    

### Routing in nodejs

```javascript
const server = http.createServer((req, res) => {
  if (req.method === "GET" && req.url === "/") {
    res.end("Home page");
    return;
  }

  if (req.method === "GET" && req.url === "/health") {
    res.end("OK");
    return;
  }

  res.statusCode = 404;
  res.end("Not Found");
});
```

Routing is just if-else on method and path(i love this analogy, got it from a cohort and still carry with me). Every framework eventually does this just in a cleaner way.

## Reading request headers

Headers are metadata.

Auth tokens, content type, user agent all comes through headers.

```javascript
const server = http.createServer((req, res) => {
  console.log(req.headers);

  res.end("Check your terminal");
});
/* output you'll see in terminal. it might differ a bit
content-type
authorization
user-agent
content-length
*/
```

### Handling request body

Request body is a stream. The body does not come all at once. It arrives in chunks.

```javascript
const server = http.createServer((req, res) => {
  let body = "";

  req.on("data", (chunk) => {
    body += chunk;
  });

  req.on("end", () => {
    console.log(body);
    res.end("Body received");
  });
});
```

This pattern matters a lot in real systems. Because -

* Requests can be huge
    
* Streaming avoids loading everything in memory
    
* This scales better
    

### Parsing JSON request body

```javascript
req.on("end", () => {
  try {
    const data = JSON.parse(body);
    console.log(data);
    res.end("JSON parsed");
  } catch (err) {
    res.statusCode = 400;
    res.end("Invalid JSON");
  }
});
```

On eimportant thing to notice here is that you are responsible for validations here, frameworks just hide these from us.

### Sending proper status codes

```javascript
res.statusCode = 201;
res.end("User created");
```

Some common status codes with meaning

* `200` – OK
    
* `201` – Created
    
* `400` – Bad request
    
* `401` – Unauthorized
    
* `404` – Not found
    
* `500` – Server error
    

### Setting response headers

Headers go out before body

```javascript
res.setHeader("Content-Type", "application/json");
res.statusCode = 200;
res.end(JSON.stringify({ message: "Hello" }));
```

Order doesn’t matter in code that much. Node sends them correctly under the hood.

### A tiny but complete server

Putting everything together

```javascript
const http = require("http");

const server = http.createServer((req, res) => {
  if (req.method === "POST" && req.url === "/echo") {
    let body = "";

    req.on("data", (chunk) => {
      body += chunk;
    });

    req.on("end", () => {
      res.setHeader("Content-Type", "application/json");
      res.statusCode = 200;
      res.end(body);
    });

    return;
  }

  res.statusCode = 404;
  res.end("Route not found");
});

server.listen(3000);
```

Once we understand these foundations of a server Frameworks stop feeling magical. Debugging becomes easier. Performance issues make sense.
