Node.js+Webpack开发实战
上QQ阅读APP看书,第一时间看更新

4.6 中间件

中间件是一个函数,在应用的请求-响应周期中,能够访问请求对象、响应对象和next函数。

中间件可以执行以下任务:

· 执行逻辑代码。

· 更改请求和响应对象。

· 结束请求-响应周期。

· 调用下一个中间件。

如果当前的中间件没有调用next(),也没有结束请求-响应周期,则该请求将被挂起。

中间件有路由中间件和全局中间件两种。全局中间件对任何请求都会生效,路由中间件只对特定的路由生效。

4.6.1 全局中间件

以下是全局的日志中间件示例,该中间件打印当前的请求方法、请求路径以及User-Agent。

访问http://localhost:8080,客户端会收到Hello World响应,并且在终端会输出以下日志:

GET / "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"

GET /favicon.ico "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"

访问http://localhost:8080/user,客户端会收到user响应,终端同样会输出请求日志。

4.6.2 路由中间件

还是以刚才的中间件为例,不过我们将其挂载到特定的路由上。

访问http://localhost:8080,终端会输出请求日志,但是访问http://localhost:8080/user时终端不会输出请求日志。

4.6.3 可配置的中间件

在请求对象这一节中,我们使用了如下代码来挂载中间件。

app.use(cookieParser());

在上面的内容中,我们使用的下面代码。

app.use(logger);

cookieParser()是函数调用,支持传入配置,并且返回一个中间件。cookieParser()的代码结构如下:

function cookieParser(options) {
  return function(req, resp, next) {

  };
}

我们针对日志中间件做一下修改来支持配置:

4.6.4 Cookie中间件

在前面的内容中我们使用cookie-parser来读取cookie,本节将和大家一起来编写一个cookie-parser。

通过请求报头可以获取原始的cookie请求报头:

可以看到每个cookie之间以分号分隔,cookie的名字和cookie值通过等号分隔,所以编写cookie的思路如下:

(1)读取请求报头的cookie字段。

(2)使用";"来分隔每个cookie。

(3)针对单个cookie,使用"="分隔名字和值。

(4)将获取到的cookie名字和值挂载到req.cookies对象上。

4.6.5 响应时长中间件

有些场景下需要统计请求开始到请求结束阶段,服务器处理请求所花费的时长,目前的中间件是无法获取到“请求结束”事件的。

Express的响应对象提供了“finish”事件来告知请求结束事件。我们基于该事件来编写响应时长中间件。

访问http://localhost:8080时,终端会打印响应时长。

监听resp事件需要使用once,使用on会引起内存泄露。

4.6.6 静态资源中间件

为了提供图片、CSS和JS之类的静态文件的访问,可以使用内置的express.static中间件。

express.static(root, [options])

· root:服务器文件夹路径。

· options:选项。

以下是一个提供静态资源访问的示例。

项目目录结构如下:

// 导入express模块
const express = require('express');
const app = express();

app.use(express.static('./public')); // 将静态资源中间件挂载到全局

// 开启监听
app.listen(8080, () => {
    console.log('listen on 8080');
});

上面的代码需要访问http://localhost:8080/css/style.css才能获取style.css。

也就是说public目录在请求链接中不能出现,如果需要将静态资源挂载到/public这个路由前缀下,可以使用下面的代码:

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

上面的代码需要访问http://localhost:8080/public/css/style.css才能获取style.css。