A web server is the software responsible for receiving requests from clients, processing those requests, and sending responses back.

Learn Node JS

When you visit a website, your browser is essentially saying:

“Give me this resource.”

The web server receives that request, figures out what to return, and sends a response.

You can build a simple web server yourself to understand what happens behind frameworks such as Express, Django, Laravel, and Spring Boot.

1. How a Web Server Works

The basic communication looks like this:

Browser
   |
   | HTTP Request
   ↓
Web Server
   |
   | Process request
   ↓
Application / Files / Database
   |
   | HTTP Response
   ↓
Browser

For example, when you request:

GET /index.html HTTP/1.1
Host: example.com

the server may respond with:

HTTP/1.1 200 OK
Content-Type: text/html

<h1>Hello World</h1>

The browser then renders the HTML.

2. What You Need

A basic web server needs a few fundamental components:

  • Network socket to communicate over TCP
  • Port to listen for connections
  • HTTP request parser
  • Routing logic
  • Response generator
  • Static file handling
  • Error handling

For a learning project, you don’t need Nginx or Apache. You can build a small HTTP server using a programming language’s built-in networking capabilities.

3. Build One With Node.js

Node.js makes this particularly straightforward because it provides the built-in http module.

Create a file:

server.js

Add:

const http = require("http");

const server = http.createServer((req, res) => {
    res.writeHead(200, {
        "Content-Type": "text/plain"
    });

    res.end("Hello from my web server!");
});

server.listen(3000, () => {
    console.log("Server running on http://localhost:3000");
});

Start it:

node server.js

Then open:

http://localhost:3000

Your browser sends a request and your server sends back:

Hello from my web server!

That’s a real web server, albeit a very small one.

4. Understanding the Code

This line creates the server:

http.createServer()

The callback receives two important objects:

(req, res)

req

req represents the incoming request.

You can inspect:

req.method
req.url
req.headers

For example:

console.log(req.method);
console.log(req.url);

A request to:

/about

could produce:

GET
/about

res

res represents the response you send back to the client.

For example:

res.writeHead(200);
res.end("Hello!");

The 200 means:

OK

5. Add Routing

A useful server needs to respond differently depending on the URL.

const http = require("http");

const server = http.createServer((req, res) => {
    if (req.url === "/" && req.method === "GET") {
        res.writeHead(200, {
            "Content-Type": "text/plain"
        });

        return res.end("Home Page");
    }

    if (req.url === "/about" && req.method === "GET") {
        res.writeHead(200, {
            "Content-Type": "text/plain"
        });

        return res.end("About Page");
    }

    res.writeHead(404, {
        "Content-Type": "text/plain"
    });

    res.end("Page not found");
});

server.listen(3000);

Now you have basic routing:

/       → Home Page
/about  → About Page
other   → 404

Frameworks such as Express essentially provide much more sophisticated routing and middleware systems on top of concepts like these.

6. Return HTML

A server doesn’t have to return plain text.

You can send HTML:

const http = require("http");

const server = http.createServer((req, res) => {
    res.writeHead(200, {
        "Content-Type": "text/html"
    });

    res.end(`
        <!DOCTYPE html>
        <html>
        <head>
            <title>My Server</title>
        </head>
        <body>
            <h1>Welcome</h1>
            <p>This page came from my own server.</p>
        </body>
        </html>
    `);
});

server.listen(3000);

The browser receives the HTML and renders it as a webpage.

7. Serve a Static HTML File

Hardcoding HTML inside JavaScript isn’t practical.

Create:

project/
├── server.js
└── index.html

index.html:

<!DOCTYPE html>
<html>
<head>
    <title>My Website</title>
</head>
<body>
    <h1>Hello World</h1>
    <p>Served by my Node.js server.</p>
</body>
</html>

Then use Node’s filesystem module:

const http = require("http");
const fs = require("fs");

const server = http.createServer((req, res) => {
    if (req.url === "/") {
        fs.readFile("index.html", (err, data) => {
            if (err) {
                res.writeHead(500);
                return res.end("Server Error");
            }

            res.writeHead(200, {
                "Content-Type": "text/html"
            });

            res.end(data);
        });

        return;
    }

    res.writeHead(404);
    res.end("Not Found");
});

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

Now your server reads the file and delivers it to the browser.

8. Understand HTTP Status Codes

A web server communicates more than just content.

It also tells the client what happened.

Common status codes include:

