Request & Response Objects
Work with request data, query strings, body parsing, and send responses
The Request Object
The req object represents the HTTP request and contains properties for the
request query string, parameters, body, HTTP headers, and more.
📥 Common Request Properties
req.params - Route parametersreq.query - Query stringreq.body - Request bodyreq.headers - HTTP headersreq.method - HTTP methodreq.path - URL pathreq.cookies - Cookies (with parser)req.ip - Client IP addressWorking with Request Data
import express from 'express';
const app = express();
// Enable body parsing
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.post('/users/:id', (req, res) => {
// Route parameters
const { id } = req.params; // /users/123 → id = "123"
// Query string
const { page, limit } = req.query; // ?page=1&limit=10
// Request body (JSON)
const { name, email } = req.body; // { "name": "John", "email": "..." }
// Headers
const contentType = req.headers['content-type'];
const authHeader = req.headers.authorization;
const userAgent = req.get('User-Agent'); // Alias for headers
// Request info
console.log(req.method); // POST
console.log(req.path); // /users/123
console.log(req.originalUrl); // /users/123?page=1
console.log(req.baseUrl); // Base URL if using Router
console.log(req.hostname); // localhost
console.log(req.ip); // Client IP
console.log(req.protocol); // http or https
console.log(req.secure); // true if https
res.json({ id, name, email, page });
});
Request Body Parsing
// JSON body (application/json)
app.use(express.json({ limit: '10mb' }));
// URL-encoded (form submissions)
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
// Raw body (webhooks)
app.use('/webhooks', express.raw({ type: 'application/json' }));
// Text body
app.use(express.text());
// File uploads - use multer
import multer from 'multer';
const upload = multer({
dest: 'uploads/',
limits: { fileSize: 5 * 1024 * 1024 } // 5MB
});
// Single file
app.post('/upload', upload.single('avatar'), (req, res) => {
console.log(req.file); // Uploaded file info
console.log(req.body); // Other form fields
res.json({ filename: req.file?.filename });
});
// Multiple files
app.post('/gallery', upload.array('photos', 10), (req, res) => {
console.log(req.files); // Array of files
res.json({ count: (req.files as Express.Multer.File[]).length });
});
The Response Object
app.get('/demo', (req, res) => {
// Set status code
res.status(200);
res.status(201); // Created
res.status(400); // Bad Request
res.status(404); // Not Found
res.status(500); // Server Error
// Send response
res.send('Plain text'); // Auto content-type
res.json({ data: 'value' }); // JSON response
res.sendStatus(204); // Status only, no body
// Chaining
res.status(201).json({ id: 1 });
// Set headers
res.set('X-Custom-Header', 'value');
res.setHeader('Cache-Control', 'no-store');
res.type('application/json'); // Content-Type shortcut
// Cookies
res.cookie('session', 'abc123', {
httpOnly: true,
secure: true,
maxAge: 24 * 60 * 60 * 1000 // 1 day
});
res.clearCookie('session');
// Redirect
res.redirect('/new-location');
res.redirect(301, '/permanent-redirect');
res.redirect('back'); // Previous page
});
Response Methods
// JSON response (most common)
app.get('/api/users', (req, res) => {
res.json({ users: [], count: 0 });
});
// Send file download
app.get('/download/:filename', (req, res) => {
const filePath = `./files/${req.params.filename}`;
res.download(filePath, 'custom-name.pdf');
});
// Send file inline
app.get('/view/:filename', (req, res) => {
res.sendFile('/absolute/path/to/file.pdf');
});
// Streaming response
app.get('/stream', (req, res) => {
res.setHeader('Content-Type', 'text/plain');
res.write('Chunk 1\n');
res.write('Chunk 2\n');
res.end('Final chunk');
});
// Render template (with view engine)
app.set('view engine', 'ejs');
app.get('/page', (req, res) => {
res.render('template', { title: 'My Page', user: req.user });
});
// Content negotiation
app.get('/data', (req, res) => {
res.format({
'application/json': () => res.json({ data: 'json' }),
'text/html': () => res.send('HTML
'),
'text/plain': () => res.send('Plain text'),
default: () => res.status(406).send('Not Acceptable')
});
});
TypeScript Request Types
import { Request, Response } from 'express';
// Define types for all parts of the request
interface CreateUserParams {
// Empty for POST with no route params
}
interface CreateUserBody {
name: string;
email: string;
password: string;
}
interface CreateUserQuery {
sendWelcomeEmail?: string;
}
interface UserResponse {
id: number;
name: string;
email: string;
}
// Request<Params, ResBody, ReqBody, Query>
app.post('/users',
(req: Request<CreateUserParams, UserResponse, CreateUserBody, CreateUserQuery>,
res: Response<UserResponse>) => {
const { name, email, password } = req.body; // Typed!
const { sendWelcomeEmail } = req.query; // Typed!
const user: UserResponse = {
id: 1,
name,
email
};
res.status(201).json(user);
}
);
// Extend Request for custom properties
interface AuthRequest extends Request {
user?: {
id: string;
email: string;
};
}
app.get('/profile', authenticate, (req: AuthRequest, res) => {
res.json({ user: req.user });
});
Request Validation
// Using express-validator
import { body, param, query, validationResult } from 'express-validator';
app.post('/users',
[
body('email').isEmail().normalizeEmail(),
body('password').isLength({ min: 8 }),
body('name').trim().notEmpty(),
],
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Proceed with valid data
res.status(201).json(req.body);
}
);
// Using Zod
import { z } from 'zod';
const userSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
password: z.string().min(8),
});
app.post('/users', (req, res) => {
const result = userSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ errors: result.error.issues });
}
const { name, email, password } = result.data; // Typed!
res.status(201).json({ name, email });
});
✅ Best Practices
- • Always validate and sanitize user input
- • Use proper HTTP status codes (201 for created, 204 for no content)
- • Set appropriate Content-Type headers
- • Use
res.json()for API responses - • Type your request/response with TypeScript
- • Never trust req.body - always validate first