Skip to main content

Command Palette

Search for a command to run...

Creating Routes and Handling Requests with Express.js

Updated
6 min read
Creating Routes and Handling Requests with Express.js
D

Computer Engineering student | Full-Stack Developer (in progress) | DSA in C++ | AI-era Tech Explorer 🚀 Building skills, mindset, and systems to create impactful technology.

Hey everyone — Dinesh here, your full-stack learner who spent way too many nights fighting with raw Node.js http module before discovering Express.

When I first started backend development with Node.js, I tried building a simple server using only the built-in http module. It worked… but it was painful. Writing routes manually, handling different HTTP methods, parsing request bodies — everything felt too low-level and repetitive.

Then I discovered Express.js, and it felt like someone upgraded my coding experience from a bicycle to a sports car. Suddenly, creating routes became clean, readable, and actually fun.

In this detailed guide, I’m going to walk you through everything I learned — from what Express is, why it makes life so much easier, to building proper routes for GET and POST requests. We’ll go deep with clear explanations, real examples, and lots of visuals.

Let’s get started.

Chapter 1: What is Express.js?

Express.js is a fast, unopinionated, minimalist web framework for Node.js. It sits on top of Node’s built-in http module and provides a powerful set of tools to build web servers and APIs with much less code.

Think of it this way:

  • Node.js = Engine (gives you raw power)

  • Express.js = Steering wheel, gears, and dashboard (makes driving smooth and enjoyable)

Express doesn’t force you into any specific architecture. You can use it for simple APIs, full-stack apps, microservices, or even server-side rendered websites.

Key features of Express:

  • Robust routing system

  • Middleware support

  • Easy request and response handling

  • Template engine support

  • Excellent performance

Chapter 2: Why Express Simplifies Node.js Development

Let’s do a fair comparison to understand the real difference.

Raw Node.js HTTP Server (The Old Painful Way)

const http = require('http');

const server = http.createServer((req, res) => {
  if (req.url === '/' && req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Welcome to my server');
  } 
  else if (req.url === '/users' && req.method === 'GET') {
    res.writeHead(200);
    res.end('User list');
  } 
  else {
    res.writeHead(404);
    res.end('Not Found');
  }
});

server.listen(3000);

Problems with this approach:

  • Manual URL and method checking

  • No clean routing system

  • Difficult to handle request body (POST data)

  • Repetitive code for every route

  • Hard to scale as your app grows

Same Thing with Express (Much Cleaner)

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Welcome to my server');
});

app.get('/users', (req, res) => {
  res.send('User list');
});

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

See the difference? Express gives us clean, declarative routing.

Chapter 3: Creating Your First Express Server

Let’s build a complete basic Express server step by step.

Step 1: Initialize Project

mkdir express-routes-demo
cd express-routes-demo
npm init -y
npm install express

Step 2: Create server.js

// server.js
const express = require('express');
const app = express();
const PORT = 3000;

// Middleware to parse JSON bodies
app.use(express.json());

app.get('/', (req, res) => {
  res.send('<h1>Hello from Express! 🚀</h1>');
});

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

Run it:

node server.js

Open your browser and visit http://localhost:3000 — congratulations! Your first Express server is live.

Chapter 4: Understanding the Request → Route Handler → Response Flow

This is the heart of Express. Every incoming request follows this beautiful flow:

Visual Diagram 1: Request → Route Handler → Response Flow

Breakdown of the Flow:

  1. Client sends an HTTP request (GET, POST, etc.)

  2. Express receives the request

  3. Middleware processes the request (parsing body, adding headers, logging, etc.)

  4. Express matches the request with the correct route

  5. Route handler executes

  6. Handler sends response using res.send(), res.json(), res.status(), etc.

  7. Response goes back to the client

Chapter 5: Handling GET Requests – Reading Data

GET requests are used to fetch data from the server.

// Get all users
app.get('/api/users', (req, res) => {
  const users = [
    { id: 1, name: "Dinesh", city: "Jodhpur" },
    { id: 2, name: "Rahul", city: "Mumbai" }
  ];
  res.json(users);
});

// Get single user by ID (Route Parameter)
app.get('/api/users/:id', (req, res) => {
  const userId = parseInt(req.params.id);
  // In real app, fetch from database
  const user = { id: userId, name: "Dinesh", email: "dinesh@example.com" };
  
  if (!user) {
    return res.status(404).json({ message: "User not found" });
  }
  
  res.json(user);
});

Visual Diagram 2: Express Routing Structure

Chapter 6: Handling POST Requests – Creating Data

POST requests are used to send data to the server (creating resources).

app.post('/api/users', (req, res) => {
  const newUser = req.body;   // Data sent from frontend
  
  console.log("New user received:", newUser);
  
  // In real project, save to database here
  const savedUser = {
    id: Date.now(),
    ...newUser,
    createdAt: new Date()
  };

  res.status(201).json({
    message: "User created successfully",
    user: savedUser
  });
});

Important: Don’t forget app.use(express.json()) middleware to parse incoming JSON.

Chapter 7: Sending Different Types of Responses

Express makes sending responses very easy and flexible:

// Plain text
res.send('Hello World');

// JSON response
res.json({ success: true, data: users });

// HTML response
res.send('<h1>Welcome to Express</h1>');

// Status + JSON
res.status(404).json({ error: "Resource not found" });

// Redirect
res.redirect('/dashboard');

// Download file
res.download('./files/report.pdf');

Chapter 8: Advanced Routing Concepts

Route Parameters

app.get('/api/products/:category/:productId', (req, res) => {
  const { category, productId } = req.params;
  res.json({ category, productId });
});

Query Parameters

app.get('/api/search', (req, res) => {
  const { q, limit, sort } = req.query;
  res.json({ searchTerm: q, limit, sort });
});

Visual Diagram 3: Complete Express Request Lifecycle

Chapter 9: Best Practices for Routing in Express

From my experience building multiple projects:

  1. Organize Routes Properly

    • Create a routes/ folder

    • Separate concerns: userRoutes.js, productRoutes.js, authRoutes.js

  2. Use Router Middleware

const express = require('express');
const router = express.Router();

router.get('/', ...);
router.post('/', ...);

module.exports = router;
  1. Consistent Response Format Always return consistent JSON structure:

    {
      "success": true,
      "message": "User created",
      "data": { ... }
    }
    
  2. Proper Status Codes

    • 200 → Success

    • 201 → Created

    • 400 → Bad Request

    • 404 → Not Found

    • 500 → Server Error

Visual Diagram 4: Raw Node.js vs Express Comparison

Express.js doesn’t just simplify routing — it completely transforms how we build backend applications in Node.js. What used to take 50 lines of messy code can now be done in 5 clean, readable lines.

The combination of clean routing, powerful middleware, and excellent response handling makes Express the go-to framework for most Node.js developers.

Talk soon,
Dinesh
Full-Stack Learner | Turning raw Node into elegant Express apps