diff --git a/README.md b/README.md index 9fc2a78..e25c1ff 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/src/Browser.php b/src/Browser.php index adb78f2..4913708 100644 --- a/src/Browser.php +++ b/src/Browser.php @@ -13,6 +13,7 @@ class Browser { private $sender; private $loop; + private $options = array(); public function __construct(LoopInterface $loop, Sender $sender = null) { @@ -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; + } } diff --git a/src/Io/Transaction.php b/src/Io/Transaction.php index 9f0d744..4072e48 100644 --- a/src/Io/Transaction.php +++ b/src/Io/Transaction.php @@ -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; } diff --git a/tests/FunctionalBrowserTest.php b/tests/FunctionalBrowserTest.php new file mode 100644 index 0000000..871cd1e --- /dev/null +++ b/tests/FunctionalBrowserTest.php @@ -0,0 +1,65 @@ +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(); + } +}