fanout/gripcontrol

此包已被弃用且不再维护。作者建议使用 fanout/grip 包。

PHP 的 GRIP 库。

2.1.1 2017-08-01 23:28 UTC

This package is not auto-updated.

Last update: 2021-08-31 00:40:01 UTC


README

作者:Konstantin Bokarius kon@fanout.io

PHP 的 GRIP 库。

许可

php-gripcontrol 在 MIT 许可下提供。请参阅 LICENSE 文件。

要求

  • openssl
  • curl
  • pthreads(异步发布所必需)
  • firebase/php-jwt >=1.0.0(通过 Composer 自动检索)
  • fanout/php-pubcontrol >=1.0.6(通过 Composer 自动检索)

安装

使用 Composer: 'composer require fanout/gripcontrol'

手动:确保已包含 php-jwt 和 php-pubcontrol,并在 php-gripcontrol 中要求以下文件

require 'php-gripcontrol/src/encoding.php';
require 'php-gripcontrol/src/channel.php';
require 'php-gripcontrol/src/response.php';
require 'php-gripcontrol/src/websocketevent.php';
require 'php-gripcontrol/src/websocketmessageformat.php';
require 'php-gripcontrol/src/httpstreamformat.php';
require 'php-gripcontrol/src/httpresponseformat.php';
require 'php-gripcontrol/src/grippubcontrol.php';
require 'php-gripcontrol/src/gripcontrol.php';

异步发布

为了进行异步发布调用,必须安装 pthreads。如果未安装 pthreads,则只能进行同步发布调用。要安装 pthreads,请使用以下标志重新编译 PHP:'--enable-maintainer-zts'

请注意,由于传递给 publish_async 方法的回调将在单独的线程中执行,因此该回调及其所属的类都受 pthreads 扩展强加的规则和限制的约束。

有关 pthreads 的更多信息,请参阅此处:https://php.ac.cn/manual/en/book.pthreads.php

使用

如何通过 GripPubControl 类将 HTTP 响应和 HTTP 流消息发布到 GRIP 代理端点的示例。

<?php

function callback($result, $message)
{
    if ($result)
        Print "Publish successful\r\n";
    else
        Print "Publish failed with message: {$message}\r\n";
}

// GripPubControl can be initialized with or without an endpoint configuration.
// Each endpoint can include optional JWT authentication info.
// Multiple endpoints can be included in a single configuration.

$grippub = new GripControl\GripPubControl(array(
        'control_uri' => 'https://api.fanout.io/realm/<myrealm>',
        'control_iss' => '<myrealm>',
        'key' => Base64.decode64('<myrealmkey>')));

// Add new endpoints by applying an endpoint configuration:
$grippub->apply_grip_config(array(
        array('control_uri' => '<myendpoint_uri_1>'), 
        array('control_uri' => '<myendpoint_uri_2>')));

// Remove all configured endpoints:
$grippub->remove_all_clients();

// Explicitly add an endpoint as a PubControlClient instance:
$pubclient = new PubControl\PubControlClient('<my_endpoint_uri>');
// Optionally set JWT auth: $pubclient->set_auth_jwt(<claim>, '<key>')
// Optionally set basic auth: $pubclient->set_auth_basic('<user>', '<password>')
$grippub->add_client($pubclient);

// Publish across all configured endpoints:
$grippub->publish_http_response('<channel>', 'Test publish!');
$grippub->publish_http_stream('<channel>', 'Test publish!');

// Use publish_async for async publishing only if pthreads are installed:
// $grippub->publish_http_response_async('<channel>', 'Test async publish!',
//         null, null, 'callback');
// $grippub->publish_http_stream_async('<channel>', 'Test async publish!',
//         null, null, 'callback');
// Wait for all async publish calls to complete:
// $grippub->finish();
?>

验证来自传入 GRIP 消息的 Grip-Sig 请求头。这确保了消息是从有效来源发送的,且未过期。请注意,当使用 Fanout.io 时,密钥是领域密钥,当使用 Pushpin 时,密钥可在 Pushpin 的设置中配置。

