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