Skip to main content
Course/Module 2/Topic 3 of 4Intermediate

Request/Response Handling

Master request and response handling in Express.js applications

45 minBy Priygop TeamLast updated: Feb 2026

Request Object

The request object (req) contains information about the HTTP request that triggered the route handler. It includes properties like headers, body, parameters, and query strings.

Request Properties and Methods

Example
const express = require('express');
const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Accessing request properties
app.get('/example', (req, res) => {
    // URL and path
    console.log('URL:', req.url);
    console.log('Path:', req.path);
    console.log('Base URL:', req.baseUrl);
    
    // HTTP method
    console.log('Method:', req.method);
    
    // Headers
    console.log('Headers:', req.headers);
    console.log('User Agent:', req.get('User-Agent'));
    
    // Query parameters
    console.log('Query:', req.query);
    console.log('Search:', req.query.search);
    
    // Route parameters
    console.log('Params:', req.params);
    
    // Request body (for POST, PUT, PATCH)
    console.log('Body:', req.body);
    
    // IP address
    console.log('IP:', req.ip);
    
    // Hostname
    console.log('Hostname:', req.hostname);
    
    res.json({ message: 'Request details logged' });
});

// Handling different content types
app.post('/users', (req, res) => {
    const { name, email, age } = req.body;
    
    // Validate required fields
    if (!name || !email) {
        return res.status(400).json({ error: 'Name and email are required' });
    }
    
    // Process the data
    const user = { name, email, age: age || null };
    
    res.status(201).json({ message: 'User created', user });
});

// File upload handling
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('file'), (req, res) => {
    if (!req.file) {
        return res.status(400).json({ error: 'No file uploaded' });
    }
    
    res.json({ 
        message: 'File uploaded successfully',
        filename: req.file.filename,
        originalname: req.file.originalname,
        size: req.file.size
    });
});

Response Object

Example
const express = require('express');
const app = express();

// Sending different response types
app.get('/responses', (req, res) => {
    // JSON response
    res.json({ message: 'JSON response' });
    
    // HTML response
    res.send('<h1>HTML response</h1>');
    
    // Plain text response
    res.send('Plain text response');
    
    // Redirect
    res.redirect('/new-page');
    
    // Send file
    res.sendFile('/path/to/file.html');
    
    // Download file
    res.download('/path/to/file.pdf');
});

// Setting response headers
app.get('/headers', (req, res) => {
    res.set('Content-Type', 'application/json');
    res.set('X-Custom-Header', 'Custom Value');
    res.status(200).json({ message: 'Headers set' });
});

// Different HTTP status codes
app.get('/status', (req, res) => {
    // Success responses
    res.status(200).json({ message: 'OK' });
    res.status(201).json({ message: 'Created' });
    
    // Client error responses
    res.status(400).json({ error: 'Bad Request' });
    res.status(401).json({ error: 'Unauthorized' });
    res.status(404).json({ error: 'Not Found' });
    
    // Server error responses
    res.status(500).json({ error: 'Internal Server Error' });
    res.status(503).json({ error: 'Service Unavailable' });
});

// Streaming responses
app.get('/stream', (req, res) => {
    res.setHeader('Content-Type', 'text/plain');
    res.setHeader('Transfer-Encoding', 'chunked');
    
    let counter = 0;
    const interval = setInterval(() => {
        res.write(`Data chunk ${counter}\n`);
        counter++;
        
        if (counter >= 10) {
            clearInterval(interval);
            res.end('Stream complete');
        }
    }, 1000);
});

// Error responses
app.get('/error', (req, res) => {
    try {
        // Simulate an error
        throw new Error('Something went wrong');
    } catch (error) {
        res.status(500).json({ 
            error: 'Internal Server Error',
            message: error.message 
        });
    }
});

Advanced Request/Response Patterns

Example
// Advanced request/response handling patterns
const express = require('express');
const app = express();

// Request streaming for large data
app.get('/stream', (req, res) => {
    res.writeHead(200, {
        'Content-Type': 'text/plain',
        'Transfer-Encoding': 'chunked'
    });
    
    let counter = 0;
    const interval = setInterval(() => {
        res.write(`Chunk ${counter}\n`);
        counter++;
        
        if (counter >= 10) {
            clearInterval(interval);
            res.end('Stream complete');
        }
    }, 1000);
});

