Использование middleware
Express — это фреймворк для веб-приложений с маршрутизацией и middleware, который обладает минимальной функциональностью: приложение Express в основном представляет собой последовательность вызовов middleware-функций.
Middleware-функции — это функции, которые имеют доступ к объекту запроса request object (req), объекту ответа response object (res) и следующей middleware-функции в цикле запроса-ответа приложения. Следующая middleware-функция обычно обозначается переменной под именем next.
Middleware-функции могут выполнять следующие задачи:
- Выполнить любой код.
- Внести изменения в объекты запроса и ответа.
- Завершить цикл запроса-ответа.
- Вызвать следующую middleware-функцию в стеке.
Если текущая middleware-функция не завершает цикл запроса-ответа, она должна вызвать next(), чтобы передать управление следующей middleware-функции. В противном случае запрос зависнет.
Приложение Express может использовать следующие типы middleware:
- Middleware на уровне приложения
- Middleware на уровне маршрутизатора
- Middleware обработки ошибок
- Встроенное middleware
- Middleware сторонних разработчиков
Вы можете загрузить middleware на уровне приложения и маршрутизатора с необязательным путём монтирования. Вы также можете загрузить серию middleware-функций вместе, что создаёт подстек системы middleware в точке монтирования.
Middleware на уровне приложения
Привяжите middleware на уровне приложения к экземпляру объекта app object, используя функции app.use() и app.METHOD(), где METHOD — это HTTP-метод запроса, который обрабатывает middleware-функция (например, GET, PUT или POST) в нижнем регистре.
Этот пример показывает middleware-функцию без пути монтирования. Функция выполняется каждый раз, когда приложение получает запрос.
const express = require('express')
const app = express()
app.use((req, res, next) => {
console.log('Time:', Date.now())
next()
})
Этот пример показывает middleware-функцию, смонтированную на пути /user/:id. Функция выполняется для любого типа HTTP-запроса на пути /user/:id.
app.use('/user/:id', (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
Этот пример показывает маршрут и его обработчик (middleware-система). Функция обрабатывает запросы GET на путь /user/:id.
app.get('/user/:id', (req, res, next) => {
res.send('USER')
})
Вот пример загрузки серии middleware-функций в точке монтирования с путём монтирования. Он иллюстрирует подстек middleware, который выводит информацию о запросе для любого типа HTTP-запроса на путь /user/:id.
app.use('/user/:id', (req, res, next) => {
console.log('Request URL:', req.originalUrl)
next()
}, (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
Обработчики маршрутов позволяют определить несколько маршрутов для одного пути. В примере ниже определены два маршрута для запросов GET на путь /user/:id. Второй маршрут не вызовет проблем, но никогда не будет вызван, потому что первый маршрут завершает цикл запроса-ответа.
Этот пример показывает подстек middleware, который обрабатывает запросы GET на путь /user/:id.
app.get('/user/:id', (req, res, next) => {
console.log('ID:', req.params.id)
next()
}, (req, res, next) => {
res.send('User Info')
})
// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', (req, res, next) => {
res.send(req.params.id)
})
Чтобы пропустить оставшиеся middleware-функции из стека middleware маршрутизатора, вызовите next('route'), чтобы передать управление следующему маршруту. ПРИМЕЧАНИЕ: next('route') будет работать только в middleware-функциях, загруженных с помощью функций app.METHOD() или router.METHOD().
Этот пример показывает подстек middleware, который обрабатывает запросы GET на путь /user/:id.
app.get('/user/:id', (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()
}, (req, res, next) => {
// send a regular response
res.send('regular')
})
// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req, res, next) => {
res.send('special')
})
Middleware также можно объявить в массиве для повторного использования.
Этот пример показывает массив с подстеком middleware, который обрабатывает запросы GET на путь /user/:id.
function logOriginalUrl (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}
function logMethod (req, res, next) {
console.log('Request Type:', req.method)
next()
}
const logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, (req, res, next) => {
res.send('User Info')
})
Middleware на уровне маршрутизатора
Middleware на уровне маршрутизатора работает так же, как middleware на уровне приложения, за исключением того, что он привязан к экземпляру express.Router().
const router = express.Router()
Загрузите middleware на уровне маршрутизатора, используя функции router.use() и router.METHOD().
Следующий пример кода воспроизводит систему middleware, показанную выше для middleware на уровне приложения, используя middleware на уровне маршрутизатора:
const express = require('express')
const app = express()
const router = express.Router()
// a middleware function with no mount path. This code is executed for every request to the router
router.use((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', (req, res, next) => {
console.log('Request URL:', req.originalUrl)
next()
}, (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', (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()
}, (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', (req, res, next) => {
console.log(req.params.id)
res.render('special')
})
// mount the router on the app
app.use('/', router)
Чтобы пропустить оставшиеся функции middleware маршрутизатора, вызовите next('router'), чтобы передать управление обратно из экземпляра маршрутизатора.
Этот пример показывает подстек middleware, который обрабатывает запросы GET на путь /user/:id.
const express = require('express')
const app = express()
const router = express.Router()
// predicate the router with a check and bail out when needed
router.use((req, res, next) => {
if (!req.headers['x-auth']) return next('router')
next()
})
router.get('/user/:id', (req, res) => {
res.send('hello, user!')
})
// use the router and 401 anything falling through
app.use('/admin', router, (req, res) => {
res.sendStatus(401)
})
Middleware обработки ошибок
Middleware обработки ошибок всегда принимает четыре аргумента. Вы должны предоставить четыре аргумента, чтобы идентифицировать его как функцию middleware обработки ошибок. Даже если вам не нужно использовать объект next, вы должны указать его, чтобы сохранить сигнатуру. В противном случае, объект next будет интерпретирован как обычная middleware, и не сможет обработать ошибки.
Определите функции middleware обработки ошибок так же, как и другие middleware-функции, но с четырьмя аргументами вместо трёх, то есть с сигнатурой (err, req, res, next)):
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something broke!')
})
Подробную информацию о middleware обработки ошибок см. в разделе: Обработка ошибок.
Встроенное middleware
Начиная с версии 4.x, Express больше не зависит от Connect. Middleware-функции, которые ранее были включены в Express, теперь находятся в отдельных модулях; см. список middleware-функций.
Express имеет следующие встроенные middleware-функции:
- express.static обслуживает статические ресурсы, такие как HTML-файлы, изображения и т.д.
- express.json парсит входящие запросы с JSON-payload. ПРИМЕЧАНИЕ: Доступно с Express 4.16.0+
- express.urlencoded парсит входящие запросы с URL-encoded payload. ПРИМЕЧАНИЕ: Доступно с Express 4.16.0+
Middleware сторонних разработчиков
Используйте middleware сторонних разработчиков, чтобы добавить функциональность в приложения Express.
Установите модуль Node.js для необходимой функциональности, а затем загрузите его в ваше приложение на уровне приложения или на уровне маршрутизатора.
Следующий пример иллюстрирует установку и загрузку cookie-парсинг middleware-функции cookie-parser.
$ npm install cookie-parser
const express = require('express')
const app = express()
const cookieParser = require('cookie-parser')
// load the cookie-parsing middleware
app.use(cookieParser())
Неполный список middleware-функций сторонних разработчиков, которые обычно используются с Express, см.: Middleware сторонних разработчиков.
© 2017 StrongLoop, IBM, and other expressjs.com contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v3.0.
https://expressjs.com/en/guide/using-middleware.html