Перейти к содержанию

Использование промежуточных обработчиков

Express - это веб-фреймворк маршрутизации и промежуточной обработки с минимальной собственной функциональностью: приложение Express, по сути, представляет собой серию вызовов функций промежуточной обработки.

Функции промежуточной обработки (middleware) - это функции, имеющие доступ к объекту запроса (req), объекту ответа (res) и к следующей функции промежуточной обработки в цикле "запрос-ответ" приложения. Следующая функция промежуточной обработки, как правило, обозначается переменной next.

Функции промежуточной обработки могут выполнять следующие задачи:

  • Выполнение любого кода.
  • Внесение изменений в объекты запросов и ответов.
  • Завершение цикла "запрос-ответ".
  • Вызов следующей функции промежуточной обработки из стека.

Если текущая функция промежуточной обработки не завершает цикл "запрос-ответ", она должна вызвать next() для передачи управления следующей функции промежуточной обработки. В противном случае запрос зависнет.

Приложение Express может использовать следующие типы промежуточных обработчиков:

  • Промежуточный обработчик уровня приложения
  • Промежуточный обработчик уровня маршрутизатора
  • Промежуточный обработчик для обработки ошибок
  • Встроенные промежуточные обработчики
  • Промежуточные обработчики сторонних поставщиков ПО

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

Промежуточный обработчик уровня приложения

Свяжите промежуточный обработчик уровня приложения с экземпляром объекта приложения, воспользовавшись функциями app.use() и app.METHOD(), где METHOD - метод HTTP запроса, обрабатываемый функцией промежуточной обработки (например, GET, PUT или POST) в нижнем регистре.

В данном примере представлена функция промежуточной обработки без пути монтирования. Эта функция выполняется при каждом получении запроса приложением.

1
2
3
4
5
6
var app = express();

app.use(function (req, res, next) {
    console.log('Time:', Date.now());
    next();
});

В данном примере представлена функция промежуточной обработки, монтируемая в путь /user/:id. Эта функция выполняется для всех типов запросов HTTP в пути /user/:id.

1
2
3
4
app.use('/user/:id', function (req, res, next) {
    console.log('Request Type:', req.method);
    next();
});

В данном примере представлен маршрут и функция его обработки (система промежуточных обработчиков). Эта функция обрабатывает запросы GET, адресованные ресурсам в пути /user/:id.

1
2
3
app.get('/user/:id', function (req, res, next) {
    res.send('USER');
});

Ниже приводится пример загрузки последовательности функций промежуточной обработки в точку монтирования, с указанием пути монтирования. Этот пример иллюстрирует создание вспомогательного стека промежуточных обработчиков, с выводом информации о запросе для всех типов запросов HTTP, адресованных ресурсам в пути /user/:id.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
app.use(
    '/user/:id',
    function (req, res, next) {
        console.log('Request URL:', req.originalUrl);
        next();
    },
    function (req, res, next) {
        console.log('Request Type:', req.method);
        next();
    }
);

Обработчики маршрутов позволяют определить несколько маршрутов для одного пути. В приведенном ниже примере определено два маршрута для запросов GET, адресованных ресурсам в пути /user/:id. Второй маршрут не создает никаких неудобств, но его вызов никогда не будет выполнен, поскольку первый маршрут завершает цикл "запрос-ответ".

В данном примере представлен вспомогательный стек промежуточных обработчиков для обработки запросов GET, адресованных ресурсам в пути /user/:id.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
app.get(
    '/user/:id',
    function (req, res, next) {
        console.log('ID:', req.params.id);
        next();
    },
    function (req, res, next) {
        res.send('User Info');
    }
);

// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', function (req, res, next) {
    res.end(req.params.id);
});

Для того чтобы пропустить остальные функции дополнительной обработки в стеке промежуточных обработчиков маршрутизатора, вызовите next('route') для передачи управления следующему маршруту. ПРИМЕЧАНИЕ: next('route') работает только в функциях промежуточной обработки, загруженных с помощью функций app.METHOD() или router.METHOD().

В данном примере представлен вспомогательный стек промежуточных обработчиков для обработки запросов GET, адресованных ресурсам в пути /user/:id.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
app.get(
    '/user/:id',
    function (req, res, next) {
        // if the user ID is 0, skip to the next route
        if (req.params.id == 0) next('route');
        // otherwise pass the control to the next middleware function in this stack
        else next(); //
    },
    function (req, res, next) {
        // render a regular page
        res.render('regular');
    }
);

// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {
    res.render('special');
});

Промежуточный обработчик уровня маршрутизатора

Промежуточный обработчик уровня маршрутизатора работает так же, как и промежуточный обработчик уровня приложения, но он привязан к экземпляру express.Router().

1
var router = express.Router();

Загрузите промежуточный обработчик уровня маршрутизатора с помощью функций router.use() и router.METHOD().

