@@ -9,6 +9,11 @@ Async HTTP CONNECT proxy connector, use any TCP/IP protocol through an HTTP prox
99 * [ ConnectorInterface] ( #connectorinterface )
1010 * [ connect()] ( #connect )
1111 * [ ProxyConnector] ( #proxyconnector )
12+ * [ Plain TCP connections] ( #plain-tcp-connections )
13+ * [ Secure TLS connections] ( #secure-tls-connections )
14+ * [ Connection timeout] ( #connection-timeout )
15+ * [ DNS resolution] ( #dns-resolution )
16+ * [ Advanced secure proxy connections] ( #advanced-secure-proxy-connections )
1217* [ Install] ( #install )
1318* [ Tests] ( #tests )
1419* [ License] ( #license )
@@ -21,11 +26,15 @@ secure HTTPS request to google.com through a local HTTP proxy server:
2126
2227``` php
2328$loop = React\EventLoop\Factory::create();
24- $connector = new TcpConnector($loop);
25- $proxy = new ProxyConnector('127.0.0.1:8080', $connector);
26- $ssl = new SecureConnector($proxy, $loop);
2729
28- $ssl->connect('google.com:443')->then(function (ConnectionInterface $stream) {
30+ $proxy = new ProxyConnector('127.0.0.1:8080', new Connector($loop));
31+ $connector = new Connector($loop, array(
32+ 'tcp' => $proxy,
33+ 'timeout' => 3.0,
34+ 'dns' => false
35+ ));
36+
37+ $connector->connect('tls://google.com:443')->then(function (ConnectionInterface $stream) {
2938 $stream->write("GET / HTTP/1.1\r\nHost: google.com\r\nConnection: close\r\n\r\n");
3039 $stream->on('data', function ($chunk) {
3140 echo $chunk;
@@ -91,15 +100,15 @@ Its constructor simply accepts an HTTP proxy URL and a connector used to connect
91100to the proxy server address:
92101
93102``` php
94- $connector = new TcpConnector ($loop);
103+ $connector = new Connector ($loop);
95104$proxy = new ProxyConnector('127.0.0.1:8080', $connector);
96105```
97106
98107The proxy URL may or may not contain a scheme and port definition. The default
99108port will be ` 80 ` for HTTP (or ` 443 ` for HTTPS), but many common HTTP proxy
100109servers use custom ports.
101110In its most simple form, the given connector will be a
102- [ ` TcpConnector ` ] ( https://github.com/reactphp/socket#tcpconnector ) if you
111+ [ ` \React\Socket\Connector ` ] ( https://github.com/reactphp/socket#connector ) if you
103112want to connect to a given IP address as above.
104113
105114This is the main class in this package.
@@ -114,14 +123,36 @@ higher-level component:
114123+ $client = new SomeClient($proxy);
115124```
116125
126+ #### Plain TCP connections
127+
117128This is most frequently used to issue HTTPS requests to your destination.
118129However, this is actually performed on a higher protocol layer and this
119- connector is actually inherently a general-purpose plain TCP/IP connector:
130+ connector is actually inherently a general-purpose plain TCP/IP connector.
131+
132+ The ` ProxyConnector ` implements the [ ` ConnectorInterface ` ] ( #connectorinterface ) and
133+ hence provides a single public method, the [ ` connect() ` ] ( #connect ) method.
120134
121135``` php
122136$proxy = new ProxyConnector('127.0.0.1:8080', $connector);
123137
124- $proxy->connect('smtp.googlemail.com:587')->then(function (ConnectionInterface $stream) {
138+ $proxy->connect('tcp://smtp.googlemail.com:587')->then(function (ConnectionInterface $stream) {
139+ $stream->write("EHLO local\r\n");
140+ $stream->on('data', function ($chunk) use ($stream) {
141+ echo $chunk;
142+ });
143+ });
144+ ```
145+
146+ You can either use the ` ProxyConnector ` directly or you may want to wrap this connector
147+ in React's [ ` Connector ` ] ( https://github.com/reactphp/socket#connector ) :
148+
149+ ``` php
150+ $connector = new Connector($loop, array(
151+ 'tcp' => $proxy,
152+ 'dns' => false
153+ ));
154+
155+ $connector->connect('tcp://smtp.googlemail.com:587')->then(function (ConnectionInterface $stream) {
125156 $stream->write("EHLO local\r\n");
126157 $stream->on('data', function ($chunk) use ($stream) {
127158 echo $chunk;
@@ -132,23 +163,112 @@ $proxy->connect('smtp.googlemail.com:587')->then(function (ConnectionInterface $
132163Note that HTTP CONNECT proxies often restrict which ports one may connect to.
133164Many (public) proxy servers do in fact limit this to HTTPS (443) only.
134165
166+ #### Secure TLS connections
167+
135168If you want to establish a TLS connection (such as HTTPS) between you and
136- your destination, you may want to wrap this connector in a
137- [ ` SecureConnector ` ] ( https://github.com/reactphp/socket#secureconnector )
138- instance :
169+ your destination, you may want to wrap this connector in React's
170+ [ ` Connector ` ] ( https://github.com/reactphp/socket#connector ) or the low-level
171+ [ ` SecureConnector ` ] ( https://github.com/reactphp/socket#secureconnector ) :
139172
140173``` php
141174$proxy = new ProxyConnector('127.0.0.1:8080', $connector);
142- $ssl = new SecureConnector($proxy, $loop);
175+ $connector = new Connector($loop, array(
176+ 'tcp' => $proxy,
177+ 'dns' => false
178+ ));
143179
144- $ssl ->connect('smtp.googlemail.com:465')->then(function (ConnectionInterface $stream) {
180+ $connector ->connect('tls:// smtp.googlemail.com:465')->then(function (ConnectionInterface $stream) {
145181 $stream->write("EHLO local\r\n");
146182 $stream->on('data', function ($chunk) use ($stream) {
147183 echo $chunk;
148184 });
149185});
150186```
151187
188+ > Also note how secure TLS connections are in fact entirely handled outside of
189+ this HTTP CONNECT client implementation.
190+
191+ #### Connection timeout
192+
193+ By default, the ` ProxyConnector ` does not implement any timeouts for establishing remote
194+ connections.
195+ Your underlying operating system may impose limits on pending and/or idle TCP/IP
196+ connections, anywhere in a range of a few minutes to several hours.
197+
198+ Many use cases require more control over the timeout and likely values much
199+ smaller, usually in the range of a few seconds only.
200+
201+ You can use React's [ ` Connector ` ] ( https://github.com/reactphp/socket#connector )
202+ or the low-level
203+ [ ` TimeoutConnector ` ] ( https://github.com/reactphp/socket#timeoutconnector )
204+ to decorate any given ` ConnectorInterface ` instance.
205+ It provides the same ` connect() ` method, but will automatically reject the
206+ underlying connection attempt if it takes too long:
207+
208+ ``` php
209+ $connector = new Connector($loop, array(
210+ 'tcp' => $proxy,
211+ 'dns' => false,
212+ 'timeout' => 3.0
213+ ));
214+
215+ $connector->connect('tcp://google.com:80')->then(function ($stream) {
216+ // connection succeeded within 3.0 seconds
217+ });
218+ ```
219+
220+ See also any of the [ examples] ( examples ) .
221+
222+ > Also note how connection timeout is in fact entirely handled outside of this
223+ HTTP CONNECT client implementation.
224+
225+ #### DNS resolution
226+
227+ By default, the ` ProxyConnector ` does not perform any DNS resolution at all and simply
228+ forwards any hostname you're trying to connect to the remote proxy server.
229+ The remote proxy server is thus responsible for looking up any hostnames via DNS
230+ (this default mode is thus called * remote DNS resolution* ).
231+
232+ As an alternative, you can also send the destination IP to the remote proxy
233+ server.
234+ In this mode you either have to stick to using IPs only (which is ofen unfeasable)
235+ or perform any DNS lookups locally and only transmit the resolved destination IPs
236+ (this mode is thus called * local DNS resolution* ).
237+
238+ The default * remote DNS resolution* is useful if your local ` ProxyConnector ` either can
239+ not resolve target hostnames because it has no direct access to the internet or
240+ if it should not resolve target hostnames because its outgoing DNS traffic might
241+ be intercepted.
242+
243+ As noted above, the ` ProxyConnector ` defaults to using remote DNS resolution.
244+ However, wrapping the ` ProxyConnector ` in React's
245+ [ ` Connector ` ] ( https://github.com/reactphp/socket#connector ) actually
246+ performs local DNS resolution unless explicitly defined otherwise.
247+ Given that remote DNS resolution is assumed to be the preferred mode, all
248+ other examples explicitly disable DNS resoltion like this:
249+
250+ ``` php
251+ $connector = new Connector($loop, array(
252+ 'tcp' => $proxy,
253+ 'dns' => false
254+ ));
255+ ```
256+
257+ If you want to explicitly use * local DNS resolution* , you can use the following code:
258+
259+ ``` php
260+ // set up Connector which uses Google's public DNS (8.8.8.8)
261+ $connector = Connector($loop, array(
262+ 'tcp' => $proxy,
263+ 'dns' => '8.8.8.8'
264+ ));
265+ ```
266+
267+ > Also note how local DNS resolution is in fact entirely handled outside of this
268+ HTTP CONNECT client implementation.
269+
270+ #### Advanced secure proxy connections
271+
152272Note that communication between the client and the proxy is usually via an
153273unencrypted, plain TCP/IP HTTP connection. Note that this is the most common
154274setup, because you can still establish a TLS connection between you and the
0 commit comments