Skip to content

Commit cc3705b

Browse files
authored
Merge pull request #4 from clue-labs/browser
Optionally inject Browser into EventSource instead of Connector
2 parents 1b05044 + 6516e8a commit cc3705b

File tree

3 files changed

+299
-401
lines changed

3 files changed

+299
-401
lines changed

README.md

+59
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,73 @@ built on top of [ReactPHP](https://reactphp.org/).
88
**Table of contents**
99

1010
* [Quickstart example](#quickstart-example)
11+
* [Usage](#usage)
12+
* [EventSource](#eventsource)
1113
* [Install](#install)
1214
* [Tests](#tests)
1315
* [License](#license)
1416

1517
## Quickstart example
1618

19+
Once [installed](#install), you can use the following code to stream messages
20+
from any Server-Sent Events (SSE) server endpoint:
21+
22+
```php
23+
$loop = Factory::create();
24+
$es = new EventSource('https://example.com/stream.php', $loop);
25+
26+
$es->on('message', function (MessageEvent $message) {
27+
//$data = json_decode($message->data);
28+
var_dump($message);
29+
});
30+
31+
$loop->run();
32+
```
33+
1734
See the [examples](examples).
1835

36+
## Usage
37+
38+
### EventSource
39+
40+
The `EventSource` class is responsible for communication with the remote Server-Sent Events (SSE) endpoint.
41+
42+
The `EventSource` object works very similar to the one found in common
43+
web browsers. Unless otherwise noted, it follows the same semantics as defined
44+
under https://html.spec.whatwg.org/multipage/server-sent-events.html
45+
46+
It requires the URL to the remote Server-Sent Events (SSE) endpoint and also
47+
registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage)
48+
in order to handle async HTTP requests.
49+
50+
```php
51+
$loop = \React\EventLoop\Factory::create();
52+
53+
$es = new \Clue\React\EventSource\EventSource('https://example.com/stream.php', $loop);
54+
```
55+
56+
If you need custom connector settings (DNS resolution, TLS parameters, timeouts,
57+
proxy servers etc.), you can explicitly pass a custom instance of the
58+
[`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface)
59+
to the [`Browser`](https://github.com/clue/reactphp-buzz#browser) instance
60+
and pass it as an additional argument to the `EventSource` like this:
61+
62+
```php
63+
$connector = new \React\Socket\Connector($loop, array(
64+
'dns' => '127.0.0.1',
65+
'tcp' => array(
66+
'bindto' => '192.168.10.1:0'
67+
),
68+
'tls' => array(
69+
'verify_peer' => false,
70+
'verify_peer_name' => false
71+
)
72+
));
73+
$browser = new \Clue\React\Buzz\Browser($loop, $connector);
74+
75+
$es = new \Clue\React\EventSource\EventSource('https://example.com/stream.php', $loop, $browser);
76+
```
77+
1978
## Install
2079

2180
The recommended way to install this library is [through Composer](https://getcomposer.org).

src/EventSource.php

+50-14
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,51 @@
22

33
namespace Clue\React\EventSource;
44

5-
use React\EventLoop\LoopInterface;
6-
use Psr\Http\Message\ResponseInterface;
7-
use React\Stream\ReadableStreamInterface;
85
use Clue\React\Buzz\Browser;
96
use Evenement\EventEmitter;
10-
use React\Socket\ConnectorInterface;
7+
use Psr\Http\Message\ResponseInterface;
8+
use React\EventLoop\LoopInterface;
9+
use React\Stream\ReadableStreamInterface;
1110

11+
/**
12+
* The `EventSource` class is responsible for communication with the remote Server-Sent Events (SSE) endpoint.
13+
*
14+
* The `EventSource` object works very similar to the one found in common
15+
* web browsers. Unless otherwise noted, it follows the same semantics as defined
16+
* under https://html.spec.whatwg.org/multipage/server-sent-events.html
17+
*
18+
* It requires the URL to the remote Server-Sent Events (SSE) endpoint and also
19+
* registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage)
20+
* in order to handle async HTTP requests.
21+
*
22+
* ```php
23+
* $loop = \React\EventLoop\Factory::create();
24+
*
25+
* $es = new \Clue\React\EventSource\EventSource('https://example.com/stream.php', $loop);
26+
* ```
27+
*
28+
* If you need custom connector settings (DNS resolution, TLS parameters, timeouts,
29+
* proxy servers etc.), you can explicitly pass a custom instance of the
30+
* [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface)
31+
* to the [`Browser`](https://github.com/clue/reactphp-buzz#browser) instance
32+
* and pass it as an additional argument to the `EventSource` like this:
33+
*
34+
* ```php
35+
* $connector = new \React\Socket\Connector($loop, array(
36+
* 'dns' => '127.0.0.1',
37+
* 'tcp' => array(
38+
* 'bindto' => '192.168.10.1:0'
39+
* ),
40+
* 'tls' => array(
41+
* 'verify_peer' => false,
42+
* 'verify_peer_name' => false
43+
* )
44+
* ));
45+
* $browser = new \Clue\React\Buzz\Browser($loop, $connector);
46+
*
47+
* $es = new \Clue\React\EventSource\EventSource('https://example.com/stream.php', $loop, $browser);
48+
* ```
49+
*/
1250
class EventSource extends EventEmitter
1351
{
1452
/**
@@ -40,27 +78,25 @@ class EventSource extends EventEmitter
4078
private $timer;
4179
private $reconnectTime = 3.0;
4280

43-
public function __construct($url, LoopInterface $loop, ConnectorInterface $connector = null)
81+
public function __construct($url, LoopInterface $loop, Browser $browser = null)
4482
{
4583
$parts = parse_url($url);
4684
if (!isset($parts['scheme'], $parts['host']) || !in_array($parts['scheme'], array('http', 'https'))) {
4785
throw new \InvalidArgumentException();
4886
}
4987

50-
$browser = new Browser($loop, $connector);
88+
if ($browser === null) {
89+
$browser = new Browser($loop);
90+
}
5191
$this->browser = $browser->withOptions(array('streaming' => true, 'obeySuccessCode' => false));
5292
$this->loop = $loop;
5393
$this->url = $url;
5494

5595
$this->readyState = self::CONNECTING;
56-
57-
$this->timer = $loop->addTimer(0, function () {
58-
$this->timer = null;
59-
$this->send();
60-
});
96+
$this->request();
6197
}
6298

63-
private function send()
99+
private function request()
64100
{
65101
$headers = array(
66102
'Accept' => 'text/event-stream',
@@ -120,7 +156,7 @@ private function send()
120156
$this->readyState = self::CONNECTING;
121157
$this->timer = $this->loop->addTimer($this->reconnectTime, function () {
122158
$this->timer = null;
123-
$this->send();
159+
$this->request();
124160
});
125161
}
126162
});
@@ -140,7 +176,7 @@ private function send()
140176

141177
$this->timer = $this->loop->addTimer($this->reconnectTime, function () {
142178
$this->timer = null;
143-
$this->send();
179+
$this->request();
144180
});
145181
});
146182
}

0 commit comments

Comments
 (0)