2
2
3
3
namespace Clue \React \EventSource ;
4
4
5
- use React \EventLoop \LoopInterface ;
6
- use Psr \Http \Message \ResponseInterface ;
7
- use React \Stream \ReadableStreamInterface ;
8
5
use Clue \React \Buzz \Browser ;
9
6
use Evenement \EventEmitter ;
10
- use React \Socket \ConnectorInterface ;
7
+ use Psr \Http \Message \ResponseInterface ;
8
+ use React \EventLoop \LoopInterface ;
9
+ use React \Stream \ReadableStreamInterface ;
11
10
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
+ */
12
50
class EventSource extends EventEmitter
13
51
{
14
52
/**
@@ -40,27 +78,25 @@ class EventSource extends EventEmitter
40
78
private $ timer ;
41
79
private $ reconnectTime = 3.0 ;
42
80
43
- public function __construct ($ url , LoopInterface $ loop , ConnectorInterface $ connector = null )
81
+ public function __construct ($ url , LoopInterface $ loop , Browser $ browser = null )
44
82
{
45
83
$ parts = parse_url ($ url );
46
84
if (!isset ($ parts ['scheme ' ], $ parts ['host ' ]) || !in_array ($ parts ['scheme ' ], array ('http ' , 'https ' ))) {
47
85
throw new \InvalidArgumentException ();
48
86
}
49
87
50
- $ browser = new Browser ($ loop , $ connector );
88
+ if ($ browser === null ) {
89
+ $ browser = new Browser ($ loop );
90
+ }
51
91
$ this ->browser = $ browser ->withOptions (array ('streaming ' => true , 'obeySuccessCode ' => false ));
52
92
$ this ->loop = $ loop ;
53
93
$ this ->url = $ url ;
54
94
55
95
$ this ->readyState = self ::CONNECTING ;
56
-
57
- $ this ->timer = $ loop ->addTimer (0 , function () {
58
- $ this ->timer = null ;
59
- $ this ->send ();
60
- });
96
+ $ this ->request ();
61
97
}
62
98
63
- private function send ()
99
+ private function request ()
64
100
{
65
101
$ headers = array (
66
102
'Accept ' => 'text/event-stream ' ,
@@ -120,7 +156,7 @@ private function send()
120
156
$ this ->readyState = self ::CONNECTING ;
121
157
$ this ->timer = $ this ->loop ->addTimer ($ this ->reconnectTime , function () {
122
158
$ this ->timer = null ;
123
- $ this ->send ();
159
+ $ this ->request ();
124
160
});
125
161
}
126
162
});
@@ -140,7 +176,7 @@ private function send()
140
176
141
177
$ this ->timer = $ this ->loop ->addTimer ($ this ->reconnectTime , function () {
142
178
$ this ->timer = null ;
143
- $ this ->send ();
179
+ $ this ->request ();
144
180
});
145
181
});
146
182
}
0 commit comments