diff --git a/README.md b/README.md index b9491ef..dc4151e 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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 @@ -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 @@ -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. @@ -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 @@ -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. diff --git a/examples/11-socks-proxy.php b/examples/11-socks-proxy.php index 993a4de..ec49f1b 100644 --- a/examples/11-socks-proxy.php +++ b/examples/11-socks-proxy.php @@ -1,11 +1,9 @@ $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) { diff --git a/src/Browser.php b/src/Browser.php index 163cbde..d388d47 100644 --- a/src/Browser.php +++ b/src/Browser.php @@ -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; } @@ -135,6 +143,7 @@ public function withOptions(array $options) return $browser; } + /** @deprecated */ public function withSender(Sender $sender) { $browser = clone $this; diff --git a/src/Io/Sender.php b/src/Io/Sender.php index 15e10c5..71d2e7e 100644 --- a/src/Io/Sender.php +++ b/src/Io/Sender.php @@ -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)); } /** @@ -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 - )))); + ))); } /** @@ -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 - )))); + ))); } /** @@ -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;