Menu

HTML & JS Topic

Node.js Creating a Basic Server

HTTP Server with http Module

Node.js has a built-in http module to create HTTP servers without any external dependencies.

Basic HTTP Server:

javascript

// Import the http module
const http = require('http');

// Create a server instance
const server = http.createServer((req, res) => {
  // This callback runs for every incoming request
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello, World!\n');
});

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

Server Instance Methods:

javascript

const http = require('http');

const server = http.createServer();

// Listen for request events
server.on('request', (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html' });
  res.end('<h1>Hello from Node.js Server!</h1>');
});

// Listen for other events
server.on('listening', () => {
  console.log(`Server listening on port ${server.address().port}`);
});

server.on('error', (error) => {
  console.error('Server error:', error);
});

server.on('close', () => {
  console.log('Server closed');
});

// Start server with options
server.listen({
  port: 3000,
  host: 'localhost',
  backlog: 511, // Maximum length of the queue of pending connections
  exclusive: false // Allow other servers to listen on the same port (cluster mode)
});

HTTP Methods and URL:

javascript

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

const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url, true); // Parse query string
  const pathname = parsedUrl.pathname;
  const query = parsedUrl.query;
  
  console.log(`Method: ${req.method}`);
  console.log(`URL: ${req.url}`);
  console.log(`Path: ${pathname}`);
  console.log(`Query:`, query);
  console.log(`Headers:`, req.headers);
  
  res.end('Request logged');
});

server.listen(3000);

Handling Requests & Responses

Request Object (req):

Contains information about the incoming request.

javascript

const server = http.createServer((req, res) => {
  // Request properties
  console.log('HTTP Method:', req.method); // GET, POST, PUT, DELETE, etc.
  console.log('URL:', req.url); // /path?query=string
  console.log('HTTP Version:', req.httpVersion);
  console.log('Headers:', req.headers);
  
  // Extract specific headers
  const contentType = req.headers['content-type'];
  const userAgent = req.headers['user-agent'];
  const authorization = req.headers['authorization'];
  
  // Remote address
  console.log('Remote IP:', req.socket.remoteAddress);
  console.log('Remote Port:', req.socket.remotePort);
});

Handling Request Body:

javascript

const server = http.createServer((req, res) => {
  // For POST, PUT, PATCH requests with body
  if (req.method === 'POST' || req.method === 'PUT') {
    let body = '';
    
    // Listen for data chunks
    req.on('data', (chunk) => {
      body += chunk.toString(); // Convert buffer to string
    });
    
    // When all data is received
    req.on('end', () => {
      try {
        // Parse JSON if content-type is application/json
        if (req.headers['content-type'] === 'application/json') {
          const data = JSON.parse(body);
          console.log('Received JSON:', data);
        } else {
          console.log('Received body:', body);
        }
        
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ message: 'Data received' }));
      } catch (error) {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'Invalid JSON' }));
      }
    });
    
    // Handle errors
    req.on('error', (error) => {
      console.error('Request error:', error);
      res.writeHead(500, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ error: 'Internal server error' }));
    });
  } else {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Send a POST request with JSON data');
  }
});

Response Object (res):

Used to send data back to the client.

javascript

const server = http.createServer((req, res) => {
  // Set status code
  res.statusCode = 200; // Default is 200
  
  // Set headers
  res.setHeader('Content-Type', 'text/html');
  res.setHeader('X-Powered-By', 'Node.js');
  
  // Multiple headers at once
  res.writeHead(200, {
    'Content-Type': 'text/html',
    'X-Custom-Header': 'MyValue',
    'Cache-Control': 'no-cache'
  });
  
  // Write response in chunks
  res.write('<html>');
  res.write('<head><title>My Server</title></head>');
  res.write('<body>');
  res.write('<h1>Welcome to Node.js Server</h1>');
  res.write('</body>');
  res.write('</html>');
  
  // End the response (mandatory)
  res.end();
});

Common Response Patterns:

javascript

