Creating Routes and Handling Requests with Express

Raw Node.js HTTP servers work, but they're verbose. You spend time parsing URLs and handling different HTTP methods instead of building your app. Express removes that noise.
This is about how Express simplifies server building and lets you focus on routes and logic.
What Express.js Is
Express is a framework for building web servers in Node.js. It handles routing, middleware, and request/response management so you don't have to.
Without Express (Raw Node.js)
const http = require("http");
const server = http.createServer((req, res) => {
if (req.method === "GET" && req.url === "/") {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Home page");
} else if (req.method === "GET" && req.url === "/about") {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("About page");
} else {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("Not found");
}
});
server.listen(3000);
Lots of boilerplate for just two routes.
With Express
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.send("Home page");
});
app.get("/about", (req, res) => {
res.send("About page");
});
app.listen(3000);
Same functionality, much cleaner.
Why Express Simplifies Node.js Development
1. Routing Is Built-In
Express makes routing straightforward:
app.get("/users", (req, res) => {
// Handle GET /users
});
app.post("/users", (req, res) => {
// Handle POST /users
});
app.delete("/users/:id", (req, res) => {
// Handle DELETE /users/123
});
Raw Node.js requires manual URL parsing.
2. Request/Response Helpers
Express provides convenience methods:
res.json({ data: "value" }); // Send JSON
res.send("text response"); // Send text
res.status(404).send("Not found"); // Set status
Raw Node.js requires manual header management.
3. URL Parameters and Query Strings
Automatic parsing:
app.get("/users/:id", (req, res) => {
const userId = req.params.id; // From /users/123
});
app.get("/search", (req, res) => {
const query = req.query.q; // From /search?q=hello
});
Raw Node.js requires string parsing.
Creating Your First Express Server
Step 1: Install Express
npm install express
Step 2: Create the Server
const express = require("express");
const app = express();
// Your routes here
app.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});
That's the minimal setup. Just a few lines.
Step 3: Add Routes
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.send("Hello, World!");
});
app.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});
Now your server responds to GET requests at the root path.
Test It
node server.js
# Server running on http://localhost:3000
# In another terminal
curl http://localhost:3000
# Hello, World!
It works immediately.
Request → Route Handler → Response Flow
Browser sends request
|
v
Express receives request
|
v
Matches URL to a route
|
v
Route handler function called
|
├─ req: request object (data from browser)
└─ res: response object (send data back)
|
v
Handler uses res.send() or res.json()
|
v
Response sent back to browser
|
v
Browser displays it
Each request goes through this cycle.
Handling GET Requests
GET requests retrieve data. They're read-only.
Basic GET Route
app.get("/", (req, res) => {
res.send("Home page");
});
Visiting the root URL triggers this handler.
GET With URL Parameters
app.get("/users/:id", (req, res) => {
const userId = req.params.id;
res.send(`User ID: ${userId}`);
});
// /users/5 → "User ID: 5"
// /users/123 → "User ID: 123"
The :id is a variable in the URL.
GET With Query Strings
app.get("/search", (req, res) => {
const query = req.query.q;
res.send(`Searching for: ${query}`);
});
// /search?q=javascript → "Searching for: javascript"
Query strings come after the ?.
Real Example: User Endpoint
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
];
app.get("/users", (req, res) => {
res.json(users);
});
app.get("/users/:id", (req, res) => {
const user = users.find(u => u.id == req.params.id);
if (user) {
res.json(user);
} else {
res.status(404).send("User not found");
}
});
Requests:
GET /users→ all usersGET /users/1→ user 1GET /users/999→ 404
Handling POST Requests
POST requests send data to the server.
Basic POST Route
app.post("/users", (req, res) => {
res.send("User created");
});
A POST to /users triggers this handler.
POST With Data
Add middleware to parse the body:
const express = require("express");
const app = express();
app.use(express.json());
app.post("/users", (req, res) => {
const name = req.body.name;
res.json({ message: "User created", name });
});
Now req.body contains the request data.
Real Example: Creating a Resource
const express = require("express");
const app = express();
app.use(express.json());
let users = [{ id: 1, name: "Alice" }];
app.post("/users", (req, res) => {
const newUser = {
id: users.length + 1,
name: req.body.name
};
users.push(newUser);
res.status(201).json(newUser);
});
Test it:
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{"name":"David"}'
# Response: {"id":2,"name":"David"}
Sending Responses
Express provides multiple ways to send responses back.
Plain Text
app.get("/text", (req, res) => {
res.send("Plain text response");
});
JSON
app.get("/json", (req, res) => {
res.json({ message: "Hello", value: 42 });
});
HTML
app.get("/html", (req, res) => {
res.send("<h1>Hello World</h1>");
});
With Status Code
app.post("/created", (req, res) => {
res.status(201).json({ id: 1 });
});
app.get("/not-found", (req, res) => {
res.status(404).send("Not found");
});
app.get("/error", (req, res) => {
res.status(500).send("Server error");
});
Status codes tell the browser what happened:
- 200: OK
- 201: Created
- 404: Not found
- 500: Server error
Redirect
app.get("/old-page", (req, res) => {
res.redirect("/new-page");
});
Complete Example: Simple API
const express = require("express");
const app = express();
app.use(express.json());
// In-memory data store
let posts = [
{ id: 1, title: "First Post", body: "Hello" },
{ id: 2, title: "Second Post", body: "World" }
];
// GET all posts
app.get("/posts", (req, res) => {
res.json(posts);
});
// GET one post
app.get("/posts/:id", (req, res) => {
const post = posts.find(p => p.id == req.params.id);
if (post) {
res.json(post);
} else {
res.status(404).json({ error: "Post not found" });
}
});
// CREATE a post
app.post("/posts", (req, res) => {
const newPost = {
id: posts.length + 1,
title: req.body.title,
body: req.body.body
};
posts.push(newPost);
res.status(201).json(newPost);
});
// UPDATE a post
app.put("/posts/:id", (req, res) => {
const post = posts.find(p => p.id == req.params.id);
if (post) {
post.title = req.body.title || post.title;
post.body = req.body.body || post.body;
res.json(post);
} else {
res.status(404).json({ error: "Post not found" });
}
});
// DELETE a post
app.delete("/posts/:id", (req, res) => {
const index = posts.findIndex(p => p.id == req.params.id);
if (index !== -1) {
const deleted = posts.splice(index, 1);
res.json(deleted[0]);
} else {
res.status(404).json({ error: "Post not found" });
}
});
app.listen(3000, () => {
console.log("API running on http://localhost:3000");
});
This API handles create, read, update, and delete operations.
Express Routing Structure
app
|
├─ app.get("/path", handler)
├─ app.post("/path", handler)
├─ app.put("/path", handler)
├─ app.delete("/path", handler)
|
└─ app.listen(port)
Each route:
path: URL to match
handler: function to run
req: incoming request
res: outgoing response
Practice Assignment
1. Create a basic server:
const express = require("express");
const app = express();
// Create GET / endpoint that returns "Hello"
// Create GET /about endpoint that returns "About page"
app.listen(3000);
2. Handle URL parameters:
// Create GET /greet/:name that returns "Hello, {name}"
// Example: /greet/alice → "Hello, alice"
3. Handle POST requests:
// Parse JSON
// Create POST /data that receives { message: "..." }
// Return { received: message }
4. Build a simple resource API:
// Create an array of items
// GET /items → return all
// GET /items/:id → return one
// POST /items → create new
// DELETE /items/:id → delete one
Quick Recap
Express is a framework for building web servers in Node.js.
Routes are defined with
app.get(),app.post(),app.put(),app.delete().URL parameters come from
req.params.Query strings come from
req.query.POST data comes from
req.body(withexpress.json()middleware).Responses are sent with
res.send(),res.json(), orres.status().Status codes indicate what happened (200, 201, 404, 500).
Express removes boilerplate compared to raw Node.js.
A single
app.listen()starts the server.Routing in Express is simple and readable.
Express makes building web servers straightforward. Focus on routes and logic, not HTTP boilerplate.
If you enjoyed this article, check out my other blogs on this profile. 🔗 Connect with me: LinkedIn | GitHub | X (Twitter)




