reactphp-x/eventsource

即时实时更新。轻量级的EventSource客户端,通过HTML5服务器端发送事件(SSE)接收实时消息。基于ReactPHP事件驱动架构的快速流处理。

v1.0.0 2024-08-10 01:34 UTC

This package is auto-updated.

Last update: 2024-09-10 02:44:33 UTC


README

CI status code coverage installs on Packagist

即时实时更新。轻量级的EventSource客户端,通过HTML5服务器端发送事件(SSE)接收实时消息。基于ReactPHP的事件驱动架构的快速流处理。

目录

支持我们

我们投入大量时间开发、维护和更新我们出色的开源项目。您可以通过成为GitHub赞助商来帮助我们保持工作的高质量。赞助商将获得许多回报,请参阅我们的赞助页面以获取详细信息。

让我们一起将这些项目提升到新的水平!🚀

快速入门示例

安装后,您可以使用以下代码从任何服务器端发送事件(SSE)服务器端点流式传输消息

data: {"name":"Alice","message":"Hello everybody!"}

data: {"name":"Bob","message":"Hey Alice!"}

data: {"name":"Carol","message":"Nice to see you Alice!"}

data: {"name":"Alice","message":"What a lovely chat!"}

data: {"name":"Bob","message":"All powered by ReactPHP, such an awesome piece of technology :)"}
$es = new Clue\React\EventSource\EventSource('https://example.com/stream.php');

$es->on('message', function (Clue\React\EventSource\MessageEvent $message) {
    $json = json_decode($message->data);
    echo $json->name . ': ' . $json->message . PHP_EOL;
});

查看示例

用法

EventSource

EventSource类负责与远程服务器端发送事件(SSE)端点进行通信。

EventSource对象与常见网络浏览器中的对象非常相似。除非另有说明,否则它遵循https://html.whatwg.com.cn/multipage/server-sent-events.html下定义的相同语义

其构造函数仅需要远程服务器端发送事件(SSE)端点的URL

$es = new Clue\React\EventSource\EventSource('https://example.com/stream.php');

如果您需要自定义连接器设置(DNS解析、TLS参数、超时、代理服务器等),您可以将自定义的ConnectorInterface实例显式传递给Browser实例,并将其作为附加参数传递给EventSource,如下所示

$connector = new React\Socket\Connector([
    'dns' => '127.0.0.1',
    'tcp' => [
        'bindto' => '192.168.10.1:0'
    ],
    'tls' => [
        'verify_peer' => false,
        'verify_peer_name' => false
    ]
]);
$browser = new React\Http\Browser($connector);

$es = new Clue\React\EventSource\EventSource('https://example.com/stream.php', $browser);

此类接受一个可选的LoopInterface|null $loop参数,该参数可用于将事件循环实例传递给此对象。您可以使用null值,以便使用默认循环。除非您确信您想显式使用给定的事件循环实例,否则不应提供此值。

消息事件

每当收到EventSource消息时,将发出message事件。

$es->on('message', function (Clue\React\EventSource\MessageEvent $message) {
    // $json = json_decode($message->data);
    var_dump($message);
});

EventSource流在其生命周期内可能发出任意数量的消息。每个message事件将接收一个MessageEvent对象

可以使用MessageEvent::$data属性来访问消息有效负载数据。它通常用于传输结构化数据,如JSON。

data: {"name":"Alice","age":30}

data: {"name":"Bob","age":50}
$es->on('message', function (Clue\React\EventSource\MessageEvent $message) {
    $json = json_decode($message->data);
    echo "{$json->name} is {$json->age} years old" . PHP_EOL;
});

EventSource 流可以为每个传入的消息指定事件类型。这个 event 字段可以用来发出适当的事件类型,如下所示

data: Alice
event: join

data: Hello!
event: chat

data: Bob
event: leave
$es->on('join', function (Clue\React\EventSource\MessageEvent $message) {
    echo $message->data . ' joined' . PHP_EOL;
});

$es->on('chat', function (Clue\React\EventSource\MessageEvent $message) {
    echo 'Message: ' . $message->data . PHP_EOL;
});

$es->on('leave', function (Clue\React\EventSource\MessageEvent $message) {
    echo $message->data . ' left' . PHP_EOL;
});

有关更多详情,请参阅 MessageEvent::$type 属性

打开事件

当 EventSource 连接成功建立时,将发出 open 事件。

$es->on('open', function () {
    echo 'Connection opened' . PHP_EOL;
});

一旦 EventSource 连接打开,它可能发出任意数量的 message 事件

