共计 3146 个字符,预计需要花费 8 分钟才能阅读完成。
上一回讲到给 Server 增加了 10 个 swoole 监听事件. | |
在增加完 swoole 的事件后, 框架调用 Swoft 的 trigger()办法触发了几种用户注册的生命周期事件. | |
接着框架调用 server 的 start()办法, 正式开始承受用户申请. |
本章将从 onRequest 事件着手, 逐渐剖析 Swoole 原生的 Request 及 Response 封装成 Swoft 中应用的 Swoft\Http\Message\Request 和 Swoft\Http\Message\Response 的过程.
先看 onRequest 代码:
public function onRequest(Request $request, Response $response): void | |
{$psrRequest = ServerRequest::new($request); | |
$psrResponse = ServerResponse::new($response); | |
$this->dispatcher->dispatch($psrRequest, $psrResponse); | |
} |
此办法是 swoole 的 onRequest 回调函数, 所以参数传进来的 Request 和 Response 别离对应的类型是 Swoole\Http\Request
和Swoole\Http\Response
.
能够看到, 在收到参数后, 框架干的第一件事就是调用 Swoft\Http\Message\Request
和Swoft\Http\Message\Response
的 new 办法, 生成与之对应的合乎 psr 标准的对象.
接着, 框架将新生成的 request 和 response 对象作为参数传递给调度函数, 由调度函数去执行具体的业务逻辑并返回后果给客户端.
实现细节之 (Swoft\Http\Message\Request::new
):
此办法以及外面用到的 Uri::new 办法都是获取 PROTOTYPE 模式的 bean
public static function new(CoRequest $coRequest): self | |
{ | |
// 此处获取的 bean 是一个新的对象, 因为以后类的 bean 注解 | |
// 为 PROTOTYPE 模式 | |
//@Bean(name="httpRequest", scope=Bean::PROTOTYPE) | |
/** @var Request $self */ | |
$self = BeanFactory::getBean('httpRequest'); | |
// Server params | |
// 获取 Swoole 原生 Request 对象的 server 参数 | |
$serverParams = $coRequest->server; | |
// 将 Swoole 原生 Request 对象中的 header 设置到新获取的 bean 对象上 | |
// Set headers | |
$self->initializeHeaders($headers = $coRequest->header ?: []); | |
// 设置申请形式 | |
$self->method = $serverParams['request_method'] ?? ''; | |
// 绑定原生 Request 对象到新的 bean 对象上 | |
$self->coRequest = $coRequest; | |
// 设置 GET 申请参数 | |
$self->queryParams = $coRequest->get ?: []; | |
// 设置 COOKIE | |
$self->cookieParams = $coRequest->cookie ?: []; | |
// 设置 SERVER 参数 | |
$self->serverParams = $serverParams; | |
// 将申请的 URI 设置为 requestTarget | |
$self->requestTarget = $serverParams['request_uri'] ?? ''; | |
// 设置 URI | |
// Save | |
$self->uriPath = $serverParams['request_uri'] ?? ''; | |
// 设置 QUERY_STRING | |
$self->uriQuery = $serverParams['query_string'] ?? ''; | |
// 如果 URI 中还蕴含? 号, 阐明还须要解决 | |
if (strpos($self->uriPath, '?') !== false) { | |
// Split | |
$parts = explode('?', $self->uriPath, 2); | |
$self->uriPath = $parts[0]; | |
$self->uriQuery = $parts[1] ?? $self->uriQuery; | |
} | |
// 调用 Uri 类结构 Uri 对象并绑定给新的 bean 对象 | |
/** @var Uri $uri */ | |
$self->uri = Uri::new('', ['host'=> $headers['host'] ??'', | |
'path' => $self->uriPath, | |
'query' => $self->uriQuery, | |
'https' => $serverParams['https'] ?? '','http_host'=> $serverParams['http_host'] ??'', | |
'server_name' => $serverParams['server_name'] ?? '','server_addr'=> $serverParams['server_addr'] ??'', | |
'server_port' => $serverParams['server_port'] ?? '', | |
]); | |
// 如果以后 headers 外面没有 host 数据, 则通过 Uri 对象去更新 | |
// | |
// Update host by Uri info | |
if (!isset($headers['host'])) {$self->updateHostByUri(); | |
} | |
return $self; | |
} |
Uri::new 的实现:
public static function new(string $uri = '', array $params = []): self | |
{ | |
/** @var Uri $instance */ | |
$instance = Swoft::getBean(self::class); | |
// Save some params | |
$instance->params = $params; | |
// Weak type check to also accept null until we can add scalar type hints | |
if ($uri === '') {return $instance;} | |
// If params is empty, padding defaults data | |
if (!$params) {$instance->params = self::DEFAULT_PARAMS;} | |
$parts = parse_url($uri); | |
if ($parts === false) {throw new InvalidArgumentException("Unable to parse URI: $uri"); | |
} | |
$instance->applyParts($parts); | |
return $instance; | |
} |
实现细节之 (Swoft\Http\Message\Response::new
):
此办法依然是获取 PROTOTYPE 模式的 bean, 申请初期只是很单纯的设置了是否发送的状态以及绑定原生 Response 对象, 并未做过多设置.
public static function new(CoResponse $coResponse): self | |
{ | |
/** @var Response $self */ | |
$self = BeanFactory::getBean('httpResponse'); | |
// $self = bean('httpResponse'); | |
$self->sent = false; | |
$self->coResponse = $coResponse; | |
return $self; | |
} |
正文完