CodeMeaning
200OK
201Created
301Moved Permanently
302Found / Redirect
400Bad Request
401Unauthorized
403Forbidden
404Not Found
500Internal Server Error
503Service Unavailable

For example:

res.writeHead(404);
res.end("Not Found");

tells the browser that the requested resource doesn’t exist.

9. Add an API Endpoint

Your server can also return JSON instead of HTML.

if (req.url === "/api/users") {
    const users = [
        {
            id: 1,
            name: "John"
        },
        {
            id: 2,
            name: "Jane"
        }
    ];

    res.writeHead(200, {
        "Content-Type": "application/json"
    });

    return res.end(JSON.stringify(users));
}

Visiting:

/api/users

could return:

[
    {
        "id": 1,
        "name": "John"
    },
    {
        "id": 2,
        "name": "Jane"
    }
]

Now your web server is also acting as a simple API server.

10. What Happens When Someone Visits Your Server?

Suppose a user visits:

http://example.com/products

A simplified process is:

1. Browser enters URL
        ↓
2. DNS resolves example.com
        ↓
3. Browser connects to server
        ↓
4. TCP connection established
        ↓
5. Browser sends HTTP request
        ↓
6. Server receives request
        ↓
7. Server determines the route
        ↓
8. Application processes request
        ↓
9. Server generates response
        ↓
10. Browser receives response
        ↓
11. Browser renders the page

This is the foundation behind the web.

11. From Localhost to the Internet

A server running on:

localhost:3000

is only accessible from your computer.

To make a server publicly accessible, you generally need:

Domain
   ↓
DNS
   ↓
Public IP
   ↓
Firewall / Network
   ↓
Web Server
   ↓
Application
   ↓
Database

A production setup might look like:

Internet
    ↓
Cloudflare
    ↓
Nginx
    ↓
Node.js Application
    ↓
MySQL / PostgreSQL

Nginx can handle things such as TLS termination, reverse proxying, static files, connection management, and routing traffic to your application.

12. Important Security Considerations

A learning server can be simple. A production server cannot.

You need to consider:

  • Input validation
  • Authentication and authorization
  • HTTPS/TLS
  • Rate limiting
  • Secure headers
  • Error handling
  • Logging
  • Dependency security
  • File-access restrictions
  • SQL injection prevention
  • Cross-site scripting
  • CSRF protection
  • Request-size limits
  • Secrets management

One particularly important rule is:

Never blindly trust data received from the client.

A request such as:

GET /user?id=123

should not automatically be treated as safe input.

13. What You Are Really Learning

Building a web server from scratch isn’t primarily about creating something that will replace Nginx or Apache.

The real value is understanding what happens underneath web frameworks.

Once you understand:

TCP
 ↓
HTTP
 ↓
Request
 ↓
Routing
 ↓
Application logic
 ↓
Response

frameworks become much easier to understand.

Express, Django, Laravel, Spring Boot and other frameworks aren’t magic. They automate and organize many of the repetitive problems involved in handling HTTP requests and building web applications.

A Good Learning Progression

If you want to take the project further, build it in this order:

Basic TCP server
       ↓
HTTP server
       ↓
Request parser
       ↓
Routing
       ↓
Static files
       ↓
JSON API
       ↓
POST requests
       ↓
Request body parsing
       ↓
Middleware
       ↓
Authentication
       ↓
Database
       ↓
HTTPS
       ↓
Reverse proxy
       ↓
Production deployment

The moment you build even a tiny web server yourself, HTTP stops being something that happens “behind the browser” and becomes something you can actually see and control.

Share
Published by
codeflare

Recent Posts

Shell Prompt Tutorial

A shell prompt is the text displayed by a command-line shell to show that it is ready…

4 days ago

The SOC Analyst

A SOC Analyst (Security Operations Center Analyst) is one of the frontline defenders of an organization’s cybersecurity…

2 weeks ago

Building an Offline-Friendly Image Upload System

Most image upload systems assume one thing: the user has a stable internet connection. That assumption…

3 weeks ago

JavaScript Background Sync API

Imagine a user submits a form while their internet connection suddenly disappears. Normally, the request…

3 weeks ago

10 Signs Your PC Has Been Hacked

Cybercriminals don't always announce their presence. Many compromises are designed to remain unnoticed for weeks…

1 month ago

What Killed jQuery?

For years, jQuery was everywhere. If you were building websites in the 2010s, there was a…

1 month ago