Express Response Methods
Comprehensive guide to all Express response methods provided by Response Handler.
Response Method Overview
Response Handler extends the Express response object with standardized methods for all common HTTP status codes.
Success Response Methods
res.ok(data, message, options)
Status Code: 200 OK
Use Case: Successful GET requests, successful operations
app.get('/api/users', (req, res) => {
const users = getUsersFromDatabase();
res.ok(users, 'Users retrieved successfully');
});
// With pagination
app.get('/api/products', (req, res) => {
const { products, total, page, limit } = getProducts(req.query);
res.ok(products, 'Products retrieved successfully', {
pagination: {
page,
limit,
total,
totalPages: Math.ceil(total / limit),
},
});
});res.created(data, message, options)
Status Code: 201 Created
Use Case: Successful resource creation
app.post('/api/users', (req, res) => {
const newUser = createUser(req.body);
res.created(newUser, 'User created successfully');
});
// With location header
app.post('/api/posts', (req, res) => {
const post = createPost(req.body);
res.created(post, 'Post created successfully', {
headers: {
Location: `/api/posts/${post.id}`,
},
});
});res.accepted(data, message, options)
Status Code: 202 Accepted
Use Case: Async operations, queued tasks
app.post('/api/reports/generate', (req, res) => {
const jobId = queueReportGeneration(req.body);
res.accepted(
{
jobId,
status: 'queued',
estimatedTime: '5 minutes',
},
'Report generation started',
);
});
// Bulk operations
app.post('/api/users/bulk-import', (req, res) => {
const batchId = startBulkImport(req.body.users);
res.accepted(
{
batchId,
totalUsers: req.body.users.length,
status: 'processing',
},
'Bulk import started',
);
});res.noContent(message)
Status Code: 204 No Content
Use Case: Successful DELETE operations, successful PUT with no response body
app.delete('/api/users/:id', (req, res) => {
deleteUser(req.params.id);
res.noContent('User deleted successfully');
});
// Update with no response body
app.put('/api/settings', (req, res) => {
updateSettings(req.body);
res.noContent('Settings updated successfully');
});Client Error Response Methods
res.badRequest(error, message, options)
Status Code: 400 Bad Request
Use Case: Invalid request format, validation errors
app.post('/api/users', (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
return res.badRequest(
{
missingFields: ['email', 'password'].filter((field) => !req.body[field]),
},
'Missing required fields',
);
}
if (!isValidEmail(email)) {
return res.badRequest({ email: 'Invalid email format' }, 'Invalid email address');
}
// Continue with user creation...
});
// Validation with detailed errors
app.post('/api/products', (req, res) => {
const validationErrors = validateProduct(req.body);
if (validationErrors.length > 0) {
return res.badRequest({ validationErrors }, 'Product validation failed');
}
// Continue with product creation...
});res.unauthorized(error, message, options)
Status Code: 401 Unauthorized
Use Case: Missing or invalid authentication
const authenticateToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.unauthorized({}, 'Access token required');
}
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) {
return res.unauthorized({ tokenError: err.message }, 'Invalid or expired token');
}
req.user = user;
next();
});
};
// Multiple authentication methods
app.get('/api/profile', (req, res) => {
const token = req.headers.authorization || req.cookies.token;
if (!token) {
return res.unauthorized(
{
supportedMethods: ['Bearer token', 'Cookie'],
loginUrl: '/auth/login',
},
'Authentication required',
);
}
// Continue with profile retrieval...
});res.forbidden(error, message, options)
Status Code: 403 Forbidden
Use Case: Valid authentication but insufficient permissions
const requireRole = (roles) => {
return (req, res, next) => {
if (!req.user) {
return res.unauthorized({}, 'Authentication required');
}
if (!roles.includes(req.user.role)) {
return res.forbidden(
{
userRole: req.user.role,
requiredRoles: roles,
},
'Insufficient permissions',
);
}
next();
};
};
app.delete('/api/users/:id', authenticateToken, requireRole(['admin']), (req, res) => {
// User deletion logic...
});
// Resource-specific permissions
app.put('/api/posts/:id', authenticateToken, (req, res) => {
const post = getPost(req.params.id);
if (post.authorId !== req.user.id && req.user.role !== 'admin') {
return res.forbidden(
{
postId: req.params.id,
authorId: post.authorId,
userId: req.user.id,
},
'Can only edit your own posts',
);
}
// Continue with post update...
});res.notFound(error, message, options)
Status Code: 404 Not Found
Use Case: Resource does not exist
app.get('/api/users/:id', (req, res) => {
const user = getUserById(req.params.id);
if (!user) {
return res.notFound({ userId: req.params.id }, 'User not found');
}
res.ok(user, 'User retrieved successfully');
});
// With suggestions
app.get('/api/products/:slug', (req, res) => {
const product = getProductBySlug(req.params.slug);
if (!product) {
const suggestions = findSimilarProducts(req.params.slug);
return res.notFound(
{
slug: req.params.slug,
suggestions: suggestions.map((p) => p.slug),
},
'Product not found',
);
}
res.ok(product, 'Product retrieved successfully');
});res.methodNotAllowed(error, message, options)
Status Code: 405 Method Not Allowed
Use Case: HTTP method not supported for endpoint
app.all('/api/users/:id', (req, res, next) => {
const allowedMethods = ['GET', 'PUT', 'DELETE'];
if (!allowedMethods.includes(req.method)) {
res.set('Allow', allowedMethods.join(', '));
return res.methodNotAllowed(
{
method: req.method,
allowedMethods,
},
`Method ${req.method} not allowed`,
);
}
next();
});res.conflict(error, message, options)
Status Code: 409 Conflict
Use Case: Resource already exists, version conflicts
app.post('/api/users', (req, res) => {
const existingUser = getUserByEmail(req.body.email);
if (existingUser) {
return res.conflict(
{
email: req.body.email,
existingUserId: existingUser.id,
},
'User with this email already exists',
);
}
// Continue with user creation...
});
// Optimistic locking
app.put('/api/documents/:id', (req, res) => {
const document = getDocument(req.params.id);
if (document.version !== req.body.version) {
return res.conflict(
{
currentVersion: document.version,
clientVersion: req.body.version,
lastModified: document.updatedAt,
},
'Document has been modified by another user',
);
}
// Continue with document update...
});res.unprocessableEntity(error, message, options)
Status Code: 422 Unprocessable Entity
Use Case: Valid request format but semantic errors
app.post('/api/orders', (req, res) => {
const { items } = req.body;
const errors = [];
for (const item of items) {
const product = getProduct(item.productId);
if (!product) {
errors.push({
productId: item.productId,
error: 'Product not found',
});
} else if (product.stock < item.quantity) {
errors.push({
productId: item.productId,
requested: item.quantity,
available: product.stock,
error: 'Insufficient stock',
});
}
}
if (errors.length > 0) {
return res.unprocessableEntity({ itemErrors: errors }, 'Order contains invalid items');
}
// Continue with order creation...
});res.tooManyRequests(error, message, options)
Status Code: 429 Too Many Requests
Use Case: Rate limiting exceeded
const rateLimit = require('express-rate-limit');
const createRateLimiter = (windowMs, max) => {
return rateLimit({
windowMs,
max,
standardHeaders: true,
legacyHeaders: false,
handler: (req, res) => {
res.tooManyRequests(
{
limit: max,
windowMs,
retryAfter: Math.round(windowMs / 1000),
},
'Too many requests, please try again later',
);
},
});
};
// API rate limiting
app.use('/api/', createRateLimiter(15 * 60 * 1000, 100)); // 100 requests per 15 minutes
// Stricter rate limiting for auth endpoints
app.use('/api/auth/', createRateLimiter(15 * 60 * 1000, 5)); // 5 requests per 15 minutesServer Error Response Methods
res.error(error, message, options)
Status Code: 500 Internal Server Error
Use Case: Unexpected server errors
app.get('/api/users', (req, res) => {
try {
const users = getUsersFromDatabase();
res.ok(users, 'Users retrieved successfully');
} catch (error) {
console.error('Database error:', error);
res.error(error, 'Failed to retrieve users');
}
});
// With error context
app.post('/api/reports', (req, res) => {
try {
const report = generateReport(req.body);
res.created(report, 'Report generated successfully');
} catch (error) {
console.error('Report generation failed:', error);
res.error(
{
errorId: generateErrorId(),
context: 'report_generation',
timestamp: new Date().toISOString(),
},
'Report generation failed',
);
}
});res.notImplemented(error, message, options)
Status Code: 501 Not Implemented
Use Case: Feature not yet implemented
app.get('/api/analytics/advanced', (req, res) => {
res.notImplemented(
{
feature: 'advanced_analytics',
plannedRelease: '2024-Q2',
},
'Advanced analytics feature not yet implemented',
);
});res.badGateway(error, message, options)
Status Code: 502 Bad Gateway
Use Case: Upstream service errors
app.get('/api/external-data', async (req, res) => {
try {
const data = await fetchFromExternalAPI();
res.ok(data, 'External data retrieved successfully');
} catch (error) {
if (error.code === 'ECONNREFUSED') {
return res.badGateway(
{
service: 'external-api',
endpoint: error.config?.url,
},
'External service unavailable',
);
}
res.error(error, 'Failed to fetch external data');
}
});res.serviceUnavailable(error, message, options)
Status Code: 503 Service Unavailable
Use Case: Temporary service downtime, maintenance
const maintenanceMode = process.env.MAINTENANCE_MODE === 'true';
app.use((req, res, next) => {
if (maintenanceMode) {
return res.serviceUnavailable(
{
estimatedDowntime: process.env.MAINTENANCE_DURATION || '30 minutes',
retryAfter: 1800, // 30 minutes
},
'Service temporarily unavailable for maintenance',
);
}
next();
});Advanced Response Features
Custom Headers
app.get('/api/data', (req, res) => {
const data = getData();
res.ok(data, 'Data retrieved successfully', {
headers: {
'X-Total-Count': data.length.toString(),
'X-API-Version': '1.2.0',
'Cache-Control': 'public, max-age=3600',
},
});
});Performance Tracking
app.get('/api/heavy-operation', (req, res) => {
const startTime = Date.now();
const result = performHeavyOperation();
const operationTime = Date.now() - startTime;
res.ok(result, 'Operation completed successfully', {
performance: {
operationTime: `${operationTime}ms`,
complexity: 'O(n²)',
cacheHit: false,
},
});
});Conditional Responses
app.get('/api/posts/:id', (req, res) => {
const post = getPost(req.params.id);
if (!post) {
return res.notFound({}, 'Post not found');
}
// Check If-Modified-Since header
const ifModifiedSince = req.headers['if-modified-since'];
if (ifModifiedSince && new Date(ifModifiedSince) >= post.updatedAt) {
return res.status(304).end();
}
res.ok(post, 'Post retrieved successfully', {
headers: {
'Last-Modified': post.updatedAt.toUTCString(),
ETag: `"${post.version}"`,
},
});
});Response Compression
app.get('/api/large-dataset', (req, res) => {
const data = getLargeDataset();
res.ok(data, 'Dataset retrieved successfully', {
headers: {
'Content-Encoding': 'gzip',
'X-Uncompressed-Size': JSON.stringify(data).length.toString(),
},
});
});All response methods automatically include:
- Consistent format with success/error flags
- Timestamp for request tracking
- Execution time for performance monitoring
- Request ID for correlation
- Proper HTTP status codes
- Security headers when enabled
This provides a complete, standardized API response system for Express applications.