Part 4 – Creating Your First Web Server

Now that you understand Node.js fundamentals, let’s build your first web server from scratch using only the core http module.

1. Basic HTTP Server

Create a file named server.js with this minimal implementation:

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World!\n');
});

const PORT = 3000;
server.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}/`);
});

Key Components:
1. http.createServer() – Creates server instance
2. Request handler callback – Processes all incoming requests
3. res.writeHead() – Sets response headers
4. server.listen() – Starts the server

2. Understanding Request and Response

Request Object (req)

  • req.url – Request URL path
  • req.method – HTTP method (GET, POST, etc.)
  • req.headers – Request headers

Response Object (res)

  • res.writeHead() – Set status code and headers
  • res.write() – Send response content
  • res.end() – End the response

3. Handling Different Routes

Expand your server to handle multiple routes:

const http = require('http');

const server = http.createServer((req, res) => {
  if (req.url === '/') {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('<h1>Home Page</h1>');
  } 
  else if (req.url === '/about') {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('<h1>About Us</h1>');
  }
  else {
    res.writeHead(404, { 'Content-Type': 'text/html' });
    res.end('<h1>404 Not Found</h1>');
  }
});

server.listen(3000);

4. Serving Different Content Types

Content TypeHeaderExample
HTMLtext/htmlres.writeHead(200, {'Content-Type': 'text/html'});
JSONapplication/jsonres.writeHead(200, {'Content-Type': 'application/json'});
Plain Texttext/plainres.writeHead(200, {'Content-Type': 'text/plain'});

5. Serving Static Files

Create a public folder and add this file handling:

const fs = require('fs');
const path = require('path');

// Inside request handler:
const filePath = path.join(__dirname, 'public', req.url);

fs.readFile(filePath, (err, content) => {
  if (err) {
    if (err.code === 'ENOENT') {
      // File not found
      res.writeHead(404);
      res.end('File not found');
    } else {
      // Server error
      res.writeHead(500);
      res.end('Server error');
    }
  } else {
    // Success - determine content type
    const extname = path.extname(filePath);
    let contentType = 'text/html';

    switch(extname) {
      case '.js': contentType = 'text/javascript'; break;
      case '.css': contentType = 'text/css'; break;
      case '.json': contentType = 'application/json'; break;
      case '.png': contentType = 'image/png'; break;
    }

    res.writeHead(200, { 'Content-Type': contentType });
    res.end(content, 'utf-8');
  }
});

6. Handling POST Data

Process form submissions or API requests:

if (req.method === 'POST' && req.url === '/submit') {
  let body = '';

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

  req.on('end', () => {
    console.log('Received data:', body);
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ status: 'success', data: body }));
  });
}

7. Complete Server Example

Combine all concepts into a robust server:

const http = require('http');
const fs = require('fs');
const path = require('path');

const PORT = process.env.PORT || 3000;

const server = http.createServer((req, res) => {
  console.log(`${req.method} request for ${req.url}`);

  // API endpoint
  if (req.url === '/api/users' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify([{ id: 1, name: 'John' }]));
    return;
  }

  // Static files
  let filePath = path.join(__dirname, 'public', 
    req.url === '/' ? 'index.html' : req.url);

  fs.readFile(filePath, (err, content) => {
    if (err) {
      if (err.code === 'ENOENT') {
        res.writeHead(404);
        res.end('404 Not Found');
      } else {
        res.writeHead(500);
        res.end('Server Error');
      }
    } else {
      res.writeHead(200);
      res.end(content);
    }
  });
});

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

Next: Asynchronous Programming in Node.js →

Server Checklist

  • Handle different HTTP methods (GET, POST, etc.)
  • Proper error handling (404, 500 responses)
  • Correct content-type headers
  • Environment variables for configuration
  • Logging for debugging

Leave a Comment

Your email address will not be published. Required fields are marked *