图文解说:请求与响应-Laravel 底层是如何处理 HTTP 请求的
学习链接
流程
文字版: 下面也有。
- 全局中间件都校验通过才会将请求分发到路由器进行处理
- 路由器会将进行匹配传入request 是否已经注册
- 有路由,找到对应的中间件
- 路由中间件对请求进行过滤
- 运行对应的匿名函数或控制器方法,处理逻辑
- 响应客户端
- 终止kernel,终止中间件,以及注册到服务容器的一些终止回调
注意: 最后回到route 是在 response 中进行了兜底处理。
可以看下一篇文章。
看源代码
- 所有 HTTP 请求都会被转发到单入口文件
public/index.php
- 首先会创建一个 Application 实例,作为全局的服务容器
- 将处理请求的核心类 Kernel 实现实例绑定到该容器中
- 通过服务器捕获请求并将其传递给 Kernel 实例进行处理,处理结果是准备好的响应实例
- 调用该响应实例的 send() 方法即可将其发送给发起请求的客户端
- 执行 Kernel 实例上的 terminate() 终止程序,退出脚本。
核心逻辑位于 $kernel->handle() 方法调用中
核心逻辑位于 $kernel->handle()
1. 服务容器
首先 在index.php 中我们看下这段代码:
// 从服务容器中解析处理 HTTP 请求的 Kernel 实例
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
在上面的代码中,$app
对应的就是服务容器实例,并且在我们获取到该实例后就注册了 Kernel 接口及其实现类到容器中:
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
singleton
方法会以单例方式在服务容器中将 App\Http\Kernel
实例绑定到 Illuminate\Contracts\Http\Kernel
接口,后续我们要获取 App\Http\Kernel
实例,就可以通过 Illuminate\Contracts\Http\Kernel
接口从服务容器中获取,获取方法是 $app->make()
:
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
2. 回到 Kernel
打开 Illuminate\Foundation\Http\Kernel
(App\Http\Kernel
的父类),查看 handle
方法,可以看到核心处理逻辑
通过
sendRequestThroughRouter
方法实现核心处理逻辑在发送请求到路由之前,先调用 bootstrap() 方法运用应用的启动类
这些个启动类在路由解析之前执行,相当于对整个应用进行初始化。主要包含:加载环境变量和全局配置、配置异常处理逻辑、注册门面和服务提供者以及执行所有已注册服务提供者的 boot 方法等等。
开始真正的 HTTP 请求处理
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
Laravel 框架以管道模式来处理 HTTP 请求,首先通过全局中间件对请求进行处理,如果返回 false 直接退出,不会做路由解析处理。
路由解析处理过程
- 全局中间件都校验通过才会将请求分发到路由器进行处理
- 路由器会将进行匹配传入request 是否已经注册
- 有路由,找到对应的中间件
- 路由中间件对请求进行过滤
- 运行对应的匿名函数或控制器方法,处理逻辑
- 响应客户端
3. 终止 Kernel
响应准备就绪后,就会通过 $response->send()
发送给发起请求的客户端,之后还要运行 $kernel->terminate()
做一些善后清理工作,并最终退出脚本。这些善后清理工作主要包括运行终止中间件,以及注册到服务容器的一些终止回调