← Назад к вопросам

Сталкивался ли с Middleware

1.0 Junior🔥 231 комментариев
#Node.js и JavaScript#Фреймворки и библиотеки

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Опыт работы с 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);
});

Важные моменты

  1. Порядок имеет значение — middleware выполняются по порядку их регистрации
  2. Обработка ошибок — всегда оборачивай async middleware в try-catch
  3. Производительность — избегай тяжёлых операций в middleware
  4. Статус code — всегда явно указывай правильные коды ответов
  5. Логирование — логирование middleware должно быть одним из первых

Middleware — это один из самых мощных инструментов в Node.js для построения чистого, масштабируемого кода.

Сталкивался ли с Middleware | PrepBro