在4.6版本中,对Swoole\Http\Request做了一些增强:添加create/parse/isCompleted方法(#3938)(@matyhtf)添加getMethod方法(#3987)(@luolaifa000)那么这些增强功能有什么用呢?下面是一个例子:使用TCPServer提供对HTTPServer的访问。在这些方法之前,需要手动将onReceive事件中收到的$data数据解析成HTTP协议$server->on('Receive',function($server,$fd,$reactor_id,$data){$server->send($fd,"服务器:{$data}");});现在不需要手动解析HTTP协议,直接使用Swoole提供的Method进行解析即可,返回的数据格式与Http\Server中的Http\Request完全一致。试试看:本文使用Swoolev4.6.2版本进行演示。创建/解析Swoole\Server;useSwoole\Http\Request;$server=newServer('127.0.0.1',9501);$server->on('Receive',function(Server$server,$fd,$reactor_id,$data){/**@varRequest$request*/$request=Request::create();$request->parse($data);var_dump($request);$body='Hello,Swoole';$body_len=strlen($body);$send_data="HTTP/1.1200OK\r\nServer:swoole-server\r\nContent-Type:text/html;charset=utf-8\r\nContent-Length:{$body_len}\r\n连接:保持活动状态\r\n\r\n{$body}";$server->send($fd,$send_data);});$服务器->开始();在Swoole\ServerTCP服务器的onReceive事件中,调用Request::create()方法创建一个Http\Request对象,然后将$data数据传递给Request->parse方法进行解析,打印$request和使用浏览器或curl发起Request,如http://127.0.0.1:9501/?foo=bar输出结果与Swoole\Http\ServerHTTP服务器对象$request结果一致(Swoole\Http\Request)#6(9){["fd"]=>int(0)["streamId"]=>int(0)["header"]=>array(14){["host"]=>string(14)“127.0.0.1:9501"["connection"]=>string(10)"keep-alive"["sec-ch-ua"]=>string(64)""Chromium";v="88","GoogleChrome";v="88",";NotABrand";v="99""["sec-ch-ua-mobile"]=>string(2)"?0"["dnt"]=>string(1)"1"["upgrade-insecure-requests"]=>string(1)"1"["user-agent"]=>string(120)"Mozilla/5.0(Macintosh;IntelMacOSX10_15_6)AppleWebKit/537.36(KHTML,likeGecko)Chrome/88.0.4324.96Safari/537.36"["accept"]=>string(135)"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"["sec-fetch-site"]=>string(4)"none"["sec-fetch-mode"]=>string(8)"navigate"["sec-fetch-user"]=>string(2)"?1"["sec-fetch-dest"]=>string(8)"document"["accept-encoding"]=>string(17)"gzip,deflate,br"["accept-language"]=>string(14)"zh-CN,zh;q=0.9"}[“服务器”]=>array(7){["query_string"]=>string(7)"foo=bar"["request_method"]=>string(3)"GET"["request_uri"]=>string(1)"/"["path_info"]=>string(1)"/"["request_time"]=>int(1612413945)["request_time_float"]=>float(1612413945.3474)["server_protocol"]=>string(8)"HTTP/1.1"}["cookie"]=>NULL["get"]=>array(1){["foo"]=>string(3)"bar"}["files"]=>NULL["post"]=>NULL["tmpfiles"]=>NULL}调用send方法发送响应,浏览器也输出Hello,Swoole$body='Hello,Swoole';$body_len=strlen($body);$send_data="HTTP/1.1200OK\r\nServer:swoole-server\r\nContent-Type:text/html;charset=utf-8\r\nContent-Length:{$body_len}\r\nConnection:keep-活着\r\n\r\n{$body}";$server->send($fd,$send_data);这里需要了解HTTP协议,包括新的getMethod方法和$request->server['request_method']方法的结果是一样的,都是用来获取当前HTTP请求的请求方法var_dump($request->server['request_method']);var_dump($request->getMethod());isCompleted我们有这样一个HTTP请求消息:GET/HTTP/1.1\r\nHost:127.0.0.1:9501\r\nConnection:keep-alive\r\nCache-Control:max-age=0\r\nDNT:1\r\nUpgrade-Insecure-Requests:1\r\nUser-Agent:Mozilla/5.0(Macintosh;IntelMacOSX10_15_6)AppleWebKit/537.36(KHTML,likeGecko)Chrome/88.0.4324.96Safari/537.36\r\nAccept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nSec-Fetch-Site:none\r\nSec-Fetch-Mode:navigate\r\nSec-Fetch-User:?1\r\nSec-Fetch-Dest:document\r\nAccept-Encoding:gzip,deflate,br\r\nAccept-Language:zh-CN,zh;q=0.9,en;q=0.8\r\nCookie:PHPSESSID=679eca30f8e96dcb3ad4ff82ceb62079\r\n\r\nHTTP协议用两个\r\n表示消息头已经结束。代码中如何判断是否已经结束?这里可以使用isCompleted方法,如:useSwoole\Http\Request;$data="GET/?foo=barHTTP/1.1\r\n";$data.="Host:127.0.0.1:9501\r\n";$data.="连接:keep-alive\r\n";$data.="Cache-Control:max-age=0\r\n";$data.="DNT:1\r\n";$data.="升级-Insecure-Requests:1\r\n";$data.="User-Agent:Mozilla/5.0(Macintosh;IntelMacOSX10_15_6)AppleWebKit/537.36(KHTML,likeGecko)Chrome/88.0.4324.96Safari/537.36\r\n";$data.="接受:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n";$data.="Sec-Fetch-Site:none\r\n";$data.="Sec-Fetch-Mode:navigate\r\n";$data.="Sec-Fetch-User:?1\r\n";$data.="Sec-Fetch-Dest:document\r\n";$data.="Accept-Encoding:gzip,deflate,br\r\n";$data.="Accept-Language:zh-CN,zh;q=0.9,en;q=0.8\r\n";$data.="Cookie:PHPSESSID=679eca30f8e96dcb3ad4ff82ceb62079\r\n";$request=Request::create();var_dump($request->isCompleted());//falsevar_dump($request->parse($data));//637var_dump($request);//Swoole\Http\Requestvar_dump($request->parse("\r\n"));//2var_dump($request->isCompleted());//trueparse方法会尽可能多的解析消息,所以在打印$request的时候,看似消息已经解析完毕,但实际上消息是不完整的,没有到达终点。再次调用parse方法添加一个\r\n即可成功到达结尾。下篇文章会讲解Http\Response的增强,就不用像文章开头的$send_data那样手动拼接HTTP协议了。
