【php】Swoole v4.6 版本新特性之 Http\Request 增强

Swoole v4.6 版本新特性之 Http\Request 增强

沈唁

发布于 36 分钟前

在 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 完全一致

下面来试一下:

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 协议了

【php】Swoole v4.6 版本新特性之 Http\Request 增强

phpswoole

阅读 60发布于 36 分钟前

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议


Swoole

PHP的协程框架

avatar

沈唁

Swoole & Hyperf & Docsify 开发组成员

欢迎关注我的个人公众号:沈唁志

1.2k 声望

71 粉丝

0 条评论

得票时间

avatar

沈唁

Swoole & Hyperf & Docsify 开发组成员

欢迎关注我的个人公众号:沈唁志

1.2k 声望

71 粉丝

宣传栏

在 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 完全一致

下面来试一下:

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 协议了

【php】Swoole v4.6 版本新特性之 Http\Request 增强

以上是 【php】Swoole v4.6 版本新特性之 Http\Request 增强 的全部内容, 来源链接: utcz.com/a/112859.html

回到顶部