Lesson 4 of 6
5 min read
Node.js

Building HTTP Servers

Create web servers and handle HTTP requests using Node.js built-in http module

Creating a Basic HTTP Server

Node.js includes a built-in http module that allows you to create web servers without any external dependencies.

Your First Web Server

const http = require('http');

// Create the server
const server = http.createServer((req, res) => {
  // Set response headers
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  
  // Send response body
  res.end('Hello, World!');
});

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

Run the server and visit http://localhost:3000 in your browser.

Understanding Request & Response

const http = require('http');

const server = http.createServer((req, res) => {
  // Request information
  console.log('Method:', req.method);      // GET, POST, etc.
  console.log('URL:', req.url);            // /path/to/resource
  console.log('Headers:', req.headers);    // Request headers
  
  // Response methods
  res.statusCode = 200;                    // Set status code
  res.setHeader('Content-Type', 'text/html');  // Set header
  res.write('

Hello

'); // Write chunk res.end('

World!

'); // End response }); server.listen(3000);

Routing Requests

const http = require('http');

const server = http.createServer((req, res) => {
  const { method, url } = req;
  
  // Set default content type
  res.setHeader('Content-Type', 'application/json');
  
  // Simple routing
  if (method === 'GET' && url === '/') {
    res.statusCode = 200;
    res.end(JSON.stringify({ message: 'Welcome to the API' }));
  } 
  else if (method === 'GET' && url === '/users') {
    res.statusCode = 200;
    res.end(JSON.stringify({ users: ['Alice', 'Bob', 'Charlie'] }));
  } 
  else if (method === 'GET' && url === '/health') {
    res.statusCode = 200;
    res.end(JSON.stringify({ status: 'OK', timestamp: Date.now() }));
  } 
  else {
    res.statusCode = 404;
    res.end(JSON.stringify({ error: 'Not Found' }));
  }
});

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

Handling POST Requests

const http = require('http');

const server = http.createServer((req, res) => {
  if (req.method === 'POST' && req.url === '/users') {
    let body = '';
    
    // Collect data chunks
    req.on('data', chunk => {
      body += chunk.toString();
    });
    
    // Process complete request
    req.on('end', () => {
      try {
        const user = JSON.parse(body);
        console.log('Received user:', user);
        
        res.writeHead(201, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ 
          message: 'User created', 
          user 
        }));
      } catch (error) {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'Invalid JSON' }));
      }
    });
  } else {
    res.writeHead(404);
    res.end('Not Found');
  }
});

server.listen(3000);

Test with curl:

curl -X POST http://localhost:3000/users \
  -H "Content-Type: application/json" \
  -d '{"name": "John", "email": "john@example.com"}'

Serving HTML Files

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

const server = http.createServer(async (req, res) => {
  // Serve static HTML files
  if (req.method === 'GET') {
    let filePath = req.url === '/' ? '/index.html' : req.url;
    filePath = path.join(__dirname, 'public', filePath);
    
    // Determine content type
    const ext = path.extname(filePath);
    const contentTypes = {
      '.html': 'text/html',
      '.css': 'text/css',
      '.js': 'text/javascript',
      '.json': 'application/json',
      '.png': 'image/png',
      '.jpg': 'image/jpeg'
    };
    
    try {
      const content = await fs.readFile(filePath);
      res.writeHead(200, { 
        'Content-Type': contentTypes[ext] || 'text/plain' 
      });
      res.end(content);
    } catch (error) {
      res.writeHead(404);
      res.end('File not found');
    }
  }
});

server.listen(3000);

URL Parsing

const http = require('http');
const url = require('url');

const server = http.createServer((req, res) => {
  // Parse URL
  const parsedUrl = new URL(req.url, `http://${req.headers.host}`);
  
  console.log('Pathname:', parsedUrl.pathname);     // /users
  console.log('Search:', parsedUrl.search);         // ?name=john
  console.log('Query params:', parsedUrl.searchParams.get('name')); // john
  
  // Example: GET /users?name=john&age=30
  if (parsedUrl.pathname === '/users') {
    const name = parsedUrl.searchParams.get('name');
    const age = parsedUrl.searchParams.get('age');
    
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ name, age }));
  } else {
    res.writeHead(404);
    res.end('Not Found');
  }
});

server.listen(3000);

🚀 Moving Beyond http Module

While the built-in http module is great for learning, most production applications use frameworks like:

  • Express.js - Minimal and flexible, most popular
  • Fastify - High performance with schema validation
  • Koa - Modern async/await from Express creators
  • Hono - Ultra-fast, works on Edge and serverless
  • NestJS - Enterprise-grade with TypeScript and decorators

💡 Key Takeaways

  • • Use http.createServer() to create a web server
  • • The callback receives request (req) and response (res) objects
  • • Always set appropriate Content-Type headers
  • • Parse request body for POST/PUT requests
  • • Use frameworks like Express for production apps

Continue Learning