Express.js Request & Response
Master the req and res objects — the backbone of every Express route handler
req.params
req.query
req.body
res.json()
1. Introduction to Express.js
Express.js is a minimal and flexible Node.js web application framework. It provides a robust set of features for building web and mobile applications. At the heart of every Express route handler are two critical objects: the Request (req) and Response (res) objects.
The Request (req) object represents the HTTP request and contains properties for the request data (query string, parameters, body, headers, etc.).
The Response (res) object represents the HTTP response that an Express app sends when it gets a request.
Understanding these two objects is essential for building any backend functionality.
2. The Request Object (req)
The req object gives you access to everything the client sent to the server.
2.1 Accessing Route Parameters (req.params)
Route parameters are named URL segments used to capture values from a URL.
JavaScript// Route definition: /users/:userId/books/:bookId
app.get('/users/:userId/books/:bookId', (req, res) => {
console.log(req.params.userId); // Output: 123
console.log(req.params.bookId); // Output: abc
res.send('Route parameters captured');
});
// Request: GET /users/123/books/abc
2.2 Accessing Query Strings (req.query)
Query strings are the key-value pairs after the ? in a URL.
JavaScript// URL: /search?keyword=express&page=2
app.get('/search', (req, res) => {
console.log(req.query.keyword); // Output: express
console.log(req.query.page); // Output: 2
res.send(`Searching for: ${req.query.keyword}`);
});
2.3 Accessing POST Data (req.body)
To access data sent in the body of a POST, PUT, or PATCH request, you must use middleware like express.json() or express.urlencoded().
JavaScript// Middleware setup
app.use(express.json()); // Parses JSON data
app.use(express.urlencoded({ extended: true })); // Parses form data
// POST request with JSON body: { "name": "John", "age": 30 }
app.post('/user', (req, res) => {
console.log(req.body.name); // Output: John
console.log(req.body.age); // Output: 30
res.send('User data received');
});
Headers contain metadata about the request (like content-type, authorization token, user-agent).
JavaScriptapp.get('/info', (req, res) => {
const userAgent = req.headers['user-agent'];
const authToken = req.headers.authorization;
console.log(`User Agent: ${userAgent}`);
console.log(`Auth Token: ${authToken}`);
res.send('Headers logged');
});
2.5 Other Useful Request Properties
- req.method — The HTTP method (GET, POST, etc.)
- req.url — The full URL path
- req.ip — The client's IP address
- req.protocol — The protocol (http or https)
- req.hostname — The server's hostname
JavaScriptapp.get('/meta', (req, res) => {
res.json({
method: req.method,
url: req.url,
ip: req.ip,
protocol: req.protocol,
hostname: req.hostname
});
});
3. The Response Object (res)
The res object is your tool to send data back to the client. It controls the status code, headers, and body of the response.
3.1 Sending Responses (res.send())
The most common way to send a response. It automatically sets the Content-Type header.
JavaScriptapp.get('/html', (req, res) => {
res.send('<h1>Hello World</h1><p>This is HTML</p>');
});
app.get('/text', (req, res) => {
res.send('Just plain text');
});
3.2 Sending JSON (res.json())
This is the standard for building APIs. It converts JavaScript objects into a JSON string.
JavaScriptapp.get('/api/user', (req, res) => {
const user = {
id: 1,
name: 'Alice',
email: 'alice@example.com'
};
res.json(user);
});
// Output: {"id":1,"name":"Alice","email":"alice@example.com"}
3.3 Setting Status Codes (res.status())
Chaining .status() allows you to send the appropriate HTTP status code (200, 201, 404, 500, etc.).
JavaScriptapp.post('/api/user', (req, res) => {
// ... create user logic ...
res.status(201).json({ message: 'User created successfully' });
});
app.get('/api/user/:id', (req, res) => {
const user = null; // Simulate user not found
if (!user) {
res.status(404).json({ error: 'User not found' });
} else {
res.status(200).json(user);
}
});
3.4 Redirecting Requests (res.redirect())
Redirects the client to a different URL.
JavaScriptapp.get('/old-page', (req, res) => {
res.redirect(301, '/new-page');
});
app.get('/login', (req, res) => {
// After login, redirect to dashboard
res.redirect('/dashboard');
});
3.5 Rendering Templates (res.render())
Used when building server-rendered websites with template engines like Pug, EJS, or Handlebars.
JavaScript (using EJS)// Setup: app.set('view engine', 'ejs');
app.get('/profile', (req, res) => {
const user = { name: 'John', age: 25 };
res.render('profile', { user }); // Renders 'profile.ejs' with user data
});
3.6 Serving Files (res.download() & res.sendFile())
- res.download() — Prompts the browser to download the file
- res.sendFile() — Sends the file directly for viewing in the browser
JavaScriptapp.get('/download', (req, res) => {
res.download('./files/report.pdf');
});
app.get('/view/invoice', (req, res) => {
res.sendFile('./invoices/invoice-123.pdf', { root: __dirname });
});
3.7 Setting Headers (res.set())
Allows you to set custom HTTP headers on the response.
JavaScriptapp.get('/api/secure', (req, res) => {
res.set('X-Custom-Header', 'MySecretValue');
res.set({
'X-Powered-By': 'Express.js',
'Cache-Control': 'no-cache'
});
res.json({ message: 'Headers set successfully' });
});
4. Putting It All Together (Example API)
Let's build a simple notes API to demonstrate both req and res in action.
JavaScript — Notes APIconst express = require('express');
const app = express();
app.use(express.json()); // For parsing JSON bodies
// In-memory data store
let notes = [
{ id: 1, title: 'Buy milk', content: 'Don\'t forget!' },
{ id: 2, title: 'Call mom', content: 'Birthday on Friday' }
];
// GET all notes (with optional search query)
app.get('/api/notes', (req, res) => {
const { search } = req.query;
if (search) {
const filtered = notes.filter(n => n.title.includes(search));
return res.json(filtered);
}
res.json(notes);
});
// GET a single note by ID (using route params)
app.get('/api/notes/:id', (req, res) => {
const id = parseInt(req.params.id);
const note = notes.find(n => n.id === id);
if (!note) {
return res.status(404).json({ error: 'Note not found' });
}
res.json(note);
});
// POST a new note (using request body)
app.post('/api/notes', (req, res) => {
const { title, content } = req.body;
if (!title || !content) {
return res.status(400).json({ error: 'Title and content required' });
}
const newNote = {
id: notes.length + 1,
title,
content
};
notes.push(newNote);
res.status(201).json(newNote);
});
// DELETE a note (using route params)
app.delete('/api/notes/:id', (req, res) => {
const id = parseInt(req.params.id);
const index = notes.findIndex(n => n.id === id);
if (index === -1) {
return res.status(404).json({ error: 'Note not found' });
}
notes.splice(index, 1);
res.status(200).json({ message: 'Note deleted successfully' });
});
app.listen(3000, () => console.log('Server running on port 3000'));
5. Conclusion
The req and res objects are the backbone of every Express application.
req brings the client's request into your server. Master req.params, req.query, and req.body to capture any data the client sends.
res sends the server's response back. Master res.send(), res.json(), res.status(), and res.redirect() to control exactly what the client receives.
| Object | Property / Method | Purpose |
req | req.params | Route parameters from URL path |
req.query | Query string key-value pairs |
req.body | POST/PUT/PATCH request body |
req.headers | Request metadata headers |
req.method, req.ip, etc. | Other request metadata |
res | res.send() | Send text or HTML response |
res.json() | Send JSON response |
res.status() | Set HTTP status code |
res.redirect() | Redirect to another URL |
res.render(), res.sendFile() | Templates and file serving |