Creating Routes and Handling Requests with Express.js

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:
Client sends an HTTP request (GET, POST, etc.)
Express receives the request
Middleware processes the request (parsing body, adding headers, logging, etc.)
Express matches the request with the correct route
Route handler executes
Handler sends response using
res.send(),res.json(),res.status(), etc.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:
Organize Routes Properly
Create a
routes/folderSeparate concerns:
userRoutes.js,productRoutes.js,authRoutes.js
Use Router Middleware
const express = require('express');
const router = express.Router();
router.get('/', ...);
router.post('/', ...);
module.exports = router;
Consistent Response Format Always return consistent JSON structure:
{ "success": true, "message": "User created", "data": { ... } }Proper Status Codes
200→ Success201→ Created400→ Bad Request404→ Not Found500→ 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
