Creating Routes and Handling Requests with Express

Search for a command to run...

No comments yet. Be the first to comment.
You open WhatsApp, type a message, and hit send. A single grey tick appears. You're on a train with no signal, but the message went through anyway. Or did it? That single tick is the beginning of a su

You record a Reel, add a song, trim it, and then close the app before posting. When you reopen Instagram, the draft is right there waiting. Nothing was lost. That experience feels simple. The system b

If you have built a React Native app, you have felt the pain of navigation setup. It is easy to get wrong and hard to keep clean as apps grow. This article explains what routing means, why it matters,

Modern apps are not just a pile of screens. They are a living system of features, data flows, offline behavior, and performance constraints. If you have only shipped small apps, the jump to something

Your application has user accounts. Some routes should only be accessible to logged-in users. How do you protect routes and verify that a request actually comes from who they claim to be? JWT (JSON We

Ashish's Blog
57 posts
Node.js has a built-in HTTP module, but writing servers with it is verbose. Express.js simplifies everything. It handles routing, request parsing, and response sending with clean, simple code.
Express is a lightweight web framework for Node.js. It makes building web applications easier by providing helpful features for routing, middleware, and responses.
Without Express, here's a basic Node.js server:
import http from 'http';
const server = http.createServer((req, res) => {
if (req.url === '/' && req.method === 'GET') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Home page');
} else if (req.url === '/about' && req.method === 'GET') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('About page');
} else {
res.statusCode = 404;
res.end('Not found');
}
});
server.listen(3000);
This gets messy quickly. With multiple routes, you'd have many if-else statements.
With Express, the same thing is much simpler:
import express from 'express';
const app = express();
app.get('/', (req, res) => {
res.send('Home page');
});
app.get('/about', (req, res) => {
res.send('About page');
});
app.listen(3000);
Much cleaner. Express handles the complexity.
First, create a project and install Express:
npm init -y
npm install express
Create a file called server.js:
import express from 'express';
const app = express();
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Run it:
node server.js
You have a running server. It doesn't do anything yet, but it's listening on port 3000.
A route is a combination of:
HTTP method (GET, POST, PUT, DELETE, etc.)
URL path (/home, /users, /posts/123, etc.)
Handler function (what to do when this route is called)
The basic structure is:
app.METHOD(PATH, HANDLER);
For example:
app.get('/home', (req, res) => {
res.send('This is the home page');
});
This means: "When someone sends a GET request to /home, execute this function."
GET requests fetch data. They're read-only and don't change anything.
import express from 'express';
const app = express();
app.get('/', (req, res) => {
res.send('Welcome to the home page');
});
app.get('/about', (req, res) => {
res.send('This is the about page');
});
app.get('/contact', (req, res) => {
res.send('Contact us at info@example.com');
});
app.listen(3000, () => {
console.log('Server running');
});
Now visit:
http://localhost:3000/ → "Welcome to the home page"
http://localhost:3000/about → "This is the about page"
http://localhost:3000/contact → "Contact us at..."
POST requests send data to the server. They typically create new resources.
For this, you need to parse incoming data. Express provides middleware for this:
import express from 'express';
const app = express();
// Parse JSON data
app.use(express.json());
app.get('/', (req, res) => {
res.send('GET request received');
});
app.post('/submit', (req, res) => {
const { name, email } = req.body;
res.send(`Thank you, \({name}. We'll email \){email}`);
});
app.listen(3000, () => {
console.log('Server running');
});
When someone sends a POST request to /submit with JSON data, Express parses it and stores it in req.body.
To test this, you'd need a tool like Postman or curl:
curl -X POST http://localhost:3000/submit \
-H "Content-Type: application/json" \
-d '{"name":"John","email":"john@example.com"}'
Response: "Thank you, John. We'll email john@example.com"
Routes can have dynamic parts. Parameters start with a colon:
import express from 'express';
const app = express();
app.get('/users/:id', (req, res) => {
const userId = req.params.id;
res.send(`Getting user ${userId}`);
});
app.get('/posts/:postId/comments/:commentId', (req, res) => {
const { postId, commentId } = req.params;
res.send(`Comment \({commentId} on post \){postId}`);
});
app.listen(3000);
Examples:
GET /users/123 → "Getting user 123"
GET /posts/456/comments/789 → "Comment 789 on post 456"
Query parameters come after a question mark and are optional:
import express from 'express';
const app = express();
app.get('/search', (req, res) => {
const query = req.query.q;
const limit = req.query.limit;
res.send(`Searching for "\({query}", limit \){limit}`);
});
app.listen(3000);
Examples:
GET /search?q=javascript → "Searching for 'javascript', limit undefined"
GET /search?q=node&limit=10 → "Searching for 'node', limit 10"
Express provides several ways to send responses:
import express from 'express';
const app = express();
// Send plain text
app.get('/text', (req, res) => {
res.send('This is plain text');
});
// Send JSON
app.get('/json', (req, res) => {
res.json({ message: 'This is JSON', status: 'success' });
});
// Send HTML
app.get('/html', (req, res) => {
res.send('<h1>This is HTML</h1>');
});
// Send with status code
app.get('/error', (req, res) => {
res.status(404).send('Not found');
});
// Redirect
app.get('/old-path', (req, res) => {
res.redirect('/new-path');
});
app.listen(3000);
Express supports all standard HTTP methods:
import express from 'express';
const app = express();
app.use(express.json());
app.get('/users', (req, res) => {
res.json({ message: 'Get all users' });
});
app.post('/users', (req, res) => {
res.json({ message: 'Create new user' });
});
app.put('/users/:id', (req, res) => {
res.json({ message: `Update user ${req.params.id}` });
});
app.delete('/users/:id', (req, res) => {
res.json({ message: `Delete user ${req.params.id}` });
});
app.listen(3000);
When a route doesn't exist, Express returns a 404 error by default. You can customize this:
import express from 'express';
const app = express();
app.get('/', (req, res) => {
res.send('Home');
});
// Catch all unmatched routes
app.use((req, res) => {
res.status(404).send('Page not found');
});
app.listen(3000);
The order matters. This "catch-all" route must be last, otherwise it will intercept all requests.
Let's build a simple blog API:
import express from 'express';
const app = express();
app.use(express.json());
// Sample data
let posts = [
{ id: 1, title: 'First Post', content: 'Hello world' },
{ id: 2, title: 'Second Post', content: 'Another post' }
];
// GET all posts
app.get('/posts', (req, res) => {
res.json(posts);
});
// GET single post
app.get('/posts/:id', (req, res) => {
const post = posts.find(p => p.id === parseInt(req.params.id));
if (!post) {
return res.status(404).send('Post not found');
}
res.json(post);
});
// CREATE new post
app.post('/posts', (req, res) => {
const newPost = {
id: posts.length + 1,
title: req.body.title,
content: req.body.content
};
posts.push(newPost);
res.status(201).json(newPost);
});
// UPDATE post
app.put('/posts/:id', (req, res) => {
const post = posts.find(p => p.id === parseInt(req.params.id));
if (!post) {
return res.status(404).send('Post not found');
}
post.title = req.body.title || post.title;
post.content = req.body.content || post.content;
res.json(post);
});
// DELETE post
app.delete('/posts/:id', (req, res) => {
const index = posts.findIndex(p => p.id === parseInt(req.params.id));
if (index === -1) {
return res.status(404).send('Post not found');
}
const deleted = posts.splice(index, 1);
res.json(deleted);
});
app.listen(3000, () => {
console.log('Blog API running on port 3000');
});
This simple API lets you create, read, update, and delete posts.
Mistake 1: Forgetting middleware
// Wrong - won't parse JSON
app.post('/data', (req, res) => {
console.log(req.body); // undefined
});
// Correct
app.use(express.json());
app.post('/data', (req, res) => {
console.log(req.body); // has data
});
Mistake 2: Forgetting to return after sending response
app.get('/users/:id', (req, res) => {
if (!id) {
res.status(400).send('Invalid ID');
// BUG: continues executing below
}
res.send('User data');
});
// Better
app.get('/users/:id', (req, res) => {
if (!id) {
return res.status(400).send('Invalid ID');
}
res.send('User data');
});
Express simplifies building web servers with Node.js
Routes combine HTTP method, path, and handler function
GET requests fetch data, POST requests send data
URL parameters (:id) capture dynamic values
Query parameters (?key=value) pass optional filters
Middleware processes requests before they reach handlers
Always return after sending a response
Use appropriate HTTP status codes
Express makes building web applications enjoyable. These fundamentals are the foundation for all Express applications.