const server = http.createServer((req, res) => {
  // 200 OK - Successful response
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Success!');
  
  // 201 Created - Resource created successfully
  // res.writeHead(201, { 'Content-Type': 'application/json' });
  // res.end(JSON.stringify({ id: 123, message: 'User created' }));
  
  // 400 Bad Request - Client error
  // res.writeHead(400, { 'Content-Type': 'application/json' });
  // res.end(JSON.stringify({ error: 'Invalid request data' }));
  
  // 404 Not Found - Resource doesn't exist
  // res.writeHead(404, { 'Content-Type': 'application/json' });
  // res.end(JSON.stringify({ error: 'Resource not found' }));
  
  // 500 Internal Server Error - Server error
  // res.writeHead(500, { 'Content-Type': 'application/json' });
  // res.end(JSON.stringify({ error: 'Something went wrong' }));
  
  // 302 Redirect
  // res.writeHead(302, { 'Location': '/new-path' });
  // res.end();
});

Streaming Responses:

javascript

const fs = require('fs');

const server = http.createServer((req, res) => {
  // Stream large files efficiently
  const fileStream = fs.createReadStream('largefile.txt');
  
  res.writeHead(200, {
    'Content-Type': 'text/plain',
    'Content-Disposition': 'attachment; filename="download.txt"'
  });
  
  // Pipe the file stream to response
  fileStream.pipe(res);
  
  // Handle stream errors
  fileStream.on('error', (error) => {
    console.error('File stream error:', error);
    res.writeHead(500, { 'Content-Type': 'text/plain' });
    res.end('Error reading file');
  });
});

Routing Basics

Simple Routing:

javascript

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

const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url, true);
  const pathname = parsedUrl.pathname;
  
  // Home route
  if (pathname === '/' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end(`
      <html>
        <head><title>Home</title></head>
        <body>
          <h1>Welcome to Home Page</h1>
          <nav>
            <a href="/about">About</a> | 
            <a href="/contact">Contact</a> |
            <a href="/api/users">API Users</a>
          </nav>
        </body>
      </html>
    `);
  }
  
  // About route
  else if (pathname === '/about' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('<h1>About Us</h1><p>This is our about page.</p>');
  }
  
  // Contact route
  else if (pathname === '/contact' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('<h1>Contact Us</h1><p>Email: contact@example.com</p>');
  }
  
  // 404 Not Found
  else {
    res.writeHead(404, { 'Content-Type': 'text/html' });
    res.end('<h1>404 - Page Not Found</h1><p>The page you requested does not exist.</p>');
  }
});

REST API Routing:

javascript

const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url, true);
  const pathname = parsedUrl.pathname;
  const method = req.method;
  
  // Parse path segments
  const pathSegments = pathname.split('/').filter(segment => segment);
  
  // API Routes
  if (pathSegments[0] === 'api') {
    // /api/users
    if (pathSegments[1] === 'users') {
      // GET /api/users - Get all users
      if (method === 'GET' && pathSegments.length === 2) {
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify([
          { id: 1, name: 'Alice' },
          { id: 2, name: 'Bob' }
        ]));
      }
      
      // GET /api/users/:id - Get specific user
      else if (method === 'GET' && pathSegments.length === 3) {
        const userId = parseInt(pathSegments[2]);
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ id: userId, name: 'User ' + userId }));
      }
      
      // POST /api/users - Create new user
      else if (method === 'POST' && pathSegments.length === 2) {
        let body = '';
        req.on('data', chunk => body += chunk.toString());
        req.on('end', () => {
          try {
            const userData = JSON.parse(body);
            res.writeHead(201, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({ 
              message: 'User created', 
              id: Date.now(), 
              ...userData 
            }));
          } catch {
            res.writeHead(400, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({ error: 'Invalid JSON' }));
          }
        });
      }
      
      else {
        res.writeHead(404, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'API endpoint not found' }));
      }
    }
    
    // /api/products
    else if (pathSegments[1] === 'products') {
      // Handle product routes
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ message: 'Products API' }));
    }
    
    else {
      res.writeHead(404, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ error: 'API resource not found' }));
    }
  }
  
  // Static file serving (basic example)
  else if (pathname.startsWith('/public/') && method === 'GET') {
    const fs = require('fs');
    const path = require('path');
    
    const filePath = path.join(__dirname, pathname);
    const extname = path.extname(filePath);
    
    const contentTypes = {
      '.html': 'text/html',
      '.css': 'text/css',
      '.js': 'text/javascript',
      '.json': 'application/json',
      '.png': 'image/png',
      '.jpg': 'image/jpeg',
      '.txt': 'text/plain'
    };
    
    fs.readFile(filePath, (error, content) => {
      if (error) {
        if (error.code === 'ENOENT') {
          res.writeHead(404);
          res.end('File not found');
        } else {
          res.writeHead(500);
          res.end('Server error');
        }
      } else {
        const contentType = contentTypes[extname] || 'application/octet-stream';
        res.writeHead(200, { 'Content-Type': contentType });
        res.end(content);
      }
    });
  }
  
  // 404 for all other routes
  else {
    res.writeHead(404, { 'Content-Type': 'text/html' });
    res.end('<h1>404 - Page Not Found</h1>');
  }
});

