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

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 在 4.6 版本中,对 Swoole\Http\Request 进行了一些增强

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

目录
相关文章
verbose stack FetchError: request to https://registry.npm.taobao.org/md-editor-v3 failed, reason: ce
这篇文章描述了在安装npm包`md-editor-v3`时遇到的淘宝镜像证书过期问题,并提供了解决方案,即通过切换npm镜像源到`https://registry.npmmirror.com/`来解决安装失败的问题。
verbose stack FetchError: request to https://registry.npm.taobao.org/md-editor-v3 failed, reason: ce
|
2月前
|
安全 应用服务中间件 网络安全
修复HTTPS升级后出现 Mixed Content: The page at 'https://xxx' was loaded over HTTPS, but requested an insecure frame 'http://xxx'. This request has been blocked; the content must be served over HTTPS. 的问题
修复HTTPS升级后出现 Mixed Content: The page at 'https://xxx' was loaded over HTTPS, but requested an insecure frame 'http://xxx'. This request has been blocked; the content must be served over HTTPS. 的问题
|
3月前
|
测试技术 API
8-20|https://gitlab.xx.com/api/v4/projects/4/trigger/pipeline Request failed 状态码400
8-20|https://gitlab.xx.com/api/v4/projects/4/trigger/pipeline Request failed 状态码400
|
4月前
|
Web App开发 缓存 网络协议
HTTP3版本和实现验证
这篇文章详细介绍了HTTP3协议及其与HTTP2的比较,解释了HTTP3基于QUIC协议的工作原理,包括0-RTT恢复、H3-29草案等技术细节,并提供了验证网站HTTP3支持和浏览器支持的工具和方法。
66 1
|
4月前
|
JavaScript
request to https://registry.npm.taobao.org/cnpm failed, reason: certificate has expired
request to https://registry.npm.taobao.org/cnpm failed, reason: certificate has expired
111 2
|
4月前
|
Python
【Azure 应用服务】Azure Function HTTP Trigger 遇见奇妙的500 Internal Server Error: Failed to forward request to http://169.254.130.x
【Azure 应用服务】Azure Function HTTP Trigger 遇见奇妙的500 Internal Server Error: Failed to forward request to http://169.254.130.x
|
4月前
|
JavaScript 前端开发 Java
【Azure 环境】各种语言版本或命令,发送HTTP/HTTPS的请求合集
【Azure 环境】各种语言版本或命令,发送HTTP/HTTPS的请求合集
|
4月前
|
Oracle Java 关系型数据库
JDK版本特性问题之在 JDK 11 中,HTTP Client API 的特点有哪些
JDK版本特性问题之在 JDK 11 中,HTTP Client API 的特点有哪些
|
5月前
|
网络协议 程序员 应用服务中间件
Swoole与Go系列教程之HTTP服务的应用
PHP 曾是Web开发领域佼佼者,随着业务壮大,异步和高并发方面不足显现。Swoole 曾经尝试填补空白,但局限性也比较的明显。Go 语言的崛起,简洁语法和并发优势吸引大厂使用,吸引了大多数程序员的转型。
1005 0
Swoole与Go系列教程之HTTP服务的应用
Bad Request, Resolved [org.springframework.http.converter.HttpMessageNotReadableException,跟着视频仔细比对
Bad Request, Resolved [org.springframework.http.converter.HttpMessageNotReadableException,跟着视频仔细比对