Swoole v4.6 版本新特性之 HttpRequest 增强
Posted 沈唁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swoole v4.6 版本新特性之 HttpRequest 增强相关的知识,希望对你有一定的参考价值。
在 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\\n
Host: 127.0.0.1:9501\\r\\n
Connection: keep-alive\\r\\n
Cache-Control: max-age=0\\r\\n
DNT: 1\\r\\n
Upgrade-Insecure-Requests: 1\\r\\n
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
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
Sec-Fetch-Site: none\\r\\n
Sec-Fetch-Mode: navigate\\r\\n
Sec-Fetch-User: ?1\\r\\n
Sec-Fetch-Dest: document\\r\\n
Accept-Encoding: gzip, deflate, br\\r\\n
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\\r\\n
Cookie: 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()); // false
var_dump($request->parse($data)); // 637
var_dump($request); // Swoole\\Http\\Request
var_dump($request->parse("\\r\\n")); // 2
var_dump($request->isCompleted()); // true
parse
方法会尽可能多的去解析报文,所以在打印$request
的时候,看起来报文已经解析完成了,但实际上这个报文不完整,并没有到达结尾
再次调用parse
方法补充一个\\r\\n
才算成功到达了结尾
下篇文章将会讲解 Http\\Response
的增强,就不需要像文章开头的$send_data
一样手动去拼接 HTTP 协议了
以上是关于Swoole v4.6 版本新特性之 HttpRequest 增强的主要内容,如果未能解决你的问题,请参考以下文章