Route Handler Pattern:

javascript

// Better organized routing with route handlers
const routeHandlers = {
  'GET': {
    '/': (req, res) => {
      res.writeHead(200, { 'Content-Type': 'text/html' });
      res.end('<h1>Home Page</h1>');
    },
    '/about': (req, res) => {
      res.writeHead(200, { 'Content-Type': 'text/html' });
      res.end('<h1>About Page</h1>');
    },
    '/api/users': (req, res) => {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify([{ id: 1, name: 'John' }]));
    }
  },
  'POST': {
    '/api/users': (req, res) => {
      let body = '';
      req.on('data', chunk => body += chunk.toString());
      req.on('end', () => {
        res.writeHead(201, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ message: 'User created', data: body }));
      });
    }
  }
};

const server = http.createServer((req, res) => {
  const method = req.method;
  const url = req.url;
  
  // Find handler for the route
  const handlers = routeHandlers[method];
  const handler = handlers && handlers[url];
  
  if (handler) {
    handler(req, res);
  } else {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Route not found' }));
  }
});

Sending JSON Responses

Basic JSON Response:

javascript

const server = http.createServer((req, res) => {
  // Always set Content-Type header for JSON
  res.writeHead(200, {
    'Content-Type': 'application/json',
    'Cache-Control': 'no-cache'
  });
  
  // Send JSON data
  const data = {
    success: true,
    message: 'Operation successful',
    timestamp: new Date().toISOString(),
    data: {
      user: {
        id: 123,
        name: 'John Doe',
        email: 'john@example.com'
      },
      items: ['item1', 'item2', 'item3']
    }
  };
  
  // Convert object to JSON string
  res.end(JSON.stringify(data));
});

JSON Response Helper Function:

javascript

// Helper function for consistent JSON responses
function sendJsonResponse(res, statusCode, data) {
  res.writeHead(statusCode, {
    'Content-Type': 'application/json',
    'Cache-Control': 'no-cache'
  });
  
  const response = {
    success: statusCode >= 200 && statusCode < 300,
    timestamp: new Date().toISOString(),
    ...data
  };
  
  res.end(JSON.stringify(response));
}

const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url, true);
  
  if (parsedUrl.pathname === '/api/user') {
    sendJsonResponse(res, 200, {
      message: 'User data retrieved',
      data: {
        id: 1,
        name: 'Alice',
        role: 'admin'
      }
    });
  } else if (parsedUrl.pathname === '/api/error') {
    sendJsonResponse(res, 400, {
      error: 'Invalid request',
      details: 'Missing required fields'
    });
  } else {
    sendJsonResponse(res, 404, {
      error: 'Not found',
      message: 'The requested resource does not exist'
    });
  }
});

Complete REST API Example:

javascript

const http = require('http');

// Mock database
let users = [
  { id: 1, name: 'Alice', email: 'alice@example.com' },
  { id: 2, name: 'Bob', email: 'bob@example.com' }
];

// Helper functions
function parseBody(req) {
  return new Promise((resolve, reject) => {
    let body = '';
    req.on('data', chunk => body += chunk.toString());
    req.on('end', () => {
      try {
        resolve(JSON.parse(body));
      } catch {
        reject(new Error('Invalid JSON'));
      }
    });
    req.on('error', reject);
  });
}

