首页
下载
文档
问答社区
视频
捐赠
源代码
AI 助理
赞助商
CRMEB
Apipost
腾讯云
微擎
禅道
51Talk
商业产品
Swoole AI 智能文档翻译器
Swoole-Compiler PHP 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
Swoole v4.6 版本新特性之 Http\Request 增强
在 4.6 版本中,对 `Swoole\Http\Request` 进行了一些增强: - 新增 create/parse/isCompleted 方法 (#3938) (@matyhtf) - 新增 getMethod 方法 (#3987) (@luolaifa000) 那么这些增强功能有什么用呢?这里举一个例子: 使用 `TCP Server`,提供 `HTTP Server` 的访问 在没有这些方法之前,需要手动将 `onReceive` 事件中收到的 `$data` 数据解析为 HTTP 协议 ```php $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 ```php 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` 结果一致 ```bash 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` ```php $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 请求的请求方式。 ```php var_dump($request->server['request_method']); var_dump($request->getMethod()); ``` ## isCompleted 我们有这样一段 HTTP 请求报文: ```txt 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`方法,如: ```php 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 协议了 ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/swoole/wechat.png)
发布于3年前 · 53 次浏览 · 来自
分享
鲁飞
在 4.6 版本中,对 `Swoole\Http\Request` 进行了一些增强: - 新增 create/parse/isCompleted 方法 (#3938) (@matyhtf) - 新增 getMethod 方法 (#3987) (@luolaifa000) 那么这些增强功能有什么用呢?这里举一个例子: 使用 `TCP Server`,提供 `HTTP Server` 的访问 在没有这些方法之前,需要手动将 `onReceive` 事件中收到的 `$data` 数据解析为 HTTP 协议 ```php $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 ```php 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` 结果一致 ```bash 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` ```php $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 请求的请求方式。 ```php var_dump($request->server['request_method']); var_dump($request->getMethod()); ``` ## isCompleted 我们有这样一段 HTTP 请求报文: ```txt 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`方法,如: ```php 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 协议了 ![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/swoole/wechat.png)
赞
0
分享
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
评论
2022-02-12
JKD
请求的参数类型全变成string,请问怎么处理保留原始http请求的类型 $request->get
赞
0
回复
微信公众号
热门内容
作者其它话题
- thinkphp5.1在使用think-swoole的时候报错unsupported option [host]
- WSL 下服务器响应数据过大无法接收
暂无回复的问答
- CodeGalaxy K3s 轻量集群节点之间如何实现负载均衡
- 关于openssl CURL WARNING swSSL_connect: SSL_connect(fd=69) failed. Error: error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small[1|394]
- 多个模型如何进行事务异常回退?
- websocket开启wss报错
- 协程tcp服务器如何使用多进程?recv()方法接收信息,打印出来的pid一直是同一个。没用使用到多进程啊。