<?php
$is_valid = GripControl\GripControl::validate_sig(headers['Grip-Sig'], '<key>');
?>

通过响应 头部 的长轮询示例。客户端通过 HTTP 连接到 GRIP 代理,代理将请求转发到原始服务器。原始服务器将客户端订阅到频道并指示其通过响应 头部 进行长轮询。请注意,在 Apache 的最新版本中,无法发送包含自定义头部的 304 响应,在这种情况下,应使用响应体(下面的下一个使用示例)。

<?php
// Validate the Grip-Sig header:
$request_headers = getallheaders();
if (!GripControl\GripControl::validate_sig($request_headers['Grip-Sig'], '<key>'))
    return;

// Instruct the client to long poll via the response headers:
http_response_code(200);
header('Grip-Hold: response');
header('Grip-Channel: ' .
        GripControl\GripControl::create_grip_channel_header('<channel>'));
// To optionally set a timeout value in seconds:
// header('Grip-Timeout: <timeout_value>');
?>

通过响应 的长轮询示例。客户端通过 HTTP 连接到 GRIP 代理,代理将请求转发到原始服务器。原始服务器将客户端订阅到频道并指示其通过响应 进行长轮询。

<?php
// Validate the Grip-Sig header:
$request_headers = getallheaders();
if (!GripControl\GripControl::validate_sig($request_headers['Grip-Sig'], '<key>'))
    return;

// Instruct the client to long poll via the response body:
http_response_code(200);
header('Content-Type: application/grip-instruct');
echo GripControl\GripControl::create_hold_response('<channel>');
// Or to optionally set a timeout value in seconds:
// echo GripControl\GripControl::create_hold_response(
//        '<channel>', null, <timeout_value>);
?>

通过 HTTP 的 WebSocket 示例。在这种情况下,客户端通过 WebSocket 连接到 GRIP 代理,GRIP 代理通过 HTTP 与原始服务器通信。

<?php

class PublishMessage extends Thread
{
    public function run()
    {
        // Wait and then publish a message to the subscribed channel:
        sleep(5);
        $grippub = new GripControl\GripPubControl(
                array('control_uri' => '<myendpoint>'));
        $grippub->publish('<channel>', new PubControl\Item(
                new GripControl\WebSocketMessageFormat(
                'Test WebSocket publish!!')));
    }
}

// Validate the Grip-Sig header:
$request_headers = getallheaders();
if (!GripControl\GripControl::validate_sig($request_headers['Grip-Sig'], '<key>'))
    return;

// Set the headers required by the GRIP proxy:
header('Content-Type: application/websocket-events');
header('Sec-WebSocket-Extensions: grip; message-prefix=""');
http_response_code(200);
$in_events = GripControl\GripControl::decode_websocket_events(
        file_get_contents("php://input"));
if ($in_events[0]->type == 'OPEN')
{
    // Open the WebSocket and subscribe it to a channel:
    $out_events = array();
    $out_events[] = new GripControl\WebSocketEvent('OPEN');
    $out_events[] = new GripControl\WebSocketEvent('TEXT', 'c:' .
    GripControl\GripControl::websocket_control_message('subscribe',
            array('channel' => '<channel>')));
    $response = GripControl\GripControl::encode_websocket_events($out_events);
    ignore_user_abort(true);
    header("Connection: close");
    header("Content-Length: " . strlen($response));
    echo $response;
    ob_flush();
    flush();
    $publish_message = new PublishMessage();
    $publish_message->start();
}
?>

解析 GRIP URI 以提取 URI、ISS 和密钥值。这些值将返回一个包含 'control_uri'、'control_iss' 和 'key' 键的哈希中。

<?php
$config = GripControl\GripControl::parse_grip_uri(
    'http://api.fanout.io/realm/<myrealm>?iss=<myrealm>' .
    '&key=base64:<myrealmkey>');
?>