中间件

概述

生活中的例子:在处理污水的时候,一般要经过一下步骤,从而保证处理后的污水能达到排放标准

中间件函数是在应用程序的请求-响应周期中可以访问请求对象、响应对象和next函数的函数

next 函数是Express路由中的一个函数,当被调用时,会在当前中间件之后执行中间件

编写中间件

普通中间件

中间件函数的示例 myLogger

1
2
3
4
const myLogger = function(req,res,next) {
console.log('LOGGED')
next()
}

注意:在中间件函数的最后需要调用next()函数。这样会调用应用程序的下一个中间件函数。next()可以命名任何名称,因为是函数参数,但是按照惯例,使用’next’约定俗成

定义好中间件,需要挂载中间件,使应用接受请求先处理中间件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const express = require('express')
const app = express()

const myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}

app.use(myLogger)

app.get('/', (req, res) => {
res.send('Hello World!')
})

app.listen(3000)

应用程序每次接受请求,都会打印LOGGED

中间件添加请求对象属性

1
2
3
4
const requestTime = function(req, res, next){
req.requestTime = Date.now()
next()
}

该程序使用requestTime中间件函数。在执行函数过程中,为请求对象req添加了requestTime属性,这样在处理请求的函数中,就可以直接获得请求对象该属性

中间件函数处理Cookie

创建中间件验证传入的cookie并在cookie无效时发送400响应

这是一个使用外部异步服务验证cookie的示例函数

1
2
3
4
5
6
7
async function cookieValidator(cookies){
try{
await externallyValidateCookie(cookie.testCookie)
}catch{
throw new Error('Invalid cookies')
}
}

使用cookie-parser中间件从req对象中解析传入的cookie并将它们传递给cookieValidator函数.

validateCookies中间件返回一个Promise,在拒绝时会自动触发我们的错误处理程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const express = require('express')
const cookieParser = require('cookie-parser')
const cookieValidator = require('./cookieValidator')

const app = express()

async function validateCookies(req,res,next){
await cookieValidator(req.cookies)
next()
}

app.use(cookieParser())
app.use(validatoCookies)

app.use((err,req,res,next)=>{
res.status(400).send(err.message)
})

app.listen(3000)

可配置的中间件

如果需要可配置的中间件,导出一个接受选项对象或函数,根据输入参数返回中间件实现

如下:

my-middleware.js

1
2
3
4
5
6
module.exports = function(opstions){
return function(req,res,next){
// Implement the middleware function based on the options object
next()
}
}

使用中间件,如下所示:

1
2
const mw = require('./my-middleware.js')
app.use(mw({option1: '1', option2: '2'}))

使用中间件

Express应用程序可以使用以下类型的中间件

  • 应用级中间件
  • 路由级中间件
  • 错误处理中间件
  • 内置中间件
  • 第三方中间件

应用级中间件

通过 app.use()app.get()app.post(),绑定到app实例上的中间件

没有挂载路径的中间件函数。每次应用收到请求时都会执行该函数

1
2
3
4
5
6
7
const express = require('express')
const app = express()

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

一个挂载在user/:id路径上的中间件函数。该函数针对/user/:id路径上的任何类型的HTTP请求执行

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

一个路由和它的处理函数。该函数处理GET请求

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

路由级中间件

工作方式与应用级中间件相同,绑定到express.Router()的实例上

1
const router = express.Router()

使用 router.userouter.METHOD()函数加载路由级中间件

错误处理中间件

错误处理中间件需要四个参数,以将其表示为中间件函数。即使不需要使用next对象,也必须指定它来维护签名。否则 会被解释成常规中间件。

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

使用错误处理中间件,捕获项目的错误,防止项目发生崩溃

内置中间件

Express具有一下内置中间件函数

  • express.static 提供静态资源

  • express.json 提供JSON有效负载解析传入请求

  • express.urlencoded 使用URL编码的负载解析传入的请求

1
2
app.use(express.json())
app.use(express.urlencoded({extended: false}))

1.托管静态资源

(1)express提供了一个非常好用的函数,叫做express.static(),通过它,我们可以非常方便地创建一个静态资源服务器

1
app.use(express.static('public'))

Express在指定的静态目录中查找文件,并对外提供资源的访问路径。因此,存放静态文件的目录名不会出现在URL中

(2)托管多个静态资源目录

需要多次调用expres.static()函数

访问静态资源文件时,express.static()函数会根据目录的添加顺序查找所需的文件

(3)挂载路径前缀

1
app.use('/public',express.static('public'))

2.JSON内置中间件

1
2
3
4
5
6
7
app.use(express.json())

app.post('/user',(req,res)=>{
//默认情况下,如果不配置解析表单数据的中间件,则req.body默认等于undefined
console.log(req.body)
res.send('ok')
})

3.urlencoded 中间件

1
2
3
4
app.use(express.urlencoded({extended: false}))
app.post('/user',(req,res)=>{
console.log(req.body)
})

第三方中间件

配置body-parser中间件

1
2
3
4
5
6
7
//导入解析表单数据中间件
const parser = require('body-parser')

app.use(parser.urlencoded({extended: false}))
app.post('/user',(req,res)=>{
console.log(req.body)
})