Сталкивался ли с Middleware
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Опыт работы с Middleware в Node.js
Да, middleware — это один из базовых инструментов, с которыми я работаю ежедневно. Это паттерн, который критически важен в Node.js приложениях, особенно в Express, Fastify и других фреймворках.
Что такое Middleware
Middleware — это функция, которая обрабатывает HTTP запрос, выполняет какую-то логику и либо отправляет ответ, либо передаёт управление следующему middleware через next().
Визуально это выглядит как конвейер:
Request → [Middleware 1] → [Middleware 2] → [Middleware 3] → Handler → Response
Примеры middleware, которые использую
1. Authentication Middleware:
const express = require('express');
const app = express();
const authMiddleware = (req, res, next) => {
const token = req.headers['authorization']?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next(); // Передаём управление следующему middleware
} catch (error) {
return res.status(403).json({ error: 'Invalid token' });
}
};
app.use(authMiddleware); // Применяем ко всем маршрутам
2. Logging Middleware:
const loggingMiddleware = (req, res, next) => {
const startTime = Date.now();
res.on('finish', () => {
const duration = Date.now() - startTime;
console.log(`[${new Date().toISOString()}] ${req.method} ${req.path} - ${res.statusCode} (${duration}ms)`);
});
next();
};
app.use(loggingMiddleware);
3. CORS Middleware:
const corsMiddleware = (req, res, next) => {
res.header('Access-Control-Allow-Origin', process.env.ALLOWED_ORIGINS);
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
};
app.use(corsMiddleware);
4. Error Handling Middleware:
const errorMiddleware = (err, req, res, next) => {
console.error('Error:', err);
const statusCode = err.statusCode || 500;
const message = err.message || 'Internal Server Error';
res.status(statusCode).json({
error: message,
...(process.env.NODE_ENV === 'development' && { stack: err.stack })
});
};
// ВАЖНО: Error middleware должен быть последним!
app.use(errorMiddleware);
Порядок применения middleware
Порядок очень важен:
const express = require('express');
const app = express();
// 1. Парсирование тела запроса (должно быть первым)
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 2. Логирование
app.use(loggingMiddleware);
// 3. CORS
app.use(corsMiddleware);
// 4. Аутентификация
app.use(authMiddleware);
// 5. Бизнес-логика (роуты)
app.get('/api/users/:id', async (req, res) => {
// На этот момент req.user уже задан
res.json(await getUser(req.user.id, req.params.id));
});
// 6. Обработка ошибок (должно быть последним)
app.use(errorMiddleware);
Async Middleware в современных фреймворках
В Express и Fastify можно использовать async функции, но нужно обрабатывать ошибки:
const asyncMiddleware = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
const authMiddlewareAsync = asyncMiddleware(async (req, res, next) => {
const token = req.headers['authorization']?.replace('Bearer ', '');
try {
const decoded = await verifyTokenAsync(token);
req.user = decoded;
next();
} catch (error) {
res.status(403).json({ error: 'Invalid token' });
}
});
app.use(authMiddlewareAsync);
Fastify Hooks (альтернатива middleware)
В Fastify используются hooks вместо middleware, но логика похожа:
const fastify = require('fastify')();
fastify.register(async (fastify) => {
// onRequest hook — как middleware в Express
fastify.addHook('onRequest', async (request, reply) => {
const startTime = Date.now();
reply.addHook('onSend', async () => {
const duration = Date.now() - startTime;
console.log(`${request.method} ${request.url} (${duration}ms)`);
});
});
// onRequest hook для аутентификации
fastify.addHook('onRequest', async (request, reply) => {
const token = request.headers['authorization']?.replace('Bearer ', '');
if (!token) {
reply.code(401).send({ error: 'No token' });
}
});
});
Практические примеры из реальных проектов
Rate Limiting:
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 минут
max: 100, // Максимум 100 запросов в окно
message: 'Too many requests, please try again later'
});
app.use('/api/', limiter);
Валидация тела запроса:
const validateMiddleware = (schema) => (req, res, next) => {
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.details[0].message });
}
req.validated = value;
next();
};
const userSchema = joi.object({
email: joi.string().email().required(),
password: joi.string().min(6).required()
});
app.post('/register', validateMiddleware(userSchema), async (req, res) => {
// req.validated уже содержит валидные данные
const user = await createUser(req.validated);
res.json(user);
});
Важные моменты
- Порядок имеет значение — middleware выполняются по порядку их регистрации
- Обработка ошибок — всегда оборачивай async middleware в try-catch
- Производительность — избегай тяжёлых операций в middleware
- Статус code — всегда явно указывай правильные коды ответов
- Логирование — логирование middleware должно быть одним из первых
Middleware — это один из самых мощных инструментов в Node.js для построения чистого, масштабируемого кода.