function sendJson(res, status, data) {
  res.writeHead(status, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify(data));
}

// Create server
const server = http.createServer(async (req, res) => {
  const { method, url } = req;
  const pathSegments = url.split('/').filter(segment => segment);
  
  try {
    // Users API
    if (pathSegments[0] === 'users') {
      // GET /users - Get all users
      if (method === 'GET' && pathSegments.length === 1) {
        sendJson(res, 200, { users });
      }
      
      // GET /users/:id - Get user by ID
      else if (method === 'GET' && pathSegments.length === 2) {
        const userId = parseInt(pathSegments[1]);
        const user = users.find(u => u.id === userId);
        
        if (user) {
          sendJson(res, 200, { user });
        } else {
          sendJson(res, 404, { error: 'User not found' });
        }
      }
      
      // POST /users - Create user
      else if (method === 'POST' && pathSegments.length === 1) {
        const body = await parseBody(req);
        
        if (!body.name || !body.email) {
          sendJson(res, 400, { error: 'Name and email are required' });
          return;
        }
        
        const newUser = {
          id: users.length + 1,
          name: body.name,
          email: body.email
        };
        
        users.push(newUser);
        sendJson(res, 201, { 
          message: 'User created successfully', 
          user: newUser 
        });
      }
      
      // PUT /users/:id - Update user
      else if (method === 'PUT' && pathSegments.length === 2) {
        const userId = parseInt(pathSegments[1]);
        const body = await parseBody(req);
        const userIndex = users.findIndex(u => u.id === userId);
        
        if (userIndex === -1) {
          sendJson(res, 404, { error: 'User not found' });
          return;
        }
        
        users[userIndex] = { ...users[userIndex], ...body, id: userId };
        sendJson(res, 200, { 
          message: 'User updated successfully', 
          user: users[userIndex] 
        });
      }
      
      // DELETE /users/:id - Delete user
      else if (method === 'DELETE' && pathSegments.length === 2) {
        const userId = parseInt(pathSegments[1]);
        const userIndex = users.findIndex(u => u.id === userId);
        
        if (userIndex === -1) {
          sendJson(res, 404, { error: 'User not found' });
          return;
        }
        
        users.splice(userIndex, 1);
        sendJson(res, 200, { message: 'User deleted successfully' });
      }
      
      else {
        sendJson(res, 404, { error: 'Endpoint not found' });
      }
    }
    
    // Root endpoint
    else if (url === '/' || url === '') {
      sendJson(res, 200, {
        message: 'Welcome to Users API',
        endpoints: [
          'GET /users - Get all users',
          'GET /users/:id - Get user by ID',
          'POST /users - Create new user',
          'PUT /users/:id - Update user',
          'DELETE /users/:id - Delete user'
        ]
      });
    }
    
    // 404 for other routes
    else {
      sendJson(res, 404, { error: 'Route not found' });
    }
    
  } catch (error) {
    console.error('Server error:', error);
    
    if (error.message === 'Invalid JSON') {
      sendJson(res, 400, { error: 'Invalid JSON format' });
    } else {
      sendJson(res, 500, { error: 'Internal server error' });
    }
  }
});

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

CORS Headers for JSON APIs:

javascript

const server = http.createServer((req, res) => {
  // Set CORS headers (important for web apps)
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  
  // Handle OPTIONS preflight request
  if (req.method === 'OPTIONS') {
    res.writeHead(204);
    res.end();
    return;
  }
  
  // Your normal route handling...
  if (req.url === '/api/data') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'CORS-enabled response' }));
  }
});

Testing the Server:

bash

# Start the server
node server.js

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

# Test with browser
# Open: http://localhost:3000/

This covers the fundamentals of creating HTTP servers in Node.js using the built-in http module. While frameworks like Express.js provide more features and convenience, understanding the core http module is essential for mastering Node.js server development.

Comments (0)

No comments yet. Be the first to comment!

LecturreAI Assistant

Hello! I'm LecturreAI

What would you like to learn today?