当前位置: 首页 > 后端技术 > PHP

Swoft的HttpServer启动和请求工作流程(三)--Request和Response封装过程

时间:2023-03-29 22:26:51 PHP

上次提到我们在服务器上添加了10个swoole监听事件。添加swoole事件后,框架调用Swoft的trigger()方法触发用户注册的多个生命周期事件。然后框架调用服务端的start()方法正式开始接受用户请求。本章将从onRequest事件开始,逐步分析将Swoole原有的Request和Response封装成Swoft中使用的Swoft\Http\Message\Request和Swoft\Http\Message\Response的过程。先看onRequest的代码:publicfunctiononRequest(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\回复。可以看到,框架在接收到参数后,首先要做的就是调用Swoft\Http\Message\Request和Swoft\Http\Message\Response的new方法生成对应的符合psr规范的对象。然后,框架将新生成的请求和响应对象作为参数传递给调度函数,调度函数执行具体的业务逻辑并将结果返回给客户端。实现细节(Swoft\Http\Message\Request::new):ThismethodandtheUriusedinit:new方法是获取PROTOTYPE模式的beanpublicstaticfunctionnew(CoRequest$coRequest):self{//这里获取到的bean是一个新的对象,因为当前类的bean注解//是PROTOTYPE方式//@Bean(name="httpRequest",scope=Bean::PROTOTYPE)/**@varRequest$self*/$self=BeanFactory::getBean('httpRequest');//Serverparams//获取Swoole原生Request对象的server参数$serverParams=$coRequest->server;//将Swoole原生Request对象中的header设置为新获取的bean对象//Setheaders$self->initializeHeaders($headers=$coRequest->header?:[]);//Set请求方法$self->method=$serverParams['request_method']??'';//将原来的Request对象绑定到新的bean对象上$self->coRequest=$coRequest;//设置GET请求参数$self->queryParams=$coRequest->get?:[];//设置COOKIE$self->cookieParams=$coRequest->cookie?:[];//设置服务器参数$self->serverParams=$serverParams;//设置请求的URI为requestTarget$self->requestTarget=$serverParams['request_uri']??'';//设置URI//保存$self->uriPath=$serverParams['request_uri']??'';//设置查询字符串$self->uriQuery=$serverParams['query_string']??'';//如果URI还包含一个?sign,表示需要处理if(strpos($self->uriPath,'?')!==false){//Split$parts=explode('?',$self->uriPath,2);$self->uriPath=$parts[0];$self->uriQuery=$parts[1]??$self->uri查询;}//调用Uri类构造一个Uri对象并绑定到一个新的bean对象上/**@varUri$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']??'',]);//如果当前头中没有主机数据,则通过Uri对象更新它//通过Uri信息更新主机if(!isset($headers['host'])){$self->updateHostByUri();}return$self;}Uri::new的实现:publicstaticfunctionnew(string$uri='',array$params=[]):self{/**@varUri$instance*/$instance=Swoft::getBean(自我::类);//保存一些参数$instance->params=$params;//弱类型检查也接受null,直到我们可以添加标量类型提示if($uri===''){return$instance;}//如果参数为空,填充默认数据if(!$params){$instance->params=self::DEFAULT_PARAMS;}$parts=parse_url($uri);if($parts===false){thrownewInvalidArgumentException("无法解析URI:$uri");}$instance->applyParts($parts);返回$实例;}实现细节(Swoft\Http\Message\Response::new):该方法依然是获取PROTOTYPE方式的bean。在请求的初始阶段,只是简单的设置是否发送的状态,绑定原生的Response对象。还没有做Multiplesettings.publicstaticfunctionnew(CoResponse$coResponse):self{/**@varResponse$self*/$self=BeanFactory::getBean('httpResponse');//$self=bean('httpResponse');$self->sent=false;$self->coResponse=$coResponse;返回$自我;}