// Response compression
const compression = require('compression');
app.use(compression());

// Custom response methods
app.use((req, res, next) => {
    res.success = (data, message = 'Success') => {
        res.json({ success: true, message, data });
    };
    
    res.error = (message, statusCode = 400) => {
        res.status(statusCode).json({ success: false, message });
    };
    
    res.paginated = (data, page, limit, total) => {
        res.json({
            data,
            pagination: {
                page: parseInt(page),
                limit: parseInt(limit),
                total,
                pages: Math.ceil(total / limit)
            }
        });
    };
    
    next();
});

// Usage of custom response methods
app.get('/api/users', (req, res) => {
    const users = [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }];
    res.success(users, 'Users retrieved successfully');
});

app.get('/api/posts', (req, res) => {
    const { page = 1, limit = 10 } = req.query;
    const posts = Array.from({ length: 50 }, (_, i) => ({ id: i + 1, title: `Post ${i + 1}` }));
    const start = (page - 1) * limit;
    const end = start + parseInt(limit);
    const paginatedPosts = posts.slice(start, end);
    
    res.paginated(paginatedPosts, page, limit, posts.length);
});

Request/Response Best Practices

  • Use appropriate HTTP status codes: 200, 201, 400, 401, 403, 404, 500
  • Validate all input: Check request body, query parameters, and headers
  • Sanitize data: Clean user input to prevent injection attacks
  • Use consistent response format: Standardize JSON response structure
  • Handle CORS properly: Configure appropriate CORS headers
  • Implement rate limiting: Prevent abuse and DoS attacks
  • Use compression: Enable gzip compression for better performance
  • Set proper headers: Include security and cache headers

Mini-Project: RESTful API with Advanced Features

Example
// Complete RESTful API with advanced request/response handling
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const compression = require('compression');
const rateLimit = require('express-rate-limit');
const { body, validationResult } = require('express-validator');

const app = express();

// security and performance middleware
app.use(helmet());
app.use(cors());
app.use(compression());
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));

// Rate limiting
const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 100 // limit each IP to 100 requests per windowMs
});
app.use('/api/', limiter);

// Custom middleware for request processing
app.use((req, res, next) => {
    req.startTime = Date.now();
    req.requestId = Math.random().toString(36).substr(2, 9);
    
    // Custom response methods
    res.success = (data, message = 'Success', statusCode = 200) => {
        res.status(statusCode).json({
            success: true,
            message,
            data,
            requestId: req.requestId,
            timestamp: new Date().toISOString()
        });
    };
    
    res.error = (message, statusCode = 400, details = null) => {
        res.status(statusCode).json({
            success: false,
            message,
            details,
            requestId: req.requestId,
            timestamp: new Date().toISOString()
        });
    };
    
    res.paginated = (data, page, limit, total, message = 'Data retrieved successfully') => {
        res.json({
            success: true,
            message,
            data,
            pagination: {
                page: parseInt(page),
                limit: parseInt(limit),
                total,
                pages: Math.ceil(total / limit),
                hasNext: page * limit < total,
                hasPrev: page > 1
            },
            requestId: req.requestId,
            timestamp: new Date().toISOString()
        });
    };
    
    next();
});

// In-memory data store (in real app, use database)
let users = [
    { id: 1, name: 'John Doe', email: 'john@example.com', age: 30, createdAt: new Date() },
    { id: 2, name: 'Jane Smith', email: 'jane@example.com', age: 25, createdAt: new Date() }
];

let nextId = 3;

// Validation middleware
const validateUser = [
    body('name').isLength({ min: 2 }).withMessage('Name must be at least 2 characters'),
    body('email').isEmail().withMessage('Must be a valid email'),
    body('age').isInt({ min: 0, max: 150 }).withMessage('Age must be between 0 and 150'),
    (req, res, next) => {
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            return res.error('Validation failed', 400, errors.array());
        }
        next();
    }
];