В приведенном ниже примере с помощью промежуточного обработчика уровня маршрутизатора создается копия системы промежуточных обработчиков, представленной выше для обработчиков уровня приложения:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
var app = express();
var router = express.Router();

// a middleware function with no mount path. This code is executed for every request to the router
router.use(function (req, res, next) {
    console.log('Time:', Date.now());
    next();
});

// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use(
    '/user/:id',
    function (req, res, next) {
        console.log('Request URL:', req.originalUrl);
        next();
    },
    function (req, res, next) {
        console.log('Request Type:', req.method);
        next();
    }
);

// a middleware sub-stack that handles GET requests to the /user/:id path
router.get(
    '/user/:id',
    function (req, res, next) {
        // if the user ID is 0, skip to the next router
        if (req.params.id == 0) next('route');
        // otherwise pass control to the next middleware function in this stack
        else next(); //
    },
    function (req, res, next) {
        // render a regular page
        res.render('regular');
    }
);

// handler for the /user/:id path, which renders a special page
router.get('/user/:id', function (req, res, next) {
    console.log(req.params.id);
    res.render('special');
});

// mount the router on the app
app.use('/', router);

Промежуточный обработчик для обработки ошибок

Промежуточный обработчик ошибок всегда содержит четыре аргумента. Для определения данной функции как обработчика ошибок необходимо указать четыре аргумента. Даже если вам не нужно использовать объект next, необходимо указать его, чтобы сохранить сигнатуру. В противном случае, объект next будет интерпретирован как обычный промежуточный обработчик, который не будет обрабатывать ошибки.

Определите функции промежуточного обработчика для обработки ошибок так же, как другие функции промежуточной обработки, но с указанием не трех, а четырех аргументов в сигнатуре (err, req, res, next)):

1
2
3
4
app.use(function (err, req, res, next) {
    console.error(err.stack);
    res.status(500).send('Something broke!');
});

Подробная информация о промежуточном обработчике ошибок приведена в разделе Обработка ошибок.

Встроенные промежуточные обработчики

Начиная с версии 4.x, Express не является зависимым от Connect. За исключением express.static, все функции промежуточной обработки, ранее включенные в Express, находятся в отдельных модулях. Ознакомьтесь со списком функций промежуточной обработки.

express.static(root, [options])

Единственной встроенной функцией промежуточной обработки в Express является express.static. Эта функция основана на serve-static и отвечает за предоставление статических ресурсов приложения Express.

Аргумент root указывает на корневой каталог, из которого предоставляются статические ресурсы.

Необязательный объект options может содержать следующие свойства:

Свойство Описание Тип По умолчанию
dotfiles Опция для предоставления файлов с точкой. Возможные значения - "allow", "deny", "ignore" Строка "ignore"
etag Включение или отключение генерации etag Булевский true
extensions Установка альтернативных вариантов расширений файлов. Массив []
index Отправка файла индекса каталога. Установите значение false, чтобы отключить индексацию каталога. Смешанный "index.html"
lastModified Установка в заголовке Last-Modified даты последнего изменения файла в ОС. Возможные значения: true или false. Булевский true
maxAge Установка значения свойства max-age в заголовке Cache-Control, в миллисекундах, или в виде строки в формате ms Число 0
redirect Перенаправление к заключительному символу "/", если имя пути - это каталог. Булевский true
setHeaders Функция для установки заголовков HTTP, предоставляемых с файлом. Функция

Ниже приводится пример использования функции промежуточной обработки express.static с объектом дополнительных опций:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var options = {
    dotfiles: 'ignore',
    etag: false,
    extensions: ['htm', 'html'],
    index: false,
    maxAge: '1d',
    redirect: false,
    setHeaders: function (res, path, stat) {
        res.set('x-timestamp', Date.now());
    },
};

app.use(express.static('public', options));

Для каждого приложения допускается наличие нескольких статических каталогов:

1
2
3
app.use(express.static('public'));
app.use(express.static('uploads'));
app.use(express.static('files'));

Дополнительную информацию о функции serve-static и ее опциях можно найти в документации по serve-static.

Промежуточные обработчики сторонних поставщиков ПО

Для расширения функциональности приложений Express используются промежуточные обработчики сторонних поставщиков ПО.

Установите модуль Node.js для соответствующей функциональной возможности, затем загрузите его в приложение на уровне приложения или на уровне маршрутизатора.

В приведенном ниже примере показана установка и загрузка функции промежуточной обработки для синтаксического анализа cookie cookie-parser.

1
$ npm install cookie-parser
1
2
3
4
5
6
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');

// load the cookie-parsing middleware
app.use(cookieParser());

Список функций промежуточных обработчиков, предоставляемых сторонними поставщиками ПО и часто используемых в Express, приведен в разделе Промежуточные обработчики сторонних поставщиков ПО.

Комментарии