fanout / gripcontrol
Requires
- php: >=5.3.0
- fanout/pubcontrol: ^2.0.0
- firebase/php-jwt: ~4.0
Requires (Dev)
- phpunit/phpunit: 3.7.14
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>'); ?>