HTTP 概览
AdonisJS 主要是一个用来创建响应 HTTP 请求的应用的 Web 框架。在本指南中,我们将了解 AdonisJS 如何启动 HTTP 服务器、处理传入的请求,以及 HTTP 层可用的模块。
HTTP 层
AdonisJS 应用内部的 HTTP 层由以下模块组成。值得说明的是,AdonisJS 的 HTTP 层是从零开始构建的,底层并没有使用任何微框架。
-
router 模块 负责定义应用的端点,也就是所谓的路由。一个路由应当定义一个负责处理请求的 handler。该 handler 可以是一个闭包,也可以是对某个控制器的引用。
-
控制器是你绑定到路由上以处理 HTTP 请求的 JavaScript 类。控制器充当组织层,帮助你将应用的业务逻辑划分到不同的文件/类中。
-
AdonisJS 会为每个传入的 HTTP 请求创建 HttpContext 类的一个实例。HttpContext(即
ctx)携带了给定请求的信息,例如请求体、请求头、已认证的用户等。 -
AdonisJS 中的中间件管道是对责任链(Chain of Responsibility)设计模式的实现。你可以使用中间件在 HTTP 请求到达路由 handler 之前拦截并响应它们。
-
全局异常处理器在一个集中的位置处理 HTTP 请求期间抛出的异常。你可以使用全局异常处理器将异常转换为 HTTP 响应,或者将它们上报给外部的日志服务。
-
Server
-
server 模块 将路由器、中间件和全局异常处理器连接在一起,并导出一个
handle函数,你可以将它绑定到 Node.js HTTP 服务器上以处理请求。
AdonisJS 如何启动 HTTP 服务器
HTTP 服务器是在你调用 Server 类上的 the boot method 时启动的。在底层,该方法执行以下操作。
- 创建中间件管道
- 编译路由
- 导入并实例化全局异常处理器
在典型的 AdonisJS 应用中,boot 方法由 bin/server.ts 文件中的 Ignitor 模块调用。
此外,在调用 boot 方法之前定义路由、中间件和全局异常处理器是至关重要的,而 AdonisJS 通过使用 start/routes.ts 和 start/kernel.ts 预加载文件 来实现这一点。
HTTP 请求生命周期
既然我们已经有了一个正在监听传入请求的 HTTP 服务器,让我们来看看 AdonisJS 如何处理一个给定的 HTTP 请求。
- 创建 HttpContext
-
作为第一步,server 模块会创建 HttpContext 类的一个实例,并将其作为引用传递给中间件、路由 handler 和全局异常处理器。
如果你启用了 AsyncLocalStorage,那么同一个实例会被共享为本地存储状态。
- 执行 server 中间件栈
-
接下来,server 中间件栈 中的中间件会被执行。这些中间件可以在请求到达路由 handler 之前拦截并响应请求。
此外,即使你没有为给定端点定义任何路由,每个 HTTP 请求都会经过 server 中间件栈。这使得 server 中间件能够在不依赖路由系统的情况下为应用添加功能。
- 查找匹配的路由
-
如果 server 中间件没有结束请求,我们会为
req.url属性查找匹配的路由。当不存在匹配的路由时,请求会以404 - Not found异常中止。否则,我们会继续处理该请求。 - 执行路由中间件
-
一旦存在匹配的路由,我们就会执行路由全局中间件 和命名中间件栈。同样,中间件可以在请求到达路由 handler 之前拦截请求。
- 执行路由 handler
-
作为最后一步,请求到达路由 handler,并带着一个响应返回给客户端。
假设在流程的任意步骤中抛出了异常,那么请求将被移交给全局异常处理器,由它负责将异常转换为响应。
- 序列化响应
-
一旦你使用
response.send方法定义了响应体,或者从路由 handler 返回了一个值,我们就会开始响应序列化过程,并设置相应的请求头。了解更多关于响应体序列化的内容