协程HTTP/Websocket客户端
协程版Http
客户端的底层用纯C
编写,不依赖任何第三方扩展库,拥有超高的性能。
- 支持
Http-Chunk
、Keep-Alive
特性,支持form-data
格式 Http
协议版本为HTTP/1.1
- 支持升级为
WebSocket
客户端 gzip
压缩格式支持需要依赖zlib
库- 客户端仅实现核心的功能,实际项目建议使用 Saber
属性
errCode
错误状态码。当connect/send/recv/close
失败或者超时时,会自动设置Swoole\Coroutine\Http\Client->errCode
的值
Swoole\Coroutine\Http\Client->errCode: int;
errCode
的值等于Linux errno
。可使用socket_strerror
将错误码转为错误信息。
// 如果connect refuse,错误码为111
// 如果超时,错误码为110
echo socket_strerror($client->errCode);
!> 参考:Linux 错误码列表
body
存储上次请求的返回包体。
Swoole\Coroutine\Http\Client->body: string;
- 示例
Co\run(function (){
$cli = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
$cli->get('/index.php');
echo $cli->body;
$cli->close();
});
statusCode
Http状态码,如200、404等。状态码如果为负数,表示连接存在问题。查看更多
Swoole\Coroutine\Http\Client->statusCode: int;
方法
__construct()
构造方法。
Swoole\Coroutine\Http\Client->__construct(string $host, int $port, bool $ssl = false);
参数
string $host
- 功能:目标服务器主机地址【可以为IP或域名,底层自动进行域名解析】
- 默认值:无
- 其它值:无
int $port
- 功能:目标服务器主机端口
- 默认值:无
- 其它值:无
bool $ssl
- 功能:是否启用
SSL/TLS
隧道加密,如果目标服务器是https必须设置$ssl
参数为true
- 默认值:无
- 其它值:无
- 功能:是否启用
示例
Co\run(function () {
$client = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
$client->setHeaders([
'Host' => 'localhost',
'User-Agent' => 'Chrome/49.0.2587.3',
'Accept' => 'text/html,application/xhtml+xml,application/xml',
'Accept-Encoding' => 'gzip',
]);
$client->set(['timeout' => 1]);
$client->get('/index.php');
echo $client->body;
$client->close();
});
set()
设置客户端参数。
Swoole\Coroutine\Http\Client->set(array $options);
此方法与Swoole\Client->set
接收的参数完全一致,可参考 Swoole\Client->set 方法的文档。
Swoole\Coroutine\Http\Client
额外增加了一些选项,来控制Http
和WebSocket
客户端。
额外选项
超时控制
设置timeout
选项,启用Http请求超时检测。单位为秒,最小粒度支持毫秒。
$http->set(['timeout' => 3.0]);
- 连接超时或被服务器关闭连接,
statusCode
将设置为-1
- 在约定的时间内服务器未返回响应,请求超时,
statusCode
将设置为-2
- 请求超时后底层会自动切断连接
- 设置为
-1
表示永不超时,底层将不会添加超时检测的定时器 - 参考客户端超时规则
keep_alive
设置keep_alive
选项,启用或关闭Http长连接。
$http->set(['keep_alive' => false]);
websocket_mask
由于RFC规定, v4.4.0后此配置默认开启, 但会导致性能损耗, 如服务器端无强制要求可以设置false关闭
WebSocket
客户端启用或关闭掩码。默认为关闭。启用后会对WebSocket客户端发送的数据使用掩码进行数据转换。
$http->set(['websocket_mask' => true]);
websocket_compression
需要v4.4.12或更高版本
为true
时允许对帧进行zlib压缩,具体是否能够压缩取决于服务端是否能够处理压缩(根据握手信息决定,参见RFC-7692
) 需要配合flags参数SWOOLE_WEBSOCKET_FLAG_COMPRESS
来真正地对具体的某个帧进行压缩,具体使用方法见此节
setMethod()
设置请求方法。仅在当前请求有效,发送请求后会立刻清除method设置。
Swoole\Coroutine\Http\Client->setMethod(string $method): void;
参数
string $method
- 功能:设置方法
- 默认值:无
- 其它值:无
!> 必须为符合
Http
标准的方法名称,如果$method
设置错误可能会被Http
服务器拒绝请求
示例
$http->setMethod("PUT");
setHeaders()
设置Http请求头。
Swoole\Coroutine\Http\Client->setHeaders(array $headers): void;
参数
array $headers
- 功能:设置请求头 【必须为键值对应的数组,底层会自动映射为
$key
:$value
格式的Http
标准头格式】 - 默认值:无
- 其它值:无
- 功能:设置请求头 【必须为键值对应的数组,底层会自动映射为
!> setHeaders
设置的Http
头在Coroutine\Http\Client
对象存活期间的每次请求永久有效;重新调用setHeaders
会覆盖上一次的设置
setCookies()
设置Cookie
, 值将会被进行urlencode
编码, 若想保持原始信息, 请自行用setHeaders
设置名为Cookie
的header
。
Swoole\Coroutine\Http\Client->setCookies(array $cookies): void;
参数
array $cookies
- 功能:设置
COOKIE
【必须为键值对应数组】 - 默认值:无
- 其它值:无
- 功能:设置
!> -设置COOKIE
后在客户端对象存活期间会持续保存
-服务器端主动设置的COOKIE
会合并到cookies
数组中,可读取$client->cookies
属性获得当前Http
客户端的COOKIE
信息
-重复调用setCookies
方法,会覆盖当前的Cookies
状态,这会丢弃之前服务器端下发的COOKIE
以及之前主动设置的COOKIE
setData()
设置Http请求的包体。
Swoole\Coroutine\Http\Client->setData(string|array $data): void;
参数
string|array $data
- 功能:设置请求的包体
- 默认值:无
- 其它值:无
提示
- 设置
$data
后并且未设置$method
,底层会自动设置为POST - 如果
$data
为数组时且Content-Type
为urlencoded
格式, 底层将会自动进行http_build_query
- 如果使用了
addFile
或addData
导致启用了form-data
格式,$data
值为字符串时将会被忽略(因为格式不同), 但为数组时底层将会以form-data
格式追加数组中的字段
- 设置
addFile()
添加POST文件。
!> 使用addFile
会自动将POST
的Content-Type
将变更为form-data
。addFile
底层基于sendfile
,可支持异步发送超大文件。
Swoole\Coroutine\Http\Client->addFile(string $path, string $name,string $mimeType = null, string $filename = null, int $offset = 0, int $length = 0): void;
参数
string $path
- 功能:文件的路径【必选参数,不能为空文件或者不存在的文件】
- 默认值:无
- 其它值:无
string $name
- 功能:表单的名称【必选参数,
FILES
参数中的key
】 - 默认值:无
- 其它值:无
- 功能:表单的名称【必选参数,
string $mimeType
- 功能:文件的
MIME
格式,【可选参数,底层会根据文件的扩展名自动推断】 - 默认值:无
- 其它值:无
- 功能:文件的
string $filename
- 功能:文件名称【可选参数】
- 默认值:
basename($path)
- 其它值:无
string $offset
- 功能:上传文件的偏移量【可选参数,可以指定从文件的中间部分开始传输数据。此特性可用于支持断点续传。】
- 默认值:无
- 其它值:无
string $length
- 功能:发送数据的尺寸【可选参数】
- 默认值:默认为整个文件的尺寸
- 其它值:无
示例
Co\run(function () {
$cli = new Swoole\Coroutine\Http\Client('httpbin.org', 80);
$cli->setHeaders([
'Host' => 'httpbin.org'
]);
$cli->set(['timeout' => -1]);
$cli->addFile(__FILE__, 'file1', 'text/plain');
$cli->post('/post', ['foo' => 'bar']);
echo $cli->body;
$cli->close();
});
addData()
使用字符串构建上传文件内容。
!> addData
在 v4.1.0
以上版本可用
Swoole\Coroutine\Http\Client->addData(string $data, string $name, string $mimeType = null, string $filename = null): void
参数
string $path
- 功能:数据内容【必选参数,最大长度不得超过buffer_output_size】
- 默认值:无
- 其它值:无
string $name
- 功能:表单的名称【必选参数,
$_FILES
参数中的key
】 - 默认值:无
- 其它值:无
- 功能:表单的名称【必选参数,
string $mimeType
- 功能:文件的
MIME
格式【可选参数,默认为application/octet-stream
】 - 默认值:无
- 其它值:无
- 功能:文件的
string $filename
- 功能:文件名称【可选参数,默认为
$name
】 - 默认值:无
- 其它值:无
- 功能:文件名称【可选参数,默认为
示例
Co\run(function () {
$client = new Swoole\Coroutine\Http\Client('httpbin.org', 80);
$client->setHeaders([
'Host' => 'httpbin.org'
]);
$client->set(['timeout' => -1]);
$client->addData(Co::readFile(__FILE__), 'file1', 'text/plain');
$client->post('/post', ['foo' => 'bar']);
echo $client->body;
$client->close();
});
get()
发起 GET 请求。
Swoole\Coroutine\Http\Client->get(string $path): void
参数
string $path
- 功能:设置
URL
路径【如/index.html
,注意这里不能传入http://domain
】 - 默认值:无
- 其它值:无
- 功能:设置
示例
Co\run(function () {
$client = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
$client->setHeaders([
'Host' => 'localhost',
'User-Agent' => 'Chrome/49.0.2587.3',
'Accept' => 'text/html,application/xhtml+xml,application/xml',
'Accept-Encoding' => 'gzip',
]);
$client->get('/index.php');
echo $client->body;
$client->close();
});
!> 使用get
会忽略setMethod
设置的请求方法,强制使用GET
post()
发起 POST 请求。
Swoole\Coroutine\Http\Client->post(string $path, mixed $data): void
参数
string $path
- 功能:设置
URL
路径【如/index.html
,注意这里不能传入http://domain
】 - 默认值:无
- 其它值:无
- 功能:设置
mixed $data
- 功能:请求的包体数据
- 默认值:无
- 其它值:无
!> 如果
$data
为数组底层自动会打包为x-www-form-urlencoded
格式的POST
内容,并设置Content-Type
为application/x-www-form-urlencoded
注意
!> 使用
post
会忽略setMethod
设置的请求方法,强制使用POST
示例
Co\run(function () {
$client = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
$client->post('/post.php', array('a' => '123', 'b' => '456'));
echo $client->body;
$client->close();
});
upgrade()
升级为WebSocket
连接。
Swoole\Coroutine\Http\Client->upgrade(string $path): bool
参数
string $path
- 功能:设置
URL
路径【如/
,注意这里不能传入http://domain
】 - 默认值:无
- 其它值:无
- 功能:设置
提示
- 某些情况下请求虽然是成功的,
upgrade
返回了true
,但服务器并未设置HTTP
状态码为101
,而是200
或403
,这说明服务器拒绝了握手请求 WebSocket
握手成功后可以使用push
方法向服务器端推送消息,也可以调用recv
接收消息upgrade
会产生一次协程调度
- 某些情况下请求虽然是成功的,
示例
Co\run(function () {
$client = new Swoole\Coroutine\Http\Client("127.0.0.1", 9501);
$ret = $client->upgrade("/");
if ($ret) {
while(true) {
$client->push("hello");
var_dump($client->recv());
co::sleep(0.1);
}
}
});
push()
向WebSocket
服务器推送消息。
!> push
方法必须在upgrade
成功之后才能执行push
方法不会产生协程调度,写入发送缓存区后会立即返回
Swoole\Coroutine\Http\Client->push(mixed $data, int $opcode = WEBSOCKET_OPCODE_TEXT, bool $finish = true): bool
参数
mixed $data
- 功能:要发送的数据内容【默认为
UTF-8
文本格式,如果为其他格式编码或二进制数据,请使用WEBSOCKET_OPCODE_BINARY
】 - 默认值:无
- 其它值:无
!> Swoole >= v4.2.0
$data
可以使用 Swoole\WebSocket\Frame对象, 支持发送各种帧类型- 功能:要发送的数据内容【默认为
int $opcode
- 功能:操作类型
- 默认值:
WEBSOCKET_OPCODE_TEXT
- 其它值:无
!>
$opcode
必须为合法的WebSocket OPCODE
,否则会返回失败,并打印错误信息opcode max 10
int $finish
- 功能:操作类型
- 默认值:
SWOOLE_WEBSOCKET_FLAG_FIN
- 其它值:无
!> 自
v4.4.12
版本起,finish
参数(bool
型)改为flags
(int
型)以支持Websocket
压缩,finish
对应SWOOLE_WEBSOCKET_FLAG_FIN
值为1
,原有bool
型值会隐式转换为int
型,此改动向下兼容无影响。 此外压缩flag
为SWOOLE_WEBSOCKET_FLAG_COMPRESS
。
返回值
- 发送成功,返回
true
- 连接不存在、已关闭、未完成
WebSocket
,发送失败返回false
- 发送成功,返回
错误码
错误码 | 说明 |
---|---|
8502 | 错误的OPCODE |
8503 | 未连接到服务器或连接已被关闭 |
8504 | 握手失败 |
recv()
接收消息。只为websocket
使用,需要配合upgrade()使用,见示例
Swoole\Coroutine\Http\Client->recv(float $timeout = -1): void
参数
float $timeout
- 功能:调用
upgrade()
升级为websocket
连接时此参数才有效 - 值单位: 秒【支持浮点型,如
1.5
表示1s
+500ms
】 - 默认值:
-1
- 其它值:无
!> 设置超时,优先使用指定的参数,其次使用
set
方法中传入的timeout
配置,参考客户端超时规则- 功能:调用
示例
Co\run(function () {
$client = new Swoole\Coroutine\Http\Client("127.0.0.1", 9501);
$ret = $client->upgrade("/");
if ($ret) {
while(true) {
$client->push("hello");
var_dump($client->recv());
co::sleep(0.1);
}
}
});
download()
通过Http下载文件。
download与get方法的不同是download收到数据后会写入到磁盘,而不是在内存中对Http Body进行拼接。因此download仅使用小量内存,就可以完成超大文件的下载。
Swoole\Coroutine\Http\Client->download(string $path, string $filename, int $offset = 0): bool
参数
string $path
- 功能:设置
URL
路径 - 默认值:无
- 其它值:无
- 功能:设置
string $filename
- 功能:指定下载内容写入的文件路径【会自动写入到
downloadFile
属性】 - 默认值:无
- 其它值:无
- 功能:指定下载内容写入的文件路径【会自动写入到
int $offset
- 功能:指定写入文件的偏移量【此选项可用于支持断点续传,可配合
Http
头Range:bytes=$offset
实现】 - 默认值:无
- 其它值:无
!>
$offset
为0
时若文件已存在,底层会自动清空此文件- 功能:指定写入文件的偏移量【此选项可用于支持断点续传,可配合
返回值
- 执行成功返回
true
- 打开文件失败或底层
fseek()
文件失败返回false
- 执行成功返回
示例
Co\run(function () {
$host = 'www.swoole.com';
$client = new \Swoole\Coroutine\Http\Client($host, 443, true);
$client->set(['timeout' => -1]);
$client->setHeaders([
'Host' => $host,
'User-Agent' => 'Chrome/49.0.2587.3',
'Accept' => '*',
'Accept-Encoding' => 'gzip'
]);
$client->download('/static/files/swoole-logo.svg', __DIR__ . '/logo.svg');
});
getCookies()
获取Http
响应的cookie
内容。
Swoole\Coroutine\Http\Client->getCookies(): array|false;
!> Cookie信息将经过urldecode解码, 想要获取原始Cookie信息请按照下文自行解析
获取重名Cookie
或Cookie
原始头信息
var_dump($client->set_cookie_headers);
getHeaders()
返回Http
响应的头信息。
Swoole\Coroutine\Http\Client->getHeaders(): array|false;
getStatusCode()
获取Http
响应的状态码。
Swoole\Coroutine\Http\Client->getStatusCode(): int|false;
提示
- 状态码如果为负数,表示连接存在问题。
状态码 | v4.2.10 以上版本对应常量 | 说明 |
---|---|---|
-1 | SWOOLE_HTTP_CLIENT_ESTATUS_CONNECT_FAILED | 连接超时,服务器未监听端口或网络丢失,可以读取$errCode获取具体的网络错误码 |
-2 | SWOOLE_HTTP_CLIENT_ESTATUS_REQUEST_TIMEOUT | 请求超时,服务器未在规定的timeout时间内返回response |
-3 | SWOOLE_HTTP_CLIENT_ESTATUS_SERVER_RESET | 客户端请求发出后,服务器强制切断连接 |
getBody()
获取Http
响应的包体内容。
Swoole\Coroutine\Http\Client->getBody(): string|false;
close()
关闭连接。
Swoole\Coroutine\Http\Client->close(): bool;
!> close
后如果再次请求 get
、post
等方法时,Swoole会帮你重新连接服务器。
execute()
更底层的Http
请求方法,需要代码中调用setMethod和setData等接口设置请求的方法和数据。
Swoole\Coroutine\Http\Client->execute(string $path): bool;
- 示例
Co\run(function(){
$httpClient = new Swoole\Coroutine\Http\Client('httpbin.org', 80);
$httpClient->setMethod("POST");
$httpClient->setData("swoole");
$status = $httpClient->execute("/post");
var_dump($status);
var_dump($httpClient->getBody());
});