Skip to main content

HTTP Module

The http module allows Node.js to transfer data over the Hyper Text Transfer Protocol (HTTP). It is the foundation for web servers in Node.js.
const http = require('http');

Creating a Server

The http.createServer() method includes a request listener function which is automatically added to the 'request' event.
const server = http.createServer((req, res) => {
  res.write('Hello World');
  res.end();
});

server.listen(5000, () => {
  console.log('Server running on port 5000...');
});
Run this script and navigate to http://localhost:5000 in your browser.

The Request and Response Objects

The callback function receives two arguments:
  1. req (Request): Contains information about the incoming request (URL, method, headers, etc.).
  2. res (Response): Used to send a response back to the client.

Inspecting the Request

const server = http.createServer((req, res) => {
  console.log(req.url, req.method);
  // ...
});

Setting Headers and Status Code

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});

Basic Routing

You can use req.url to handle different routes.
const server = http.createServer((req, res) => {
  if (req.url === '/') {
    res.write('Welcome to the Home Page');
    res.end();
  } else if (req.url === '/about') {
    res.write('Welcome to the About Page');
    res.end();
  } else {
    res.statusCode = 404;
    res.write('Page Not Found');
    res.end();
  }
});

Serving JSON

To serve an API, you typically return JSON data.
const server = http.createServer((req, res) => {
  if (req.url === '/api/users') {
    const users = [
      { name: 'Alice', age: 25 },
      { name: 'Bob', age: 30 }
    ];
    
    res.setHeader('Content-Type', 'application/json');
    res.end(JSON.stringify(users));
  }
});

Serving HTML Files

To serve actual HTML files, we combine the http module with the fs module.
const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer((req, res) => {
  if (req.url === '/') {
    fs.readFile(path.join(__dirname, 'index.html'), (err, content) => {
      if (err) throw err;
      res.writeHead(200, { 'Content-Type': 'text/html' });
      res.end(content);
    });
  }
});

Handling POST Requests

Unlike GET requests, POST data comes in chunks and must be collected:
const server = http.createServer((req, res) => {
  if (req.method === 'POST' && req.url === '/api/users') {
    let body = '';
    
    // Collect data chunks
    req.on('data', chunk => {
      body += chunk.toString();
    });
    
    // All data received
    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' }));
      }
    });
  }
});

Query Parameters

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

const server = http.createServer((req, res) => {
  const parsedUrl = new URL(req.url, `http://${req.headers.host}`);
  const pathname = parsedUrl.pathname;
  const query = parsedUrl.searchParams;
  
  // GET /search?q=nodejs&limit=10
  if (pathname === '/search') {
    const searchTerm = query.get('q');
    const limit = parseInt(query.get('limit')) || 10;
    
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({
      search: searchTerm,
      limit: limit,
      results: []
    }));
  }
});

Headers Deep Dive

Request Headers

const server = http.createServer((req, res) => {
  console.log('User-Agent:', req.headers['user-agent']);
  console.log('Content-Type:', req.headers['content-type']);
  console.log('Authorization:', req.headers['authorization']);
  console.log('Accept-Language:', req.headers['accept-language']);
  console.log('All headers:', req.headers);
  
  // Check for JSON content
  const isJson = req.headers['content-type'] === 'application/json';
});

Response Headers

res.setHeader('Content-Type', 'application/json');
res.setHeader('X-Powered-By', 'Node.js');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Access-Control-Allow-Origin', '*');

// Set multiple headers at once
res.writeHead(200, {
  'Content-Type': 'text/html',
  'Set-Cookie': 'session=abc123; HttpOnly',
  'X-Request-Id': '12345'
});

Building a Simple Router

const http = require('http');

class Router {
  constructor() {
    this.routes = {
      GET: {},
      POST: {},
      PUT: {},
      DELETE: {}
    };
  }

  get(path, handler) {
    this.routes.GET[path] = handler;
  }

  post(path, handler) {
    this.routes.POST[path] = handler;
  }

  put(path, handler) {
    this.routes.PUT[path] = handler;
  }

  delete(path, handler) {
    this.routes.DELETE[path] = handler;
  }

  async handle(req, res) {
    const handler = this.routes[req.method]?.[req.url];
    
    if (handler) {
      await handler(req, res);
    } else {
      res.writeHead(404, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ error: 'Not Found' }));
    }
  }
}

// Usage
const router = new Router();

router.get('/', (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Home Page');
});

router.get('/api/users', (req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify([{ id: 1, name: 'John' }]));
});

const server = http.createServer((req, res) => router.handle(req, res));
server.listen(3000);

HTTPS Server

For production, you need HTTPS:
const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('server.key'),
  cert: fs.readFileSync('server.cert')
};

const server = https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('Secure Hello World!');
});

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

Summary

  • The http module creates web servers without external dependencies
  • Use req.url and req.method for routing
  • POST data arrives in chunks via 'data' and 'end' events
  • Parse query strings with the URL class
  • Set appropriate Content-Type headers for responses
  • Build custom routers for organized code
  • Use https module with SSL certificates for production
  • Frameworks like Express.js abstract this complexity