Getting Started
Installation & Setup
# Create a new directory and initialize npm
mkdir my-express-app
cd my-express-app
npm init -y
# Install Express
npm install express
# Install nodemon for development (optional)
npm install --save-dev nodemon
# Basic package.json scripts
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js"
}
mkdir my-express-app
cd my-express-app
npm init -y
# Install Express
npm install express
# Install nodemon for development (optional)
npm install --save-dev nodemon
# Basic package.json scripts
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js"
}
Note: Nodemon automatically restarts your application when file changes are detected, which is helpful during development.
Basic Express Server
// app.js
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
// Basic route
app.get('/', (req, res) => {
res.send('Hello World!');
});
// Start server
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
// Basic route
app.get('/', (req, res) => {
res.send('Hello World!');
});
// Start server
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
Note: The order of middleware and routes is important in Express. They are executed in the order they are defined.
Routing
Basic Routing
// GET method route
app.get('/', (req, res) => {
res.send('GET request to homepage');
});
// POST method route
app.post('/', (req, res) => {
res.send('POST request to homepage');
});
// PUT method route
app.put('/user', (req, res) => {
res.send('PUT request to /user');
});
// DELETE method route
app.delete('/user', (req, res) => {
res.send('DELETE request to /user');
});
// ALL method route (matches all HTTP verbs)
app.all('/secret', (req, res) => {
res.send('Accessing the secret section');
});
app.get('/', (req, res) => {
res.send('GET request to homepage');
});
// POST method route
app.post('/', (req, res) => {
res.send('POST request to homepage');
});
// PUT method route
app.put('/user', (req, res) => {
res.send('PUT request to /user');
});
// DELETE method route
app.delete('/user', (req, res) => {
res.send('DELETE request to /user');
});
// ALL method route (matches all HTTP verbs)
app.all('/secret', (req, res) => {
res.send('Accessing the secret section');
});
Route Parameters
// Route with parameters
app.get('/users/:userId', (req, res) => {
res.send(`User ID: ${req.params.userId}`);
});
// Multiple route parameters
app.get('/users/:userId/books/:bookId', (req, res) => {
res.send(`User ${req.params.userId}, Book ${req.params.bookId}`);
});
// Route with regex pattern
app.get('/product/:id(\\d+)', (req, res) => {
// Only matches if id is a number
res.send(`Product ID: ${req.params.id}`);
});
// Optional parameter
app.get('/archive/:year?/:month?/:day?', (req, res) => {
const { year, month, day } = req.params;
if (year) res.send(`Archive for: ${year}-${month || 'XX'}-${day || 'XX'}`);
else res.send('Full archive');
});
// Query string parameters
app.get('/search', (req, res) => {
const { q, page } = req.query;
res.send(`Search for: ${q}, Page: ${page || 1}`);
});
app.get('/users/:userId', (req, res) => {
res.send(`User ID: ${req.params.userId}`);
});
// Multiple route parameters
app.get('/users/:userId/books/:bookId', (req, res) => {
res.send(`User ${req.params.userId}, Book ${req.params.bookId}`);
});
// Route with regex pattern
app.get('/product/:id(\\d+)', (req, res) => {
// Only matches if id is a number
res.send(`Product ID: ${req.params.id}`);
});
// Optional parameter
app.get('/archive/:year?/:month?/:day?', (req, res) => {
const { year, month, day } = req.params;
if (year) res.send(`Archive for: ${year}-${month || 'XX'}-${day || 'XX'}`);
else res.send('Full archive');
});
// Query string parameters
app.get('/search', (req, res) => {
const { q, page } = req.query;
res.send(`Search for: ${q}, Page: ${page || 1}`);
});
Route Handlers
// Single callback function
app.get('/example', (req, res) => {
res.send('Hello from example!');
});
// Multiple callback functions
app.get('/example', (req, res, next) => {
console.log('First callback');
next();
}, (req, res) => {
res.send('Hello from second callback!');
});
// Array of callback functions
const cb1 = (req, res, next) => {
console.log('CB1');
next();
};
const cb2 = (req, res, next) => {
console.log('CB2');
next();
};
const cb3 = (req, res) => {
res.send('Hello from CB3!');
};
app.get('/example', [cb1, cb2, cb3]);
// Combination of functions and arrays
app.get('/example', [cb1, cb2], (req, res) => {
res.send('Combination of arrays and functions');
});
app.get('/example', (req, res) => {
res.send('Hello from example!');
});
// Multiple callback functions
app.get('/example', (req, res, next) => {
console.log('First callback');
next();
}, (req, res) => {
res.send('Hello from second callback!');
});
// Array of callback functions
const cb1 = (req, res, next) => {
console.log('CB1');
next();
};
const cb2 = (req, res, next) => {
console.log('CB2');
next();
};
const cb3 = (req, res) => {
res.send('Hello from CB3!');
};
app.get('/example', [cb1, cb2, cb3]);
// Combination of functions and arrays
app.get('/example', [cb1, cb2], (req, res) => {
res.send('Combination of arrays and functions');
});
Router Object
// birds.js - Router module
const express = require('express');
const router = express.Router();
// Middleware specific to this router
router.use((req, res, next) => {
console.log('Time: ', Date.now());
next();
});
// Define routes
router.get('/', (req, res) => {
res.send('Birds home page');
});
router.get('/about', (req, res) => {
res.send('About birds');
});
// Route with parameter
router.get('/:birdId', (req, res) => {
res.send(`Bird ID: ${req.params.birdId}`);
});
module.exports = router;
// app.js - Using the router
const birds = require('./birds');
// Mount the router
app.use('/birds', birds);
const express = require('express');
const router = express.Router();
// Middleware specific to this router
router.use((req, res, next) => {
console.log('Time: ', Date.now());
next();
});
// Define routes
router.get('/', (req, res) => {
res.send('Birds home page');
});
router.get('/about', (req, res) => {
res.send('About birds');
});
// Route with parameter
router.get('/:birdId', (req, res) => {
res.send(`Bird ID: ${req.params.birdId}`);
});
module.exports = router;
// app.js - Using the router
const birds = require('./birds');
// Mount the router
app.use('/birds', birds);
Middleware
Application Middleware
// Application-level middleware (no mount path)
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
// Application-level middleware (with mount path)
app.use('/user/:id', (req, res, next) => {
console.log('Request Type:', req.method);
next();
});
// Multiple middleware functions
app.use('/user/:id', (req, res, next) => {
console.log('Request URL:', req.originalUrl);
next();
}, (req, res, next) => {
console.log('Request Type:', req.method);
next();
});
// Built-in middleware
app.use(express.json()); // Parse JSON bodies
app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies
app.use(express.static('public')); // Serve static files
// Third-party middleware
const cookieParser = require('cookie-parser');
app.use(cookieParser());
const helmet = require('helmet');
app.use(helmet());
const cors = require('cors');
app.use(cors());
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
// Application-level middleware (with mount path)
app.use('/user/:id', (req, res, next) => {
console.log('Request Type:', req.method);
next();
});
// Multiple middleware functions
app.use('/user/:id', (req, res, next) => {
console.log('Request URL:', req.originalUrl);
next();
}, (req, res, next) => {
console.log('Request Type:', req.method);
next();
});
// Built-in middleware
app.use(express.json()); // Parse JSON bodies
app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies
app.use(express.static('public')); // Serve static files
// Third-party middleware
const cookieParser = require('cookie-parser');
app.use(cookieParser());
const helmet = require('helmet');
app.use(helmet());
const cors = require('cors');
app.use(cors());
Router Middleware
// Router-level middleware
const router = express.Router();
// Middleware for all requests to this router
router.use((req, res, next) => {
console.log('Router middleware executed');
next();
});
// Middleware for specific path
router.use('/admin', (req, res, next) => {
// Check authentication
if (req.headers.authorization) {
next();
} else {
res.status(401).send('Unauthorized');
}
});
// Error-handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// 404 handler (should be last)
app.use((req, res, next) => {
res.status(404).send('Sorry, cannot find that!');
});
// Custom middleware example
const requestTime = (req, res, next) => {
req.requestTime = Date.now();
next();
};
app.use(requestTime);
app.get('/', (req, res) => {
res.send(`Requested at: ${req.requestTime}`);
});
const router = express.Router();
// Middleware for all requests to this router
router.use((req, res, next) => {
console.log('Router middleware executed');
next();
});
// Middleware for specific path
router.use('/admin', (req, res, next) => {
// Check authentication
if (req.headers.authorization) {
next();
} else {
res.status(401).send('Unauthorized');
}
});
// Error-handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// 404 handler (should be last)
app.use((req, res, next) => {
res.status(404).send('Sorry, cannot find that!');
});
// Custom middleware example
const requestTime = (req, res, next) => {
req.requestTime = Date.now();
next();
};
app.use(requestTime);
app.get('/', (req, res) => {
res.send(`Requested at: ${req.requestTime}`);
});
Request & Response
Request Object
// Common request properties
app.get('/user', (req, res) => {
console.log(req.baseUrl); // Base URL
console.log(req.body); // Request body (needs body-parser)
console.log(req.cookies); // Cookies (needs cookie-parser)
console.log(req.hostname); // Hostname
console.log(req.ip); // Client IP
console.log(req.method); // HTTP method
console.log(req.params); // Route parameters
console.log(req.path); // Path portion of URL
console.log(req.protocol); // Request protocol
console.log(req.query); // Query string parameters
console.log(req.secure); // Boolean for HTTPS
console.log(req.url); // URL
console.log(req.xhr); // Boolean for XMLHttpRequest
res.send('Check console for request details');
});
// Accessing headers
app.get('/headers', (req, res) => {
console.log(req.headers); // All headers
console.log(req.get('Content-Type')); // Specific header
res.send('Headers logged');
});
app.get('/user', (req, res) => {
console.log(req.baseUrl); // Base URL
console.log(req.body); // Request body (needs body-parser)
console.log(req.cookies); // Cookies (needs cookie-parser)
console.log(req.hostname); // Hostname
console.log(req.ip); // Client IP
console.log(req.method); // HTTP method
console.log(req.params); // Route parameters
console.log(req.path); // Path portion of URL
console.log(req.protocol); // Request protocol
console.log(req.query); // Query string parameters
console.log(req.secure); // Boolean for HTTPS
console.log(req.url); // URL
console.log(req.xhr); // Boolean for XMLHttpRequest
res.send('Check console for request details');
});
// Accessing headers
app.get('/headers', (req, res) => {
console.log(req.headers); // All headers
console.log(req.get('Content-Type')); // Specific header
res.send('Headers logged');
});
Response Object
// Sending responses
app.get('/send', (req, res) => {
res.send('Hello World!'); // Send string
res.send({ message: 'Hello' }); // Send JSON
res.send('<p>Some html</p>'); // Send HTML
res.send(Buffer.from('hello')); // Send buffer
});
// Setting status codes
app.get('/status', (req, res) => {
res.status(201).send('Created'); // Set status and send
res.sendStatus(200); // Send just the status code
});
// Setting headers
app.get('/headers', (req, res) => {
res.set('Content-Type', 'text/plain');
res.set({
'Content-Type': 'text/plain',
'X-Custom-Header': 'value'
});
res.send('Headers set');
});
// Redirects
app.get('/redirect', (req, res) => {
res.redirect('/new-path'); // Default 302
res.redirect(301, '/permanent'); // 301 redirect
res.redirect('https://example.com'); // External redirect
});
// Sending files
app.get('/file', (req, res) => {
res.sendFile('/absolute/path/to/file.pdf');
});
// JSON responses
app.get('/json', (req, res) => {
res.json({ user: 'tobi' }); // Content-Type: application/json
res.jsonp({ user: 'tobi' }); // JSON with padding for JSONP
});
app.get('/send', (req, res) => {
res.send('Hello World!'); // Send string
res.send({ message: 'Hello' }); // Send JSON
res.send('<p>Some html</p>'); // Send HTML
res.send(Buffer.from('hello')); // Send buffer
});
// Setting status codes
app.get('/status', (req, res) => {
res.status(201).send('Created'); // Set status and send
res.sendStatus(200); // Send just the status code
});
// Setting headers
app.get('/headers', (req, res) => {
res.set('Content-Type', 'text/plain');
res.set({
'Content-Type': 'text/plain',
'X-Custom-Header': 'value'
});
res.send('Headers set');
});
// Redirects
app.get('/redirect', (req, res) => {
res.redirect('/new-path'); // Default 302
res.redirect(301, '/permanent'); // 301 redirect
res.redirect('https://example.com'); // External redirect
});
// Sending files
app.get('/file', (req, res) => {
res.sendFile('/absolute/path/to/file.pdf');
});
// JSON responses
app.get('/json', (req, res) => {
res.json({ user: 'tobi' }); // Content-Type: application/json
res.jsonp({ user: 'tobi' }); // JSON with padding for JSONP
});
Templates & Views
Template Engines
// Set EJS as template engine
// npm install ejs
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// Render a view
app.get('/', (req, res) => {
res.render('index', {
title: 'Home Page',
message: 'Hello EJS!',
users: ['Alice', 'Bob', 'Charlie']
});
});
// Using Pug (formerly Jade)
// npm install pug
app.set('view engine', 'pug');
// Using Handlebars
// npm install express-handlebars
const exphbs = require('express-handlebars');
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');
// Using Mustache
// npm install mustache-express
const mustacheExpress = require('mustache-express');
app.engine('mustache', mustacheExpress());
app.set('view engine', 'mustache');
// Serve static files
app.use(express.static('public'));
// Multiple static directories
app.use(express.static('public'));
app.use(express.static('uploads'));
// Virtual path prefix
app.use('/static', express.static('public'));
// npm install ejs
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// Render a view
app.get('/', (req, res) => {
res.render('index', {
title: 'Home Page',
message: 'Hello EJS!',
users: ['Alice', 'Bob', 'Charlie']
});
});
// Using Pug (formerly Jade)
// npm install pug
app.set('view engine', 'pug');
// Using Handlebars
// npm install express-handlebars
const exphbs = require('express-handlebars');
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');
// Using Mustache
// npm install mustache-express
const mustacheExpress = require('mustache-express');
app.engine('mustache', mustacheExpress());
app.set('view engine', 'mustache');
// Serve static files
app.use(express.static('public'));
// Multiple static directories
app.use(express.static('public'));
app.use(express.static('uploads'));
// Virtual path prefix
app.use('/static', express.static('public'));
EJS Templates
<!-- views/index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title><%= title %></title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<h1><%= message %></h1>
<!-- JavaScript execution -->
<% const date = new Date(); %>
<p>Current date: <%= date.toLocaleDateString() %></p>
<!-- Conditionals -->
<% if (users.length > 0) { %>
<ul>
<% users.forEach(function(user) { %>
<li><%= user %></li>
<% }); %>
</ul>
<% } else { %>
<p>No users found</p>
<% } %>
<!-- Includes -->
<%- include('partials/footer') %>
</body>
</html>
<!-- views/partials/footer.ejs -->
<footer>
<p>© 2023 My App</p>
</footer>
// Route to render the template
app.get('/', (req, res) => {
res.render('index', {
title: 'Home Page',
message: 'Welcome to my app!',
users: ['Alice', 'Bob', 'Charlie']
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title><%= title %></title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<h1><%= message %></h1>
<!-- JavaScript execution -->
<% const date = new Date(); %>
<p>Current date: <%= date.toLocaleDateString() %></p>
<!-- Conditionals -->
<% if (users.length > 0) { %>
<ul>
<% users.forEach(function(user) { %>
<li><%= user %></li>
<% }); %>
</ul>
<% } else { %>
<p>No users found</p>
<% } %>
<!-- Includes -->
<%- include('partials/footer') %>
</body>
</html>
<!-- views/partials/footer.ejs -->
<footer>
<p>© 2023 My App</p>
</footer>
// Route to render the template
app.get('/', (req, res) => {
res.render('index', {
title: 'Home Page',
message: 'Welcome to my app!',
users: ['Alice', 'Bob', 'Charlie']
});
});
Error Handling
Basic Error Handling
// Basic error-handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// Catching errors in routes
app.get('/error', (req, res, next) => {
try {
// Some operation that might fail
throw new Error('Something went wrong!');
} catch (err) {
next(err); // Pass to error handler
}
});
// Async error handling
app.get('/async-error', async (req, res, next) => {
try {
const data = await someAsyncOperation();
res.json(data);
} catch (err) {
next(err);
}
});
// 404 handler (should be last route)
app.use((req, res, next) => {
res.status(404).send('Sorry, cannot find that!');
});
// Custom error class
class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}
}
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// Catching errors in routes
app.get('/error', (req, res, next) => {
try {
// Some operation that might fail
throw new Error('Something went wrong!');
} catch (err) {
next(err); // Pass to error handler
}
});
// Async error handling
app.get('/async-error', async (req, res, next) => {
try {
const data = await someAsyncOperation();
res.json(data);
} catch (err) {
next(err);
}
});
// 404 handler (should be last route)
app.use((req, res, next) => {
res.status(404).send('Sorry, cannot find that!');
});
// Custom error class
class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}
}
Advanced Error Handling
// Global error handling middleware
app.use((err, req, res, next) => {
err.statusCode = err.statusCode || 500;
err.status = err.status || 'error';
if (process.env.NODE_ENV === 'development') {
// Development: send detailed error
res.status(err.statusCode).json({
status: err.status,
error: err,
message: err.message,
stack: err.stack
});
} else {
// Production: send minimal information
const errorDetails = {
status: err.status,
message: err.isOperational ? err.message : 'Something went wrong!'
};
// Log error for monitoring
console.error('ERROR 💥', err);
res.status(err.statusCode).json(errorDetails);
}
});
// Async error wrapper (avoid try-catch blocks)
const catchAsync = fn => {
return (req, res, next) => {
fn(req, res, next).catch(next);
};
};
// Usage with async/await
app.get('/user/:id', catchAsync(async (req, res, next) => {
const user = await User.findById(req.params.id);
if (!user) {
return next(new AppError('No user found with that ID', 404));
}
res.status(200).json({
status: 'success',
data: { user }
});
}));
// Handle unhandled rejections
process.on('unhandledRejection', err => {
console.log('UNHANDLED REJECTION! 💥 Shutting down...');
console.log(err.name, err.message);
server.close(() => {
process.exit(1);
});
});
// Handle uncaught exceptions
process.on('uncaughtException', err => {
console.log('UNCAUGHT EXCEPTION! 💥 Shutting down...');
console.log(err.name, err.message);
process.exit(1);
});
app.use((err, req, res, next) => {
err.statusCode = err.statusCode || 500;
err.status = err.status || 'error';
if (process.env.NODE_ENV === 'development') {
// Development: send detailed error
res.status(err.statusCode).json({
status: err.status,
error: err,
message: err.message,
stack: err.stack
});
} else {
// Production: send minimal information
const errorDetails = {
status: err.status,
message: err.isOperational ? err.message : 'Something went wrong!'
};
// Log error for monitoring
console.error('ERROR 💥', err);
res.status(err.statusCode).json(errorDetails);
}
});
// Async error wrapper (avoid try-catch blocks)
const catchAsync = fn => {
return (req, res, next) => {
fn(req, res, next).catch(next);
};
};
// Usage with async/await
app.get('/user/:id', catchAsync(async (req, res, next) => {
const user = await User.findById(req.params.id);
if (!user) {
return next(new AppError('No user found with that ID', 404));
}
res.status(200).json({
status: 'success',
data: { user }
});
}));
// Handle unhandled rejections
process.on('unhandledRejection', err => {
console.log('UNHANDLED REJECTION! 💥 Shutting down...');
console.log(err.name, err.message);
server.close(() => {
process.exit(1);
});
});
// Handle uncaught exceptions
process.on('uncaughtException', err => {
console.log('UNCAUGHT EXCEPTION! 💥 Shutting down...');
console.log(err.name, err.message);
process.exit(1);
});
REST API Development
Basic REST API
// Simple REST API for a resource
const express = require('express');
const app = express();
// Middleware to parse JSON bodies
app.use(express.json());
// In-memory "database"
let users = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];
// GET all users
app.get('/api/users', (req, res) => {
res.json({
status: 'success',
results: users.length,
data: { users }
});
});
// GET single user
app.get('/api/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) {
return res.status(404).json({
status: 'fail',
message: 'User not found'
});
}
res.json({
status: 'success',
data: { user }
});
});
// POST create new user
app.post('/api/users', (req, res) => {
const newId = users[users.length - 1].id + 1;
const newUser = { id: newId, ...req.body };
users.push(newUser);
res.status(201).json({
status: 'success',
data: { user: newUser }
});
});
// PATCH update user
app.patch('/api/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
// Update user properties
Object.assign(user, req.body);
res.json({
status: 'success',
data: { user }
});
});
// DELETE user
app.delete('/api/users/:id', (req, res) => {
const index = users.findIndex(u => u.id === parseInt(req.params.id));
if (index === -1) {
return res.status(404).json({ message: 'User not found' });
}
users.splice(index, 1);
res.status(204).json({
status: 'success',
data: null
});
});
const express = require('express');
const app = express();
// Middleware to parse JSON bodies
app.use(express.json());
// In-memory "database"
let users = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];
// GET all users
app.get('/api/users', (req, res) => {
res.json({
status: 'success',
results: users.length,
data: { users }
});
});
// GET single user
app.get('/api/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) {
return res.status(404).json({
status: 'fail',
message: 'User not found'
});
}
res.json({
status: 'success',
data: { user }
});
});
// POST create new user
app.post('/api/users', (req, res) => {
const newId = users[users.length - 1].id + 1;
const newUser = { id: newId, ...req.body };
users.push(newUser);
res.status(201).json({
status: 'success',
data: { user: newUser }
});
});
// PATCH update user
app.patch('/api/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
// Update user properties
Object.assign(user, req.body);
res.json({
status: 'success',
data: { user }
});
});
// DELETE user
app.delete('/api/users/:id', (req, res) => {
const index = users.findIndex(u => u.id === parseInt(req.params.id));
if (index === -1) {
return res.status(404).json({ message: 'User not found' });
}
users.splice(index, 1);
res.status(204).json({
status: 'success',
data: null
});
});
API Best Practices
// API versioning
app.use('/api/v1/users', userRouter);
app.use('/api/v2/users', userRouterV2);
// Rate limiting
// npm install express-rate-limit
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP, please try again later.'
});
app.use('/api', limiter);
// Data sanitization
// npm install express-mongo-sanitize
const mongoSanitize = require('express-mongo-sanitize');
app.use(mongoSanitize()); // Prevent NoSQL injection
// XSS protection
// npm install xss-clean
const xss = require('xss-clean');
app.use(xss()); // Prevent XSS attacks
// CORS
// npm install cors
const cors = require('cors');
app.use(cors()); // Enable all CORS requests
// Or configure CORS
app.use(cors({
origin: 'https://yourdomain.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
// Helmet for security headers
// npm install helmet
const helmet = require('helmet');
app.use(helmet()); // Set various HTTP headers for security
// Compression
// npm install compression
const compression = require('compression');
app.use(compression()); // Compress responses
// Parameter pollution protection
// npm install hpp
const hpp = require('hpp');
app.use(hpp()); // Protect against HTTP Parameter Pollution attacks
app.use('/api/v1/users', userRouter);
app.use('/api/v2/users', userRouterV2);
// Rate limiting
// npm install express-rate-limit
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP, please try again later.'
});
app.use('/api', limiter);
// Data sanitization
// npm install express-mongo-sanitize
const mongoSanitize = require('express-mongo-sanitize');
app.use(mongoSanitize()); // Prevent NoSQL injection
// XSS protection
// npm install xss-clean
const xss = require('xss-clean');
app.use(xss()); // Prevent XSS attacks
// CORS
// npm install cors
const cors = require('cors');
app.use(cors()); // Enable all CORS requests
// Or configure CORS
app.use(cors({
origin: 'https://yourdomain.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
// Helmet for security headers
// npm install helmet
const helmet = require('helmet');
app.use(helmet()); // Set various HTTP headers for security
// Compression
// npm install compression
const compression = require('compression');
app.use(compression()); // Compress responses
// Parameter pollution protection
// npm install hpp
const hpp = require('hpp');
app.use(hpp()); // Protect against HTTP Parameter Pollution attacks