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

Какой подход обработки запросов использует Express.js?

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

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

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

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

Подход обработки запросов в Express.js

Express.js использует middleware pipeline подход (также известный как chain of responsibility pattern) для обработки HTTP запросов. Это последовательное прохождение запроса через цепочку обработчиков.

Основной принцип

Каждый middleware — это функция, которая имеет доступ к объектам request (req), response (res) и next middleware'у:

const express = require('express');
const app = express();

// Middleware 1
app.use((req, res, next) => {
  console.log('1. Middleware 1');
  next(); // Передача управления следующему middleware
});

// Middleware 2
app.use((req, res, next) => {
  console.log('2. Middleware 2');
  next();
});

// Обработчик маршрута (тоже middleware)
app.get('/users', (req, res) => {
  console.log('3. Route handler');
  res.json({ users: [] });
});

// Порядок выполнения: 1 -> 2 -> 3 обработчик маршрута

Типы middleware в Express

Application-level middleware — применяется ко всем или определённым маршрутам:

// Глобальный middleware (для всех запросов)
app.use(express.json());

// Selective middleware (только для /api маршрутов)
app.use('/api', (req, res, next) => {
  console.log('API request');
  next();
});

Router-level middleware — применяется к определённому роутеру:

const router = express.Router();

router.use((req, res, next) => {
  console.log('User router middleware');
  next();
});

router.get('/', (req, res) => {
  res.json({ users: [] });
});

app.use('/users', router);

Built-in middleware — встроенные в Express:

app.use(express.json());        // Парсинг JSON
app.use(express.urlencoded()); // Парсинг form data
app.use(express.static('public')); // Статические файлы

Third-party middleware — внешние пакеты:

const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');

app.use(helmet());      // Безопасность
app.use(cors());        // CORS
app.use(morgan('combined')); // Логирование

Custom middleware — собственные функции:

// Аутентификация
const authMiddleware = (req, res, next) => {
  const token = req.headers.authorization;
  if (!token) {
    return res.status(401).json({ error: 'No token' });
  }
  // Проверка токена
  req.user = { id: 1, name: 'John' };
  next();
};

app.use(authMiddleware);

// Логирование
const logMiddleware = (req, res, next) => {
  console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`);
  next();
};

app.use(logMiddleware);

Error-handling middleware — обработка ошибок (4 параметра!):

// Должны иметь ровно 4 параметра для работы как error handler
app.use((err, req, res, next) => {
  console.error('Error:', err.message);
  res.status(500).json({ error: err.message });
});

// Это НЕ будет error handler (только 3 параметра)
app.use((req, res, next) => {
  // ...
});

Полный цикл обработки запроса

const express = require('express');
const app = express();

// Шаг 1: Парсинг тела запроса
app.use(express.json());

// Шаг 2: Логирование
app.use((req, res, next) => {
  console.log('LOG:', `${req.method} ${req.url}`);
  next();
});

// Шаг 3: Аутентификация
app.use((req, res, next) => {
  const token = req.headers.authorization;
  if (token) {
    req.user = { id: 1 }; // Упрощённо
  }
  next();
});

// Шаг 4: Маршруты
app.get('/users', (req, res) => {
  console.log('Getting users for user:', req.user?.id);
  res.json({ users: [{ id: 1, name: 'John' }] });
});

app.post('/users', (req, res) => {
  console.log('Creating user:', req.body);
  res.status(201).json({ id: 2, ...req.body });
});

// Шаг 5: 404 обработчик
app.use((req, res) => {
  res.status(404).json({ error: 'Not found' });
});

// Шаг 6: Error handling
app.use((err, req, res, next) => {
  console.error('ERROR:', err);
  res.status(500).json({ error: 'Internal server error' });
});

app.listen(3000);

// Порядок выполнения для GET /users:
// 1. express.json() middleware
// 2. Логирование middleware
// 3. Аутентификация middleware
// 4. Обработчик GET /users
// 5. Ответ отправлен

Управление потоком

next() — передаёт управление следующему middleware:

app.use((req, res, next) => {
  console.log('1');
  next(); // -> переход к следующему
});

app.use((req, res, next) => {
  console.log('2');
  // Если не вызвать next(), цепь разрывается
});

app.use((req, res, next) => {
  console.log('3'); // Не выполнится, если выше не вызван next()
});

Краткие ответы — остановка цепи:

app.use((req, res, next) => {
  if (req.path === '/admin' && !req.user?.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
    // return остановит выполнение
  }
  next();
});

Обработка ошибок — skip middleware и перейти к error handler:

app.use((req, res, next) => {
  try {
    // Some code
  } catch (err) {
    next(err); // Передаёт в error middleware
  }
});

// Error middleware поймёт ошибку
app.use((err, req, res, next) => {
  res.status(500).json({ error: err.message });
});

Преимущества подхода

Модульность — разделение логики на независимые middleware.

Переиспользуемость — один middleware применить к нескольким маршрутам.

Гибкость — легко добавлять, удалять, переупорядочивать обработчики.

Читаемость — цепь middleware читается как последовательность шагов.

Важные замечания

Express использует синхронный подход в цепи middleware. Если middleware содержит асинхронный код, нужно правильно обработать Promises:

// ✓ Правильно
app.use(async (req, res, next) => {
  try {
    const data = await fetchData();
    req.data = data;
    next();
  } catch (err) {
    next(err);
  }
});

// ✗ Неправильно (async ошибка не будет поймана)
app.use((req, res, next) => {
  fetchData().then(() => next());
  // Если ошибка в .then() — ничего не поймает
});

Middleware pipeline в Express — это мощный и гибкий подход, который позволяет строить сложные приложения из простых, модульных компонентов.