Skip to content

Commit e1c5e4f

Browse files
authored
Merge pull request #418 from clue-labs/browser-signature
Update `Browser` signature to take `$connector` as first argument
2 parents 77f56dc + 12a4946 commit e1c5e4f

File tree

8 files changed

+172
-31
lines changed

8 files changed

+172
-31
lines changed

README.md

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,6 @@ like this:
259259

260260
```php
261261
$browser = new React\Http\Browser(
262-
null,
263262
new React\Socket\Connector(
264263
null,
265264
array(
@@ -610,7 +609,7 @@ $connector = new React\Socket\Connector(null, array(
610609
'dns' => false
611610
));
612611

613-
$browser = new React\Http\Browser(null, $connector);
612+
$browser = new React\Http\Browser($connector);
614613
```
615614

616615
See also the [HTTP CONNECT proxy example](examples/11-client-http-connect-proxy.php).
@@ -637,7 +636,7 @@ $connector = new React\Socket\Connector(null, array(
637636
'dns' => false
638637
));
639638

640-
$browser = new React\Http\Browser(null, $connector);
639+
$browser = new React\Http\Browser($connector);
641640
```
642641

643642
See also the [SOCKS proxy example](examples/12-client-socks-proxy.php).
@@ -666,7 +665,7 @@ $connector = new React\Socket\Connector(null, array(
666665
'dns' => false
667666
));
668667

669-
$browser = new React\Http\Browser(null, $connector);
668+
$browser = new React\Http\Browser($connector);
670669
```
671670

672671
See also the [SSH proxy example](examples/13-client-ssh-proxy.php).
@@ -687,7 +686,7 @@ $connector = new React\Socket\FixedUriConnector(
687686
new React\Socket\UnixConnector()
688687
);
689688

690-
$browser = new Browser(null, $connector);
689+
$browser = new React\Http\Browser($connector);
691690

692691
$client->get('http://localhost/info')->then(function (Psr\Http\Message\ResponseInterface $response) {
693692
var_dump($response->getHeaders(), (string)$response->getBody());
@@ -1875,11 +1874,15 @@ and keeps track of pending incoming HTTP responses.
18751874
$browser = new React\Http\Browser();
18761875
```
18771876

1878-
This class takes an optional `LoopInterface|null $loop` parameter that can be used to
1879-
pass the event loop instance to use for this object. You can use a `null` value
1880-
here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
1881-
This value SHOULD NOT be given unless you're sure you want to explicitly use a
1882-
given event loop instance.
1877+
This class takes two optional arguments for more advanced usage:
1878+
1879+
```php
1880+
// constructor signature as of v1.5.0
1881+
$browser = new React\Http\Browser(?ConnectorInterface $connector = null, ?LoopInterface $loop = null);
1882+
1883+
// legacy constructor signature before v1.5.0
1884+
$browser = new React\Http\Browser(?LoopInterface $loop = null, ?ConnectorInterface $connector = null);
1885+
```
18831886

18841887
If you need custom connector settings (DNS resolution, TLS parameters, timeouts,
18851888
proxy servers etc.), you can explicitly pass a custom instance of the
@@ -1897,9 +1900,15 @@ $connector = new React\Socket\Connector(null, array(
18971900
)
18981901
));
18991902

1900-
$browser = new React\Http\Browser(null, $connector);
1903+
$browser = new React\Http\Browser($connector);
19011904
```
19021905

1906+
This class takes an optional `LoopInterface|null $loop` parameter that can be used to
1907+
pass the event loop instance to use for this object. You can use a `null` value
1908+
here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
1909+
This value SHOULD NOT be given unless you're sure you want to explicitly use a
1910+
given event loop instance.
1911+
19031912
> Note that the browser class is final and shouldn't be extended, it is likely to be marked final in a future release.
19041913
19051914
#### get()

examples/11-client-http-connect-proxy.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
'tcp' => $proxy,
2222
'dns' => false
2323
));
24-
$browser = new Browser(null, $connector);
24+
25+
$browser = new Browser($connector);
2526

2627
// demo fetching HTTP headers (or bail out otherwise)
2728
$browser->get('https://www.google.com/')->then(function (ResponseInterface $response) {

examples/12-client-socks-proxy.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
'tcp' => $proxy,
1919
'dns' => false
2020
));
21-
$browser = new Browser(null, $connector);
21+
22+
$browser = new Browser($connector);
2223

2324
// demo fetching HTTP headers (or bail out otherwise)
2425
$browser->get('https://www.google.com/')->then(function (ResponseInterface $response) {

examples/13-client-ssh-proxy.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
'tcp' => $proxy,
1818
'dns' => false
1919
));
20-
$browser = new Browser(null, $connector);
20+
21+
$browser = new Browser($connector);
2122

