Recommended and comparison of commonly used middleware libraries
Recommended and Compared Express Middleware Libraries
Express, as one of the most popular web frameworks for Node.js, relies heavily on middleware for its flexibility and extensibility. Choosing the right middleware can significantly improve development efficiency and project quality. Below is a detailed introduction and comparative analysis of commonly used middleware libraries.
Request Body Parsing Middleware
body-parser
body-parser
is a classic middleware in Express for handling HTTP request bodies, supporting JSON, URL-encoded, and text formats.
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// Parse application/json
app.use(bodyParser.json());
// Parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/api/users', (req, res) => {
console.log(req.body); // Access the parsed request body
res.send('User created');
});
express.json() and express.urlencoded()
Starting with Express 4.16.0, these two built-in middleware functions were introduced, offering similar functionality to body-parser
. The built-in solutions are recommended for basic needs.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
Comparison:
body-parser
is a standalone module with more comprehensive features (e.g., text parsing support).- Built-in middleware is lighter and suitable for basic requirements.
Static File Serving
serve-static
Express's built-in express.static
middleware is based on the serve-static
module and is used to serve static files.
// Serve static files from the 'public' directory
app.use(express.static('public'));
// With a virtual path prefix
app.use('/static', express.static('public'));
Advanced Configuration Example:
app.use('/static', express.static('public', {
index: false, // Disable directory indexing
maxAge: '1d', // Set cache headers
setHeaders: (res, path) => {
if (path.endsWith('.gz')) {
res.set('Content-Encoding', 'gzip');
}
}
}));
Session Management
express-session
The most commonly used session management middleware, supporting various storage backends (memory, Redis, MongoDB, etc.).
const session = require('express-session');
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: true,
cookie: { secure: true, maxAge: 3600000 }
}));
app.get('/login', (req, res) => {
req.session.user = { id: 1, name: 'John' };
res.send('Logged in');
});
cookie-session
Stores session data directly in client-side cookies, suitable for small session data.
const cookieSession = require('cookie-session');
app.use(cookieSession({
name: 'session',
keys: ['key1', 'key2'],
maxAge: 24 * 60 * 60 * 1000 // 24 hours
}));
Comparison:
express-session
is suitable for storing large amounts of session data.cookie-session
is simpler but limited by cookie size constraints.
Security-Related Middleware
helmet
Enhances application security by setting various HTTP headers.
const helmet = require('helmet');
app.use(helmet());
Custom Configuration:
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "trusted.cdn.com"]
}
},
hsts: {
maxAge: 31536000,
includeSubDomains: true
}
}));
csurf
CSRF protection middleware (Note: This middleware will be removed in Express 5).
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
app.get('/form', csrfProtection, (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
app.post('/process', csrfProtection, (req, res) => {
// Validate CSRF token
res.send('Form processed');
});
Logging
morgan
HTTP request logger middleware with support for predefined and custom formats.
const morgan = require('morgan');
// Use predefined format
app.use(morgan('combined'));
// Custom format
app.use(morgan(':method :url :status :res[content-length] - :response-time ms'));
// Log only error requests
app.use(morgan('combined', {
skip: (req, res) => res.statusCode < 400
}));
winston
A comprehensive logging solution supporting multiple transports and log levels.
const winston = require('winston');
const expressWinston = require('express-winston');
// Request logging
app.use(expressWinston.logger({
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'requests.log' })
],
format: winston.format.combine(
winston.format.colorize(),
winston.format.json()
),
meta: true,
msg: "HTTP {{req.method}} {{req.url}}"
}));
// Error logging
app.use(expressWinston.errorLogger({
transports: [
new winston.transports.File({ filename: 'errors.log' })
]
}));
Route Management
express.Router
Express's built-in routing system, supporting modular route definitions.
// routes/users.js
const router = express.Router();
router.get('/', (req, res) => {
res.send('User list');
});
router.get('/:id', (req, res) => {
res.send(`User ${req.params.id}`);
});
module.exports = router;
// app.js
const userRoutes = require('./routes/users');
app.use('/users', userRoutes);
express-promise-router
An enhanced Router that supports asynchronous route handling.
const Router = require('express-promise-router');
const router = new Router();
router.get('/async', async (req, res) => {
const data = await someAsyncOperation();
res.json(data);
});
app.use(router);
Error Handling
errorhandler
Error handling middleware for development environments.
const errorHandler = require('errorhandler');
if (process.env.NODE_ENV === 'development') {
app.use(errorHandler());
}
express-async-errors
Simplifies error handling for asynchronous routes.
require('express-async-errors');
app.get('/async-error', async (req, res) => {
throw new Error('Something went wrong');
// No try/catch needed
});
// Global error handler
app.use((err, req, res, next) => {
console.error(err);
res.status(500).send('Something broke!');
});
Performance Optimization
compression
Response compression middleware supporting gzip/deflate.
const compression = require('compression');
app.use(compression({
threshold: 1024, // Only compress responses larger than 1KB
filter: (req, res) => {
if (req.headers['x-no-compression']) {
return false;
}
return compression.filter(req, res);
}
}));
express-rate-limit
API request rate-limiting middleware.
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests
message: 'Too many requests from this IP, please try again later'
});
app.use('/api/', limiter);
Database Integration
connect-redis
Redis session storage adapter.
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
app.use(session({
store: new RedisStore({
host: 'localhost',
port: 6379,
ttl: 86400
}),
secret: 'your-secret-key',
resave: false,
saveUninitialized: false
}));
connect-mongo
MongoDB session storage adapter.
const MongoStore = require('connect-mongo');
app.use(session({
store: MongoStore.create({
mongoUrl: 'mongodb://localhost:27017/session_db',
ttl: 14 * 24 * 60 * 60 // 14 days
}),
secret: 'your-secret-key'
}));
File Upload
multer
Handles multipart/form-data form data, primarily used for file uploads.
const multer = require('multer');
// In-memory storage
const upload = multer();
// Disk storage
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
cb(null, Date.now() + '-' + file.originalname);
}
});
const upload = multer({ storage });
// Single file upload
app.post('/upload', upload.single('avatar'), (req, res) => {
console.log(req.file);
res.send('File uploaded');
});
// Multiple file upload
app.post('/photos', upload.array('photos', 12), (req, res) => {
console.log(req.files);
res.send('Files uploaded');
});
API Documentation Generation
swagger-ui-express
Provides Swagger UI for Express applications.
const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
apidoc
Generates API documentation from code comments.
/**
* @api {get} /user/:id Get user info
* @apiName GetUser
* @apiGroup User
*
* @apiParam {Number} id User's unique ID
*
* @apiSuccess {String} name Username
* @apiSuccess {Number} age User age
*/
app.get('/user/:id', (req, res) => {
// Implementation code
});
Template Engines
express-handlebars
Express integration for Handlebars template engine.
const exphbs = require('express-handlebars');
app.engine('hbs', exphbs({
extname: '.hbs',
defaultLayout: 'main',
layoutsDir: path.join(__dirname, 'views/layouts'),
partialsDir: path.join(__dirname, 'views/partials')
}));
app.set('view engine', 'hbs');
app.get('/', (req, res) => {
res.render('home', { title: 'Home Page' });
});
pug
Popular Pug (Jade) template engine.
app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views'));
app.get('/', (req, res) => {
res.render('index', { title: 'Pug Example', message: 'Hello Pug!' });
});
Cross-Origin Handling
cors
Middleware for handling Cross-Origin Resource Sharing (CORS).
const cors = require('cors');
// Simple usage
app.use(cors());
// Custom configuration
app.use(cors({
origin: ['https://example.com', 'https://api.example.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
exposedHeaders: ['X-Custom-Header'],
credentials: true,
maxAge: 86400
}));
// Route-level configuration
app.get('/products/:id', cors(), (req, res) => {
res.json({ id: req.params.id });
});
Testing Related
supertest
Library for testing HTTP endpoints, often used with testing frameworks.
const request = require('supertest');
const app = require('../app');
describe('GET /users', () => {
it('responds with JSON', (done) => {
request(app)
.get('/users')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200, done);
});
});
node-mocks-http
Creates mock request and response objects for testing middleware.
const httpMocks = require('node-mocks-http');
const middleware = require('../middleware/logger');
test('logger middleware should log request', () => {
const req = httpMocks.createRequest({
method: 'GET',
url: '/test'
});
const res = httpMocks.createResponse();
const next = jest.fn();
middleware(req, res, next);
expect(next).toHaveBeenCalled();
});
Utility Tools
express-validator
Request data validation middleware.
const { body, validationResult } = require('express-validator');
app.post('/user',
body('username').isLength({ min: 5 }).trim().escape(),
body('email').isEmail().normalizeEmail(),
body('age').isInt({ min: 18 }),
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Process valid data
res.send('User created');
}
);
express-list-endpoints
Lists all registered routes in an application.
const listEndpoints = require('express-list-endpoints');
// Get all routes
const allRoutes = listEndpoints(app);
console.log(allRoutes);
// Example output:
// [
// { path: '/', methods: ['GET'] },
// { path: '/users', methods: ['GET', 'POST'] }
// ]
Microservices Related
express-gateway
Framework for building API gateways.
// gateway.config.yml
http:
port: 8080
apiEndpoints:
api:
host: localhost
paths: '/ip'
serviceEndpoints:
httpbin:
url: 'https://httpbin.org'
policies:
- proxy
pipelines:
default:
apiEndpoints:
- api
policies:
- proxy:
- action:
serviceEndpoint: httpbin
changeOrigin: true
express-http-proxy
HTTP proxy middleware.
const proxy = require('express-http-proxy');
app.use('/proxy', proxy('http://example.com', {
proxyReqPathResolver: (req) => {
return req.url;
},
userResDecorator: (proxyRes, proxyResData, userReq, userRes) => {
const data = JSON.parse(proxyResData.toString());
data.customField = 'proxied';
return JSON.stringify(data);
}
}));
Real-Time Communication
express-ws
Adds WebSocket support to Express.
const expressWs = require('express-ws')(app);
app.ws('/echo', (ws, req) => {
ws.on('message', (msg) => {
ws.send(msg);
});
});
// Supports both HTTP and WebSocket
app.get('/echo', (req, res) => {
res.send('Use WebSocket endpoint');
});
socket.io
Popular real-time communication library with good Express integration.
const http = require('http');
const socketIo = require('socket.io');
const server = http.createServer(app);
const io = socketIo(server);
io.on('connection', (socket) => {
console.log('New client connected');
socket.on('chat message', (msg) => {
io.emit('chat message', msg);
});
socket.on('disconnect', () => {
console.log('Client disconnected');
});
});
server.listen(3000);
Internationalization
i18next-express-middleware
Internationalization (i18n) middleware.
const i18next = require('i18next');
const i18nextMiddleware = require('i18next-express-middleware');
i18next
.use(i18nextMiddleware.LanguageDetector)
.init({
fallbackLng: 'en',
resources: {
en: { translation: require('./locales/en.json') },
zh: { translation: require('./locales/zh.json') }
}
});
app.use(i18nextMiddleware.handle(i18next));
app.get('/', (req, res) => {
res.send(req.t('welcome_message'));
});
Monitoring and Metrics
express-status-monitor
Real-time application monitoring dashboard.
const expressStatusMonitor = require('express-status-monitor');
app.use(expressStatusMonitor({
path: '/status',
spans: [
{ interval: 1, retention: 60 }, // 1-minute sampling, retain 60 data points
{ interval: 5, retention: 60 },
{ interval: 15, retention: 60 }
],
chartVisibility: {
cpu: true,
mem: true,
load: true,
responseTime: true,
rps: true,
statusCodes: true
}
}));
prom-client
Prometheus metrics collection.
const promBundle = require('express-prom-bundle');
const metricsMiddleware = promBundle({
includeMethod: true,
includePath: true,
customLabels: { project_name: 'hello_world' },
promClient: {
collectDefaultMetrics: {
timeout: 1000
}
}
});
app.use(metricsMiddleware);
// Expose metrics endpoint
app.get('/metrics', (req, res) => {
res.set('Content-Type', promBundle.register.contentType);
res.end(promBundle.register.metrics());
});
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:中间件的复用与模块化
下一篇:中间件的性能影响分析