Skip to content

Commit eef9c95

Browse files
authored
Merge pull request #32 from clue-labs/docs
Improve documentation
2 parents a6f2c46 + dbc1d15 commit eef9c95

File tree

3 files changed

+240
-8
lines changed

3 files changed

+240
-8
lines changed

README.md

Lines changed: 238 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
[![CI status](https://github.com/clue/reactphp-eventsource/actions/workflows/ci.yml/badge.svg)](https://github.com/clue/reactphp-eventsource/actions)
44
[![installs on Packagist](https://img.shields.io/packagist/dt/clue/reactphp-eventsource?color=blue&label=installs%20on%20Packagist)](https://packagist.org/packages/clue/reactphp-eventsource)
55

6-
Event-driven EventSource client, receiving streaming messages from any HTML5 Server-Sent Events (SSE) server,
7-
built on top of [ReactPHP](https://reactphp.org/).
6+
Instant real-time updates. Lightweight EventSource client receiving live
7+
messages via HTML5 Server-Sent Events (SSE). Fast stream processing built on top
8+
of [ReactPHP](https://reactphp.org/)'s event-driven architecture.
89

910
> Note: This project is in early alpha stage! Feel free to report any issues you encounter.
1011
@@ -13,25 +14,48 @@ built on top of [ReactPHP](https://reactphp.org/).
1314
* [Quickstart example](#quickstart-example)
1415
* [Usage](#usage)
1516
* [EventSource](#eventsource)
17+
* [message event](#message-event)
18+
* [open event](#open-event)
19+
* [error event](#error-event)
20+
* [EventSource::$readyState](#eventsourcereadystate)
21+
* [EventSource::$url](#eventsourceurl)
22+
* [close()](#close)
23+
* [MessageEvent](#messageevent)
24+
* [MessageEvent::$data](#messageeventdata)
25+
* [MessageEvent::$lastEventId](#messageeventlasteventid)
26+
* [MessageEvent::$type](#messageeventtype)
1627
* [Install](#install)
1728
* [Tests](#tests)
1829
* [License](#license)
30+
* [More](#more)
1931

2032
## Quickstart example
2133

2234
Once [installed](#install), you can use the following code to stream messages
2335
from any Server-Sent Events (SSE) server endpoint:
2436

37+
```
38+
data: {"name":"Alice","message":"Hello everybody!"}
39+
40+
data: {"name":"Bob","message":"Hey Alice!"}
41+
42+
data: {"name":"Carol","message":"Nice to see you Alice!"}
43+
44+
data: {"name":"Alice","message":"What a lovely chat!"}
45+
46+
data: {"name":"Bob","message":"Yeah, all powered by ReactPHP, such an awesome piece of technology :)"}
47+
```
48+
2549
```php
2650
$es = new Clue\React\EventSource\EventSource('https://example.com/stream.php');
2751

2852
$es->on('message', function (Clue\React\EventSource\MessageEvent $message) {
29-
//$data = json_decode($message->data);
30-
var_dump($message);
53+
$json = json_decode($message->data);
54+
echo $json->name . ': ' . $json->message . PHP_EOL;
3155
});
3256
```
3357

34-
See the [examples](examples).
58+
See the [examples](examples/).
3559

3660
## Usage
3761

@@ -77,6 +101,205 @@ here in order to use the [default loop](https://github.com/reactphp/event-loop#l
77101
This value SHOULD NOT be given unless you're sure you want to explicitly use a
78102
given event loop instance.
79103

104+
#### message event
105+
106+
The `message` event will be emitted whenever an EventSource message is received.
107+
108+
```php
109+
$es->on('message', function (Clue\React\EventSource\MessageEvent $message) {
110+
// $json = json_decode($message->data);
111+
var_dump($message);
112+
});
113+
```
114+
115+
The EventSource stream may emit any number of messages over its lifetime. Each
116+
`message` event will receive a [`MessageEvent` object](#messageevent).
117+
118+
The [`MessageEvent::$data` property](#messageeventdata) can be used to access
119+
the message payload data. It is commonly used for transporting structured data
120+
such as JSON:
121+
122+
```
123+
data: {"name":"Alice","age":30}
124+
125+
data: {"name":"Bob","age":50}
126+
```
127+
```php
128+
$es->on('message', function (Clue\React\EventSource\MessageEvent $message) {
129+
$json = json_decode($message->data);
130+
echo "{$json->name} is {$json->age} years old" . PHP_EOL;
131+
});
132+
```
133+
134+
The EventSource stream may specify an event type for each incoming message. This
135+
`event` field can be used to emit appropriate event types like this:
136+
137+
```
138+
data: Alice
139+
event: join
140+
141+
data: Hello!
142+
event: chat
143+
144+
data: Bob
145+
event: leave
146+
```
147+
```php
148+
$es->on('join', function (Clue\React\EventSource\MessageEvent $message) {
149+
echo $message->data . ' joined' . PHP_EOL;
150+
});
151+
152+
$es->on('chat', function (Clue\React\EventSource\MessageEvent $message) {
153+
echo 'Message: ' . $message->data . PHP_EOL;
154+
});
155+
156+
$es->on('leave', function (Clue\React\EventSource\MessageEvent $message) {
157+
echo $message->data . ' left' . PHP_EOL;
158+
});
159+
```
160+
161+
See also [`MessageEvent::$type` property](#messageeventtype) for more details.
162+
163+
#### open event
164+
165+
The `open` event will be emitted when the EventSource connection is successfully established.
166+
167+
```php
168+
$es->on('open', function () {
169+
echo 'Connection opened' . PHP_EOL;
170+
});
171+
```
172+
173+
Once the EventSource connection is open, it may emit any number of
174+
[`message` events](#message-event).
175+
176+
If the connection can not be opened successfully, it will emit an
177+
[`error` event](#error-event) instead.
178+
179+
#### error event
180+
181+
The `error` event will be emitted when the EventSource connection fails.
182+
The event receives a single `Exception` argument for the error instance.
183+
184+
```php
185+
$redis->on('error', function (Exception $e) {
186+
echo 'Error: ' . $e->getMessage() . PHP_EOL;
187+
});
188+
```
189+
190+
The EventSource connection will be retried automatically when it is temporarily
191+
disconnected. If the server sends a non-successful HTTP status code or an
192+
invalid `Content-Type` response header, the connection will fail permanently.
193+
194+
```php
195+
$es->on('error', function (Exception $e) use ($es) {
196+
if ($es->readyState === Clue\React\EventSource\EventSource::CLOSED) {
197+
echo 'Permanent error: ' . $e->getMessage() . PHP_EOL;
198+
} else {
199+
echo 'Temporary error: ' . $e->getMessage() . PHP_EOL;
200+
}
201+
});
202+
```
203+
204+
See also the [`EventSource::$readyState` property](#eventsourcereadystate).
205+
206+
#### EventSource::$readyState
207+
208+
The `int $readyState` property can be used to
209+
check the current EventSource connection state.
210+
211+
The state is read-only and can be in one of three states over its lifetime:
212+
213+
* `EventSource::CONNECTING`
214+
* `EventSource::OPEN`
215+
* `EventSource::CLOSED`
216+
217+
#### EventSource::$url
218+
219+
The `readonly string $url` property can be used to
220+
get the EventSource URL as given to the constructor.
221+
222+
#### close()
223+
224+
The `close(): void` method can be used to
225+
forcefully close the EventSource connection.
226+
227+
This will close any active connections or connection attempts and go into the
228+
`EventSource::CLOSED` state.
229+
230+
### MessageEvent
231+
232+
The `MessageEvent` class represents an incoming EventSource message.
233+
234+
#### MessageEvent::$data
235+
236+
The `readonly string $data` property can be used to
237+
access the message payload data.
238+
239+
```
240+
data: hello
241+
```
242+
```php
243+
assert($message->data === 'hello');
244+
```
245+
246+
The `data` field may also span multiple lines. This is commonly used for
247+
transporting structured data such as JSON:
248+
249+
```
250+
data: {
251+
data: "message": "hello"
252+
data: }
253+
```
254+
```php
255+
$json = json_decode($message->data);
256+
assert($json->message === 'hello');
257+
```
258+
259+
If the message does not contain a `data` field or the `data` field is empty, the
260+
message will be discarded without emitting an event.
261+
262+
#### MessageEvent::$lastEventId
263+
264+
The `readonly string $lastEventId` property can be used to
265+
access the last event ID.
266+
267+
```
268+
data: hello
269+
id: 1
270+
```
271+
```php
272+
assert($message->data === 'hello');
273+
assert($message->lastEventId === '1');
274+
```
275+
276+
Internally, the `id` field will automatically be used as the `Last-Event-ID` HTTP
277+
request header in case the connection is interrupted.
278+
279+
If the message does not contain an `id` field, the `$lastEventId` property will
280+
be the value of the last ID received. If no previous message contained an ID, it
281+
will default to an empty string.
282+
283+
#### MessageEvent::$type
284+
285+
The `readonly string $type` property can be used to
286+
access the message event type.
287+
288+
```
289+
data: Alice
290+
event: join
291+
```
292+
```php
293+
assert($message->data === 'Alice');
294+
assert($message->type === 'join');
295+
```
296+
297+
Internally, the `event` field will be used to emit the appropriate event type.
298+
See also [`message` event](#message-event).
299+
300+
If the message does not contain a `event` field or the `event` field is empty,
301+
the `$type` property will default to `message`.
302+
80303
## Install
81304

82305
The recommended way to install this library is [through Composer](https://getcomposer.org/).
@@ -105,7 +328,7 @@ $ composer install
105328
To run the test suite, go to the project root and run:
106329

107330
```bash
108-
$ php vendor/bin/phpunit
331+
$ vendor/bin/phpunit
109332
```
110333

111334
## License
@@ -114,3 +337,12 @@ This project is released under the permissive [MIT license](LICENSE).
114337

115338
> Did you know that I offer custom development services and issuing invoices for
116339
sponsorships of releases and for contributions? Contact me (@clue) for details.
340+
341+
## More
342+
343+
* If you want to learn more about processing streams of data, refer to the documentation of
344+
the underlying [react/stream](https://github.com/reactphp/stream) component.
345+
346+
* If you're looking to run the server side of your Server-Sent Events (SSE)
347+
application, you may want to use the powerful server implementation provided
348+
by [Framework X](https://framework-x.org/).

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "clue/reactphp-eventsource",
3-
"description": "Event-driven EventSource client, receiving streaming messages from any HTML5 Server-Sent Events (SSE) server, built on top of ReactPHP",
3+
"description": "Instant real-time updates. Lightweight EventSource client receiving live messages via HTML5 Server-Sent Events (SSE). Fast stream processing built on top of ReactPHP's event-driven architecture.",
44
"keywords": ["EventSource", "Server-Side Events", "SSE", "event-driven", "ReactPHP", "async"],
55
"homepage": "https://github.com/clue/reactphp-eventsource",
66
"license": "MIT",

examples/stream.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
$es = new Clue\React\EventSource\EventSource($argv[1]);
1010

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

0 commit comments

Comments
 (0)