Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose Transaction options via Browser #25

Merged
merged 5 commits into from
Jun 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,26 @@ $client = new Browser($loop, $sender);
$client->get('http://localhost/demo');
```

### Options

Note: This API is subject to change.

The [`Browser`](#browser) class exposes several options for the handling of
HTTP transactions. These options resemble some of PHP's
[HTTP context options](http://php.net/manual/en/context.http.php) and
can be controlled via the following API (and their defaults):

```php
$newBrowser = $browser->withOptions(array(
'followRedirects' => true,
'maxRedirects' => 10,
'obeySuccessCode' => true
));
```

Notice that the [`Browser`](#browser) is an immutable object, i.e. the `withOptions()` method
actually returns a *new* [`Browser`](#browser) instance with the options applied.

### Streaming

Note: This API is subject to change.
Expand Down
15 changes: 14 additions & 1 deletion src/Browser.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Browser
{
private $sender;
private $loop;
private $options = array();

public function __construct(LoopInterface $loop, Sender $sender = null)
{
Expand Down Expand Up @@ -75,8 +76,20 @@ public function request($method, $url, $headers = array(), $content = null)

public function send(Request $request)
{
$transaction = new Transaction($request, $this->sender);
$transaction = new Transaction($request, $this->sender, $this->options);

return $transaction->send();
}

public function withOptions(array $options)
{
$browser = clone $this;

// merge all options, but remove those explicitly assigned a null value
$browser->options = array_filter($options + $this->options, function ($value) {
return ($value !== null);
});

return $browser;
}
}
8 changes: 7 additions & 1 deletion src/Io/Transaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,14 @@ class Transaction
// context: http.ignore_errors
private $obeySuccessCode = true;

public function __construct(Request $request, Sender $sender)
public function __construct(Request $request, Sender $sender, array $options = array())
{
foreach ($options as $name => $value) {
if (property_exists($this, $name)) {
$this->$name = $value;
}
}

$this->request = $request;
$this->sender = $sender;
}
Expand Down
65 changes: 65 additions & 0 deletions tests/FunctionalBrowserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

use React\EventLoop\Factory;
use Clue\React\Buzz\Browser;

class FunctionalBrowserTest extends TestCase
{
private $loop;
private $browser;

/** base url to the httpbin service **/
private $base = 'http://httpbin.org/';

public function setUp()
{
$this->loop = Factory::create();
$this->browser = new Browser($this->loop);
}

public function testSimpleRequest()
{
$this->expectPromiseResolve($this->browser->get($this->base . 'get'));

$this->loop->run();
}

public function testRedirectRequest()
{
$this->expectPromiseResolve($this->browser->get($this->base . 'redirect-to?url=' . urlencode($this->base . 'get')));

$this->loop->run();
}

public function testNotFollowingRedirectsResolvesWithRedirectResult()
{
$browser = $this->browser->withOptions(array('followRedirects' => false));

$this->expectPromiseResolve($browser->get($this->base . 'redirect/3'));

$this->loop->run();
}

public function testRejectingRedirectsRejects()
{
$browser = $this->browser->withOptions(array('maxRedirects' => 0));

$this->expectPromiseReject($browser->get($this->base . 'redirect/3'));

$this->loop->run();
}

public function testInvalidPort()
{
$this->expectPromiseReject($this->browser->get('http://www.google.com:443'));

$this->loop->run();
}

public function testInvalidPath()
{
$this->expectPromiseReject($this->browser->get($this->base . 'status/404'));

$this->loop->run();
}
}