当前位置: 首页 > 文档资料 > Swoole 中文文档 >

协程HTTP/Websocket客户端

优质
小牛编辑
133浏览
2023-12-01

协程版Http客户端的底层用纯C编写,不依赖任何第三方扩展库,拥有超高的性能。

  • 支持Http-ChunkKeep-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 额外增加了一些选项,来控制HttpWebSocket客户端。

额外选项

超时控制

设置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设置名为Cookieheader

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-Typeurlencoded格式, 底层将会自动进行http_build_query
    • 如果使用了addFileaddData导致启用了form-data格式, $data值为字符串时将会被忽略(因为格式不同), 但为数组时底层将会以form-data格式追加数组中的字段

addFile()

添加POST文件。

!> 使用addFile会自动将POSTContent-Type将变更为form-dataaddFile底层基于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()

使用字符串构建上传文件内容。

!> addDatav4.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-Typeapplication/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,而是200403,这说明服务器拒绝了握手请求
    • 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型)改为flagsint型)以支持Websocket压缩,finish对应SWOOLE_WEBSOCKET_FLAG_FIN值为1,原有bool型值会隐式转换为int型,此改动向下兼容无影响。 此外压缩flagSWOOLE_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

      • 功能:指定写入文件的偏移量【此选项可用于支持断点续传,可配合HttpRange:bytes=$offset实现】
      • 默认值:无
      • 其它值:无

      !> $offset0时若文件已存在,底层会自动清空此文件

  • 返回值

    • 执行成功返回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信息请按照下文自行解析

获取重名CookieCookie原始头信息

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 以上版本对应常量说明
-1SWOOLE_HTTP_CLIENT_ESTATUS_CONNECT_FAILED连接超时,服务器未监听端口或网络丢失,可以读取$errCode获取具体的网络错误码
-2SWOOLE_HTTP_CLIENT_ESTATUS_REQUEST_TIMEOUT请求超时,服务器未在规定的timeout时间内返回response
-3SWOOLE_HTTP_CLIENT_ESTATUS_SERVER_RESET客户端请求发出后,服务器强制切断连接

getBody()

获取Http响应的包体内容。

Swoole\Coroutine\Http\Client->getBody(): string|false;

close()

关闭连接。

Swoole\Coroutine\Http\Client->close(): bool;

!> close后如果再次请求 getpost 等方法时,Swoole会帮你重新连接服务器。

execute()

更底层的Http请求方法,需要代码中调用setMethodsetData等接口设置请求的方法和数据。

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());
});