Skip to content
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
129 changes: 39 additions & 90 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ mess with most of the low-level details.
* [ResponseException](#responseexception)
* [Advanced](#advanced)
* [Sender](#sender)
* [DNS](#dns)
* [Connection options](#connection-options)
* [SOCKS proxy](#socks-proxy)
* [UNIX domain sockets](#unix-domain-sockets)
* [Unix domain sockets](#unix-domain-sockets)
* [Options](#options)
* [Install](#install)
* [Tests](#tests)
Expand Down Expand Up @@ -86,11 +84,33 @@ It also registers everything with the main [`EventLoop`](https://github.com/reac

```php
$loop = React\EventLoop\Factory::create();

$browser = new Browser($loop);
```

If you need custom DNS or proxy settings, you can explicitly pass a
custom [`Sender`](#sender) instance. This is considered *advanced usage*.
If you need custom connector settings (DNS resolution, TLS parameters, timeouts,
proxy servers etc.), you can explicitly pass a custom instance of the
[`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface):

```php
$connector = new \React\Socket\Connector($loop, array(
'dns' => '127.0.0.1',
'tcp' => array(
'bindto' => '192.168.10.1:0'
),
'tls' => array(
'verify_peer' => false,
'verify_peer_name' => false
)
));

$browser = new Browser($loop, $connector);
```

Legacy notice: This project previously used different APIs that are now
deprecated, but continue to work unchanged. This legacy API will be removed in
a future version, so it's highly recommended to upgrade to the above API.
See also [`Sender`](#sender).

#### Methods

Expand Down Expand Up @@ -346,6 +366,9 @@ See [options](#options) for more details.

#### withSender()

> [deprecated] The `Sender` is deprecated and will likely be removed in a
future version.

The `withSender(Sender $sender)` method can be used to change the [`Sender`](#sender) instance to use:

```php
Expand Down Expand Up @@ -437,6 +460,9 @@ The `getResponse()` method can be used to access its underlying [`ResponseIntefa

### Sender

> [deprecated] The `Sender` is deprecated and will likely be removed in a
future version.

The `Sender` is responsible for passing the [`RequestInterface`](#requestinterface) objects to
the underlying [`HttpClient`](https://github.com/reactphp/http-client) library
and keeps track of its transmission and converts its reponses back to [`ResponseInterface`](#responseinterface) objects.
Expand All @@ -446,87 +472,10 @@ and the default [`Connector`](https://github.com/reactphp/socket-client) and [DN

See also [`Browser::withSender()`](#withsender) for changing the `Sender` instance during runtime.

### DNS

The [`Sender`](#sender) is also responsible for creating the underlying TCP/IP
connection to the remote HTTP server and hence has to orchestrate DNS lookups.
By default, it uses a `Connector` instance which uses Google's public DNS servers
(`8.8.8.8`).

If you need custom DNS settings, you can explicitly create a [`Sender`](#sender) instance
with your DNS server address (or `React\Dns\Resolver` instance) like this:

```php
// new API for react/http 0.5
$connector = new \React\Socket\Connector($loop, array(
'dns' => '127.0.0.1'
));
$client = new \React\HttpClient\Client($loop, $connector);
$sender = new \Clue\Buzz\Io\Sender($client);
$browser = $browser->withSender($sender);

// deprecated legacy API
$dns = '127.0.0.1';
$sender = Sender::createFromLoopDns($loop, $dns);
$browser = $browser->withSender($sender);
```

See also [`Browser::withSender()`](#withsender) for more details.

### Connection options

If you need custom connector settings (DNS resolution, SSL/TLS parameters, timeouts etc.), you can explicitly pass a
custom instance of the new [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface).

```php
// new API for react/http 0.5
$connector = new \React\Socket\Connector($loop, array(
'dns' => '127.0.0.1'
));
$client = new \React\HttpClient\Client($loop, $connector);
$sender = new \Clue\Buzz\Io\Sender($client);
$browser = $browser->withSender($sender);
```

If you're still using the deprecated legacy Http component and you need custom
connector settings (DNS resolution, SSL/TLS parameters, timeouts etc.), you can
explicitly pass a custom instance of the
[legacy `ConnectorInterface`](https://github.com/reactphp/socket-client#connectorinterface).

You can optionally pass additional
[socket context options](http://php.net/manual/en/context.socket.php)
to the constructor like this:

```php
// deprecated legacy API
// use local DNS server
$dnsResolverFactory = new DnsFactory();
$resolver = $dnsResolverFactory->createCached('127.0.0.1', $loop);

// outgoing connections via interface 192.168.10.1
$tcp = new DnsConnector(
new TcpConnector($loop, array('bindto' => '192.168.10.1:0')),
$resolver
);

$sender = Sender::createFromLoopConnectors($loop, $tcp);
$browser = $browser->withSender($sender);
```

You can optionally pass additional
[SSL context options](http://php.net/manual/en/context.ssl.php)
to the constructor like this:

```php
// deprecated legacy API
$ssl = new SecureConnector($tcp, $loop, array(
'verify_peer' => false,
'verify_peer_name' => false
));

$sender = Sender::createFromLoopConnectors($loop, $tcp, $ssl);
$browser = $browser->withSender($sender);
```
Legacy notice: The `Sender` class mostly exists in order to abstract changes
on the underlying components away from this package. As such, it offers a number
of legacy APIs that are now deprecated and no longer in active use. These APIs
continue to work unchanged, but will be removed in a future version.

### SOCKS proxy

Expand All @@ -538,11 +487,11 @@ This works for both plain HTTP and SSL encrypted HTTPS requests.

See also the [SOCKS example](examples/11-socks-proxy.php).

### UNIX domain sockets
### Unix domain sockets

This library also supports connecting to a local UNIX domain socket path.
You have to explicitly create a [`Sender`](#sender) that passes every request through the
given UNIX domain socket.
This library also supports connecting to a local Unix domain socket (UDS) path.
You have to explicitly create a legacy [`Sender`](#sender) that passes every
request through the given UNIX domain socket.
For consistency reasons you still have to pass full HTTP URLs for every request,
but the host and port will be ignored when establishing a connection.

Expand Down
9 changes: 3 additions & 6 deletions examples/11-socks-proxy.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<?php

use Clue\React\Buzz\Io\Sender;
use Clue\React\Buzz\Browser;
use Clue\React\Socks\Client as SocksClient;
use Psr\Http\Message\ResponseInterface;
use React\EventLoop\Factory as LoopFactory;
use React\HttpClient\Client as HttpClient;
use React\Socket\Connector;
use RingCentral\Psr7;

Expand All @@ -18,12 +16,11 @@
$proxy = new SocksClient('127.0.0.1:1080', new Connector($loop));

// create a Browser object that uses the SOCKS client for connections
$client = new HttpClient($loop, new Connector($loop, array(
$connector = new Connector($loop, array(
'tcp' => $proxy,
'dns' => false
)));
$sender = new Sender($client);
$browser = new Browser($loop, $sender);
));
$browser = new Browser($loop, $connector);

// demo fetching HTTP headers (or bail out otherwise)
$browser->get('https://www.google.com/')->then(function (ResponseInterface $response) {
Expand Down
33 changes: 21 additions & 12 deletions src/Browser.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,41 @@

namespace Clue\React\Buzz;

use React\EventLoop\LoopInterface;
use Psr\Http\Message\RequestInterface;
use Clue\React\Buzz\Io\Transaction;
use Clue\React\Buzz\Message\Body;
use Clue\React\Buzz\Message\Headers;
use Clue\React\Buzz\Io\Sender;
use Psr\Http\Message\UriInterface;
use Clue\React\Buzz\Io\Transaction;
use Clue\React\Buzz\Message\MessageFactory;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\UriInterface;
use React\EventLoop\LoopInterface;
use React\Socket\ConnectorInterface;

class Browser
{
private $sender;
private $loop;
private $messageFactory;
private $baseUri = null;
private $options = array();

public function __construct(LoopInterface $loop, Sender $sender = null, MessageFactory $messageFactory = null)
/**
* Instantiate the Browser
*
* @param LoopInterface $loop
* @param ConnectorInterface|Sender|null $connector [optional] Connector to
* use. Should be `null` in order to use default Connector. Passing a
* Sender instance is deprecated and only supported for BC reasons and
* will be removed in future versions.
* @param MessageFactory $messageFactory [internal] Only used internally and
* will be removed in future versions.
*/
public function __construct(LoopInterface $loop, $connector = null, MessageFactory $messageFactory = null)
{
if ($sender === null) {
$sender = Sender::createFromLoop($loop);
if (!$connector instanceof Sender) {
$connector = Sender::createFromLoop($loop, $connector);
}
if ($messageFactory === null) {
$messageFactory = new MessageFactory();
}
$this->sender = $sender;
$this->loop = $loop;
$this->sender = $connector;
$this->messageFactory = $messageFactory;
}

Expand Down Expand Up @@ -135,6 +143,7 @@ public function withOptions(array $options)
return $browser;
}

/** @deprecated */
public function withSender(Sender $sender)
{
$browser = clone $this;
Expand Down
48 changes: 30 additions & 18 deletions src/Io/Sender.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,35 @@
use React\SocketClient\ConnectorInterface as LegacyConnectorInterface;
use React\Stream\ReadableStreamInterface;
use React\Socket\UnixConnector;
use React\Socket\ConnectorInterface;

/**
* @deprecated as of v1.4.0, see `Browser`
* @see Browser
*/
class Sender
{
/**
* create a new default sender attached to the given event loop
*
* This method is used internally to create the "default sender".
* If you need custom DNS or connector settings, you're recommended to
* explicitly create a HttpClient instance yourself and pass this to the
* constructor of this method manually like this:
*
* You may also use this method if you need custom DNS or connector
* settings. You can use this method manually like this:
*
* ```php
* $connector = new \React\Socket\Connector($loop);
* $client = new \React\HttpClient\Client($loop, $connector);
* $sender = new \Clue\React\Buzz\Io\Sender($client);
* $sender = \Clue\React\Buzz\Io\Sender::createFromLoop($loop, $connector);
* $browser = new \Clue\React\Buzz\Browser($loop, $sender);
* ```
*
* @param LoopInterface $loop
* @param ConnectorInterface|null $connector
* @return self
*/
public static function createFromLoop(LoopInterface $loop)
public static function createFromLoop(LoopInterface $loop, ConnectorInterface $connector = null)
{
return new self(new HttpClient($loop));
return new self(new HttpClient($loop, $connector));
}

/**
Expand All @@ -53,9 +58,9 @@ public static function createFromLoop(LoopInterface $loop)
*/
public static function createFromLoopDns(LoopInterface $loop, $dns)
{
return new self(new HttpClient($loop, new Connector($loop, array(
return self::createFromLoop($loop, new Connector($loop, array(
'dns' => $dns
))));
)));
}

/**
Expand All @@ -75,12 +80,12 @@ public static function createFromLoopConnectors(LoopInterface $loop, LegacyConne
}

// react/http v0.5 requires the new Socket-Connector, so we upcast from the legacy SocketClient-Connectors here
return new self(new HttpClient($loop, new Connector($loop, array(
return self::createFromLoop($loop, new Connector($loop, array(
'tcp' => new ConnectorUpcaster($connector),
'tls' => new ConnectorUpcaster($secureConnector),
'dns' => false,
'timeout' => false
))));
)));
}

/**
Expand All @@ -92,19 +97,26 @@ public static function createFromLoopConnectors(LoopInterface $loop, LegacyConne
*/
public static function createFromLoopUnix(LoopInterface $loop, $path)
{
return new self(
new HttpClient(
$loop,
new FixedUriConnector(
$path,
new UnixConnector($loop)
)
return self::createFromLoop(
$loop,
new FixedUriConnector(
$path,
new UnixConnector($loop)
)
);
}

private $http;

/**
* [deprecated] Instantiate Sender
*
* @param HttpClient $http
* @deprecated explicitly calling this constructor is deprecated and it
* will be removed in a future version! Please use the above static
* `create*()` methods instead for future compatibility
* @see self::createFromLoop()
*/
public function __construct(HttpClient $http)
{
$this->http = $http;
Expand Down