在 4.6 版本中,对 Swoole\Http\Request 进行了一些加强:

  • 新增 create/parse/isCompleted 办法 (#3938) (@matyhtf)
  • 新增 getMethod 办法 (#3987) (@luolaifa000)

那么这些加强性能有什么用呢?这里举一个例子:

应用 TCP Server,提供 HTTP Server 的拜访

在没有这些办法之前,须要手动将 onReceive 事件中收到的 $data 数据解析为 HTTP 协定

$server->on('Receive', function ($server, $fd, $reactor_id, $data) {    $server->send($fd, "Server: {$data}");});

当初就不须要手动进行解析 HTTP 协定了,能够间接应用 Swoole 提供的办法进行解析,返回的数据格式和 Http\Server 中的 Http\Request 完全一致

上面来试一下:

本文应用 Swoole v4.6.2 版本进行演示。

create/parse

use Swoole\Server;use Swoole\Http\Request;$server = new Server('127.0.0.1', 9501);$server->on('Receive', function (Server $server, $fd, $reactor_id, $data) {    /** @var Request $request */    $request = Request::create();    $request->parse($data);    var_dump($request);    $body = 'Hello, Swoole';    $body_len = strlen($body);    $send_data = "HTTP/1.1 200 OK\r\nServer: swoole-server\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: {$body_len}\r\nConnection: keep-alive\r\n\r\n{$body}";    $server->send($fd, $send_data);});$server->start();

Swoole\Server TCP 服务器的 onReceive 事件中,调用Request::create()办法来创立一个 Http\Request 对象,接着将$data数据传递给Request->parse办法进行解析,打印$request

应用浏览器或者 curl 发动申请,如http://127.0.0.1:9501/?foo=bar

输入后果和 Swoole\Http\Server HTTP 服务器的 $request 后果统一

object(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", "Google Chrome";v="88", ";Not A Brand";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; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/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"  }  ["server"]=>  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办法发送response,并且浏览器还失常输入了Hello, Swoole

$body = 'Hello, Swoole';$body_len = strlen($body);$send_data = "HTTP/1.1 200 OK\r\nServer: swoole-server\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: {$body_len}\r\nConnection: keep-alive\r\n\r\n{$body}";$server->send($fd, $send_data);

这里就须要理解 HTTP 协定,包含响应头信息、状态码等

getMethod

新增的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; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/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\n

HTTP 协定应用两个\r\n示意消息报头曾经完结,代码中怎么去判断是否达到了结尾?

这里就能够应用isCompleted办法,如:

use Swoole\Http\Request;$data = "GET /?foo=bar HTTP/1.1\r\n";$data .= "Host: 127.0.0.1:9501\r\n";$data .= "Connection: keep-alive\r\n";$data .= "Cache-Control: max-age=0\r\n";$data .= "DNT: 1\r\n";$data .= "Upgrade-Insecure-Requests: 1\r\n";$data .= "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36\r\n";$data .= "Accept: 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()); // true

parse 办法会尽可能多的去解析报文,所以在打印$request的时候,看起来报文曾经解析实现了,但实际上这个报文不残缺,并没有达到结尾

再次调用parse办法补充一个\r\n才算胜利达到了结尾

下篇文章将会解说 Http\Response 的加强,就不须要像文章结尾的$send_data一样手动去拼接 HTTP 协定了