2223
// demo fetching HTTP headers (or bail out otherwise)
2324
$browser->get('https://www.google.com/')->then(function (ResponseInterface $response) {

examples/14-client-unix-domain-sockets.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
new UnixConnector()
1515
);
1616

17-
$browser = new Browser(null, $connector);
17+
$browser = new Browser($connector);
1818

1919
// demo fetching HTTP headers (or bail out otherwise)
2020
$browser->get('http://localhost/info')->then(function (ResponseInterface $response) {

src/Browser.php

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,15 @@ class Browser
3232
* $browser = new React\Http\Browser();
3333
* ```
3434
*
35-
* This class takes an optional `LoopInterface|null $loop` parameter that can be used to
36-
* pass the event loop instance to use for this object. You can use a `null` value
37-
* here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
38-
* This value SHOULD NOT be given unless you're sure you want to explicitly use a
39-
* given event loop instance.
35+
* This class takes two optional arguments for more advanced usage:
36+
*
37+
* ```php
38+
* // constructor signature as of v1.5.0
39+
* $browser = new React\Http\Browser(?ConnectorInterface $connector = null, ?LoopInterface $loop = null);
40+
*
41+
* // legacy constructor signature before v1.5.0
42+
* $browser = new React\Http\Browser(?LoopInterface $loop = null, ?ConnectorInterface $connector = null);
43+
* ```
4044
*
4145
* If you need custom connector settings (DNS resolution, TLS parameters, timeouts,
4246
* proxy servers etc.), you can explicitly pass a custom instance of the
@@ -54,15 +58,32 @@ class Browser
5458
* )
5559
* ));
5660
*
57-
* $browser = new React\Http\Browser(null, $connector);
61+
* $browser = new React\Http\Browser($connector);
5862
* ```
5963
*
60-
* @param ?LoopInterface $loop
61-
* @param ?ConnectorInterface $connector [optional] Connector to use.
62-
* Should be `null` in order to use default Connector.
64+
* This class takes an optional `LoopInterface|null $loop` parameter that can be used to
65+
* pass the event loop instance to use for this object. You can use a `null` value
66+
* here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
67+
* This value SHOULD NOT be given unless you're sure you want to explicitly use a
68+
* given event loop instance.
69+
*
70+
* @param null|ConnectorInterface|LoopInterface $connector
71+
* @param null|LoopInterface|ConnectorInterface $loop
72+
* @throws \InvalidArgumentException for invalid arguments
6373
*/
64-
public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null)
74+
public function __construct($connector = null, $loop = null)
6575
{
76+
// swap arguments for legacy constructor signature
77+
if (($connector instanceof LoopInterface || $connector === null) && ($loop instanceof ConnectorInterface || $loop === null)) {
78+
$swap = $loop;
79+
$loop = $connector;
80+
$connector = $swap;
81+
}
82+
83+
if (($connector !== null && !$connector instanceof ConnectorInterface) || ($loop !== null && !$loop instanceof LoopInterface)) {
84+
throw new \InvalidArgumentException('Expected "?ConnectorInterface $connector" and "?LoopInterface $loop" arguments');
85+
}
86+
6687
$loop = $loop ?: Loop::get();
6788
$this->transaction = new Transaction(
6889
Sender::createFromLoop($loop, $connector),

tests/BrowserTest.php

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
namespace React\Tests\Http;
44

55
use Clue\React\Block;
6-
use React\Http\Browser;
76
use Psr\Http\Message\RequestInterface;
7+
use React\Http\Browser;
88
use React\Promise\Promise;
99
use RingCentral\Psr7\Uri;
1010

@@ -21,7 +21,7 @@ public function setUpBrowser()
2121
{
2222
$this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
2323
$this->sender = $this->getMockBuilder('React\Http\Io\Transaction')->disableOriginalConstructor()->getMock();
24-
$this->browser = new Browser($this->loop);
24+
$this->browser = new Browser(null, $this->loop);
2525

2626
$ref = new \ReflectionProperty($this->browser, 'transaction');
2727
$ref->setAccessible(true);
@@ -43,6 +43,114 @@ public function testConstructWithoutLoopAssignsLoopAutomatically()
4343
$this->assertInstanceOf('React\EventLoop\LoopInterface', $loop);
4444
}
4545

46+
public function testConstructWithConnectorAssignsGivenConnector()
47+
{
48+
$connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();
49+
50+
$browser = new Browser($connector);
51+
52+
$ref = new \ReflectionProperty($browser, 'transaction');
53+
$ref->setAccessible(true);
54+
$transaction = $ref->getValue($browser);
55+
56+
$ref = new \ReflectionProperty($transaction, 'sender');
57+
$ref->setAccessible(true);
58+
$sender = $ref->getValue($transaction);
59+
60+
$ref = new \ReflectionProperty($sender, 'http');
61+
$ref->setAccessible(true);
62+
$client = $ref->getValue($sender);
63+
64+
$ref = new \ReflectionProperty($client, 'connector');
65+
$ref->setAccessible(true);
66+
$ret = $ref->getValue($client);
67+
68+
$this->assertSame($connector, $ret);
69+
}
70+
71+
public function testConstructWithConnectorWithLegacySignatureAssignsGivenConnector()
72+
{
73+
$connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();
74+
75+
$browser = new Browser(null, $connector);
76+
77+
$ref = new \ReflectionProperty($browser, 'transaction');
78+
$ref->setAccessible(true);
79+
$transaction = $ref->getValue($browser);
80+
81+
$ref = new \ReflectionProperty($transaction, 'sender');
82+
$ref->setAccessible(true);
83+
$sender = $ref->getValue($transaction);
84+
85+
$ref = new \ReflectionProperty($sender, 'http');
86+
$ref->setAccessible(true);
87+
$client = $ref->getValue($sender);
88+
89+
$ref = new \ReflectionProperty($client, 'connector');
90+
$ref->setAccessible(true);
91+
$ret = $ref->getValue($client);
92+
93+
$this->assertSame($connector, $ret);
94+
}
95+
96+
public function testConstructWithLoopAssignsGivenLoop()
97+
{
98+
$browser = new Browser(null, $this->loop);
99+
100+
$ref = new \ReflectionProperty($browser, 'transaction');
101+
$ref->setAccessible(true);
102+
$transaction = $ref->getValue($browser);
103+
104+
$ref = new \ReflectionProperty($transaction, 'loop');
105+
$ref->setAccessible(true);
106+
$loop = $ref->getValue($transaction);
107+
108+
$this->assertSame($this->loop, $loop);
109+
}
110+
111+
public function testConstructWithLoopWithLegacySignatureAssignsGivenLoop()
112+
{
113+
$browser = new Browser($this->loop);
114+
115+
$ref = new \ReflectionProperty($browser, 'transaction');
116+
$ref->setAccessible(true);
117+
$transaction = $ref->getValue($browser);
118+
119+
$ref = new \ReflectionProperty($transaction, 'loop');
120+
$ref->setAccessible(true);
121+
$loop = $ref->getValue($transaction);
122+
123+
$this->assertSame($this->loop, $loop);
124+
}
125+
126+
public function testConstructWithInvalidConnectorThrows()
127+
{
128+
$this->setExpectedException('InvalidArgumentException');
129+
new Browser('foo');
130+
}
131+
132+
public function testConstructWithInvalidLoopThrows()
133+
{
134+
$connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();
135+
136+
$this->setExpectedException('InvalidArgumentException');
137+
new Browser($connector, 'foo');
138+
}
139+
140+
public function testConstructWithConnectorTwiceThrows()
141+
{
142+
$connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();
143+
144+
$this->setExpectedException('InvalidArgumentException');
145+
new Browser($connector, $connector);
146+
}
147+
148+
public function testConstructWithLoopTwiceThrows()
149+
{
150+
$this->setExpectedException('InvalidArgumentException');
151+
new Browser($this->loop, $this->loop);
152+
}
153+
46154
public function testGetSendsGetRequest()
47155
{
48156
$that = $this;
@@ -390,7 +498,7 @@ public function testCancelGetRequestShouldCancelUnderlyingSocketConnection()
390498
$connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();
391499
$connector->expects($this->once())->method('connect')->with('example.com:80')->willReturn($pending);
392500

393-
$this->browser = new Browser($this->loop, $connector);
501+
$this->browser = new Browser($connector, $this->loop);
394502

395503
$promise = $this->browser->get('http://example.com/');
396504
$promise->cancel();

tests/FunctionalBrowserTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class FunctionalBrowserTest extends TestCase
3030
public function setUpBrowserAndServer()
3131
{
3232
$this->loop = $loop = Factory::create();
33-
$this->browser = new Browser($this->loop);
33+
$this->browser = new Browser(null, $this->loop);
3434

3535
$http = new HttpServer($this->loop, new StreamingRequestMiddleware(), function (ServerRequestInterface $request) use ($loop) {
3636
$path = $request->getUri()->getPath();
@@ -398,7 +398,7 @@ public function testVerifyPeerEnabledForBadSslRejects()
398398
)
399399
));
400400

401-
$browser = new Browser($this->loop, $connector);
401+
$browser = new Browser($connector, $this->loop);
402402

403403
$this->setExpectedException('RuntimeException');
404404
Block\await($browser->get('https://self-signed.badssl.com/'), $this->loop);
@@ -420,7 +420,7 @@ public function testVerifyPeerDisabledForBadSslResolves()
420420
)
421421
));
422422

423-
$browser = new Browser($this->loop, $connector);
423+
$browser = new Browser($connector, $this->loop);
424424

425425
Block\await($browser->get('https://self-signed.badssl.com/'), $this->loop);
426426
}

0 commit comments

Comments
 (0)