如果连接无法成功打开,它将发出一个 error 事件

错误事件

当 EventSource 连接失败时,将发出 error 事件。该事件接收一个表示错误实例的 Exception 参数。

$redis->on('error', function (Exception $e) {
    echo 'Error: ' . $e->getMessage() . PHP_EOL;
});

当 EventSource 连接暂时断开时,将自动重试。如果服务器发送非成功 HTTP 状态码或无效的 Content-Type 响应头,则连接将永久失败。

$es->on('error', function (Exception $e) use ($es) {
    if ($es->readyState === Clue\React\EventSource\EventSource::CLOSED) {
        echo 'Permanent error: ' . $e->getMessage() . PHP_EOL;
    } else {
        echo 'Temporary error: ' . $e->getMessage() . PHP_EOL;
    }
});

请参阅 EventSource::$readyState 属性

EventSource::$readyState

可以使用 int $readyState 属性来检查当前的 EventSource 连接状态。

该状态是只读的,在其生命周期内可以处于三种状态之一

  • EventSource::CONNECTING
  • EventSource::OPEN
  • EventSource::CLOSED

EventSource::$url

可以使用 readonly string $url 属性来获取构造函数中提供的 EventSource URL。

close()

可以使用 close(): void 方法强制关闭 EventSource 连接。

这将关闭任何活动的连接或连接尝试,并进入 EventSource::CLOSED 状态。

MessageEvent

MessageEvent 类表示一个传入的 EventSource 消息。

MessageEvent::__construct()

可以使用 new MessageEvent(string $data, string $lastEventId = '', string $type = 'message') 构造函数来创建一个新的 MessageEvent 实例。

这主要用于内部表示每个传入的消息事件(也请参阅 message 事件)。同样,您也可以在测试用例中使用此类来测试您的应用程序对传入消息的反应。

构造函数验证并初始化此类的所有属性。如果任何参数无效,则抛出 InvalidArgumentException

MessageEvent::$data

可以使用 readonly string $data 属性来访问消息有效载荷数据。

data: hello
assert($message->data === 'hello');

data 字段可能跨越多行。这通常用于传输结构化数据,如 JSON。

data: {
data:     "message": "hello"
data: }
$json = json_decode($message->data);
assert($json->message === 'hello');

如果消息不包含 data 字段或 data 字段为空,则消息将被丢弃而不会发出事件。

MessageEvent::$lastEventId

可以使用 readonly string $lastEventId 属性来访问最后的事件 ID。

data: hello
id: 1
assert($message->data === 'hello');
assert($message->lastEventId === '1');

内部,将自动将 id 字段用作在连接中断时作为 Last-Event-ID HTTP 请求头。

如果消息不包含 id 字段,则 $lastEventId 属性将是最后接收的 ID 的值。如果没有先前的消息包含 ID,则默认为空字符串。

MessageEvent::$type

可以使用 readonly string $type 属性来访问消息事件类型。

data: Alice
event: join
assert($message->data === 'Alice');
assert($message->type === 'join');

内部,将使用 event 字段来发出适当的事件类型。也请参阅 message 事件

如果消息不包含 event 字段或 event 字段为空,则 $type 属性将默认为 message

安装

推荐通过 Composer 来安装此库。 您是 Composer 新手吗?

此项目遵循 SemVer。这将安装最新支持的版本

composer require clue/reactphp-eventsource:^1.2

请参阅CHANGELOG以获取有关版本升级的详细信息。

本项目旨在在任何平台上运行,因此不需要任何PHP扩展,并支持在旧版PHP 5.4到当前PHP 8+上运行。强烈建议使用本项目支持的最新PHP版本。

测试

要运行测试套件,您首先需要克隆此仓库,然后通过Composer安装所有依赖项(请访问Composer网站)

composer install

要运行测试套件,请进入项目根目录并执行以下操作

vendor/bin/phpunit

测试套件已配置为始终确保所有支持的环境100%的代码覆盖率。如果您已安装Xdebug扩展,您还可以本地生成代码覆盖率报告,方法如下

XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text

许可证

本项目采用宽松的MIT许可协议发布。

您知道吗?我可以提供定制开发服务,并为发布和贡献发行赞助发票。如有需要,请联系我(@clue)获取详细信息。

更多

  • 如果您想了解更多关于处理数据流的信息,请参阅底层react/stream组件的文档。

  • 如果您想运行Server-Sent Events (SSE)应用程序的服务器端,您可能希望使用由Framework X提供的强大服务器实现。