上一回讲到给 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;
}