// Routes
app.get('/', (req, res) => {
    res.success({
        message: 'Welcome to Advanced REST API',
        version: '1.0.0',
        endpoints: {
            users: '/api/users',
            health: '/api/health'
        }
    });
});

app.get('/api/health', (req, res) => {
    res.success({
        status: 'healthy',
        uptime: process.uptime(),
        memory: process.memoryUsage(),
        timestamp: new Date().toISOString()
    });
});

// GET /api/users - Get all users with pagination
app.get('/api/users', (req, res) => {
    const { page = 1, limit = 10, search, sortBy = 'id', order = 'asc' } = req.query;
    
    let filteredUsers = users;
    
    // Search functionality
    if (search) {
        filteredUsers = users.filter(user => 
            user.name.toLowerCase().includes(search.toLowerCase()) ||
            user.email.toLowerCase().includes(search.toLowerCase())
        );
    }
    
    // Sorting
    filteredUsers.sort((a, b) => {
        const aVal = a[sortBy];
        const bVal = b[sortBy];
        
        if (order === 'desc') {
            return bVal > aVal ? 1 : -1;
        }
        return aVal > bVal ? 1 : -1;
    });
    
    // Pagination
    const start = (page - 1) * limit;
    const end = start + parseInt(limit);
    const paginatedUsers = filteredUsers.slice(start, end);
    
    res.paginated(paginatedUsers, page, limit, filteredUsers.length);
});

// GET /api/users/:id - Get user by ID
app.get('/api/users/:id', (req, res) => {
    const { id } = req.params;
    const user = users.find(u => u.id === parseInt(id));
    
    if (!user) {
        return res.error('User not found', 404);
    }
    
    res.success(user);
});

// POST /api/users - Create new user
app.post('/api/users', validateUser, (req, res) => {
    const { name, email, age } = req.body;
    
    // Check if email already exists
    const existingUser = users.find(u => u.email === email);
    if (existingUser) {
        return res.error('Email already exists', 409);
    }
    
    const newUser = {
        id: nextId++,
        name,
        email,
        age: parseInt(age),
        createdAt: new Date()
    };
    
    users.push(newUser);
    res.success(newUser, 'User created successfully', 201);
});

// PUT /api/users/:id - Update user
app.put('/api/users/:id', validateUser, (req, res) => {
    const { id } = req.params;
    const { name, email, age } = req.body;
    const userIndex = users.findIndex(u => u.id === parseInt(id));
    
    if (userIndex === -1) {
        return res.error('User not found', 404);
    }
    
    // Check if email already exists (excluding current user)
    const existingUser = users.find(u => u.email === email && u.id !== parseInt(id));
    if (existingUser) {
        return res.error('Email already exists', 409);
    }
    
    users[userIndex] = {
        ...users[userIndex],
        name,
        email,
        age: parseInt(age),
        updatedAt: new Date()
    };
    
    res.success(users[userIndex], 'User updated successfully');
});

// DELETE /api/users/:id - Delete user
app.delete('/api/users/:id', (req, res) => {
    const { id } = req.params;
    const userIndex = users.findIndex(u => u.id === parseInt(id));
    
    if (userIndex === -1) {
        return res.error('User not found', 404);
    }
    
    const deletedUser = users.splice(userIndex, 1)[0];
    res.success(deletedUser, 'User deleted successfully');
});

// Error handling middleware
app.use((err, req, res, next) => {
    console.error(`[${req.requestId}] Error:`, err);
    
    if (err.type === 'entity.parse.failed') {
        return res.error('Invalid JSON in request body', 400);
    }
    
    res.error('Internal server error', 500);
});

// 404 handler
app.use((req, res) => {
    res.error('Route not found', 404);
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);
    console.log(`API Documentation: http://localhost:${PORT}`);
});

module.exports = app;

Additional Resources

Recommended Reading

  • Express.js Official Documentation
  • Express.js Routing Guide
  • Middleware in Express.js

Online Resources

  • Express.js Tutorial for Beginners
  • REST API Design with Express.js
  • Express.js Best Practices
Chat on WhatsApp
Priygop - Leading Professional Development Platform | Expert Courses & Interview Prep