Middleware для маршрутов

Middleware — это функции, которые выполняются между запросом клиента и обработчиком маршрута на сервере. Они обеспечивают промежуточную обработку данных, проверку условий, модификацию запроса или ответа. В экосистеме Node.js и Express.js middleware занимает ключевое место, позволяя создавать гибкие и расширяемые серверные приложения.

Принципы работы middleware

Middleware получает три аргумента: req (объект запроса), res (объект ответа) и next (функция для передачи управления следующему middleware).

function exampleMiddleware(req, res, next) {
    console.log('Запрос обработан на уровне middleware');
    next();
}
  • req — содержит информацию о запросе: путь, параметры, тело, заголовки.
  • res — позволяет формировать ответ клиенту.
  • next — функция, вызываемая для передачи управления следующей функции middleware или маршруту.

Вызов next() обязателен, если нужно продолжить обработку запроса. Без него запрос зависнет.

Типы middleware

  1. Application-level middleware Применяется ко всем маршрутам приложения или к выбранным путем указания пути.
const express = require('express');
const app = express();

app.use((req, res, next) => {
    console.log('Application-level middleware');
    next();
});

app.get('/home', (req, res) => {
    res.send('Главная страница');
});
  1. Router-level middleware Привязан к конкретному маршрутизатору (express.Router). Используется для групп маршрутов с общими правилами.
const router = express.Router();

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

router.get('/profile', (req, res) => {
    res.send('Профиль пользователя');
});

app.use('/user', router);
  1. Error-handling middleware Обрабатывает ошибки, передаваемые через next(err). Должен иметь четыре аргумента: err, req, res, next.
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('Произошла ошибка на сервере');
});
  1. Built-in middleware Express предоставляет встроенные middleware для обработки JSON, статических файлов и данных формы.
app.use(express.json()); // парсит JSON из тела запроса
app.use(express.urlencoded({ extended: true })); // парсит данные формы
app.use(express.static('public')); // отдаёт статические файлы
  1. Third-party middleware Подключаются через npm и расширяют функциональность сервера: логирование (morgan), сессии (express-session), CORS (cors) и другие.
const morgan = require('morgan');
app.use(morgan('dev'));

Middleware для маршрутов

Middleware можно использовать на уровне отдельных маршрутов для проверки авторизации, валидации данных или логирования.

function authMiddleware(req, res, next) {
    if (req.headers.authorization === 'Bearer token') {
        next();
    } else {
        res.status(401).send('Неавторизован');
    }
}

app.get('/dashboard', authMiddleware, (req, res) => {
    res.send('Панель управления');
});
  • Порядок вызова имеет значение: middleware выполняются в том порядке, в котором они подключены.
  • Композиция middleware: несколько middleware можно объединять в массив.
app.post('/submit', [validateData, authMiddleware], (req, res) => {
    res.send('Данные отправлены');
});

Асинхронный middleware

Middleware может быть асинхронным с использованием async/await. При ошибках важно передавать их через next(err).

async function asyncMiddleware(req, res, next) {
    try {
        const data = await fetchDataFromDB();
        req.data = data;
        next();
    } catch (err) {
        next(err);
    }
}

Ограничения и советы

  • Не стоит использовать тяжелые операции внутри middleware без необходимости, чтобы не блокировать обработку запросов.
  • Middleware не должен завершать обработку ответа, если предполагается передача управления дальше.
  • Правильное расположение middleware критично: middleware, подключенные выше маршрутов, выполняются первыми.

Middleware для маршрутов является фундаментальным инструментом для организации серверной логики. Оно обеспечивает повторное использование кода, безопасность и масштабируемость приложений, позволяя создавать сложные цепочки обработки запросов с минимальным дублированием кода.