diff options
-rw-r--r-- | _test/tests/inc/httpclient_http_proxy.test.php | 20 | ||||
-rw-r--r-- | _test/tests/inc/httpclient_https.test.php | 1 | ||||
-rw-r--r-- | _test/tests/inc/httpclient_https_proxy.test.php | 15 | ||||
-rw-r--r-- | inc/HTTPClient.php | 66 |
4 files changed, 97 insertions, 5 deletions
diff --git a/_test/tests/inc/httpclient_http_proxy.test.php b/_test/tests/inc/httpclient_http_proxy.test.php new file mode 100644 index 000000000..faa7a4280 --- /dev/null +++ b/_test/tests/inc/httpclient_http_proxy.test.php @@ -0,0 +1,20 @@ +<?php + +class httpclient_http_proxy_test extends DokuWikiTest { + protected $url = 'http://www.dokuwiki.org/README'; + + /** + * @group internet + */ + function test_simpleget(){ + $http = new HTTPClient(); + // proxy provided by Andrwe Lord Weber <dokuwiki@andrwe.org> + $http->proxy_host = 'proxy.andrwe.org'; + $http->proxy_port = 8080; + + $data = $http->get($this->url); + $this->assertFalse($data === false, 'HTTP response'); + $this->assertTrue(strpos($data,'DokuWiki') !== false, 'response content'); + } + +}
\ No newline at end of file diff --git a/_test/tests/inc/httpclient_https.test.php b/_test/tests/inc/httpclient_https.test.php index 26a0f86db..955d467ec 100644 --- a/_test/tests/inc/httpclient_https.test.php +++ b/_test/tests/inc/httpclient_https.test.php @@ -1,4 +1,5 @@ <?php +require_once dirname(__FILE__).'/httpclient_http.test.php'; class httpclient_https_test extends httpclient_http_test { protected $server = 'https://httpbin.org/'; diff --git a/_test/tests/inc/httpclient_https_proxy.test.php b/_test/tests/inc/httpclient_https_proxy.test.php new file mode 100644 index 000000000..aca3b3be2 --- /dev/null +++ b/_test/tests/inc/httpclient_https_proxy.test.php @@ -0,0 +1,15 @@ +<?php +require_once dirname(__FILE__).'/httpclient_http_proxy.test.php'; + +class httpclient_https_proxy_test extends httpclient_http_proxy_test { + protected $url = 'https://www.dokuwiki.org/README'; + + public function setUp(){ + // skip tests when this PHP has no SSL support + $transports = stream_get_transports(); + if(!in_array('ssl',$transports)){ + $this->markTestSkipped('No SSL support available.'); + } + parent::setUp(); + } +}
\ No newline at end of file diff --git a/inc/HTTPClient.php b/inc/HTTPClient.php index c4cfcbf7c..51c1de875 100644 --- a/inc/HTTPClient.php +++ b/inc/HTTPClient.php @@ -254,11 +254,7 @@ class HTTPClient { if(!empty($uri['port'])) $headers['Host'].= ':'.$uri['port']; $headers['User-Agent'] = $this->agent; $headers['Referer'] = $this->referer; - if ($this->keep_alive) { - $headers['Connection'] = 'Keep-Alive'; - } else { - $headers['Connection'] = 'Close'; - } + if($method == 'POST'){ if(is_array($data)){ if($headers['Content-Type'] == 'multipart/form-data'){ @@ -299,6 +295,14 @@ class HTTPClient { return false; } + // try establish a CONNECT tunnel for SSL + if($this->_ssltunnel($socket, $request_url)){ + // no keep alive for tunnels + $this->keep_alive = false; + // tunnel is authed already + if(isset($headers['Proxy-Authentication'])) unset($headers['Proxy-Authentication']); + } + // keep alive? if ($this->keep_alive) { self::$connections[$connectionId] = $socket; @@ -307,6 +311,15 @@ class HTTPClient { } } + if ($this->keep_alive && !$this->proxy_host) { + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive + // connection token to a proxy server. We still do keep the connection the + // proxy alive (well except for CONNECT tunnels) + $headers['Connection'] = 'Keep-Alive'; + } else { + $headers['Connection'] = 'Close'; + } + try { //set non-blocking stream_set_blocking($socket, false); @@ -485,6 +498,49 @@ class HTTPClient { } /** + * Tries to establish a CONNECT tunnel via Proxy + * + * Protocol, Servername and Port will be stripped from the request URL when a successful CONNECT happened + * + * @param ressource &$socket + * @param string &$requesturl + * @return bool true if a tunnel was established + */ + function _ssltunnel(&$socket, &$requesturl){ + if(!$this->proxy_host) return false; + $requestinfo = parse_url($requesturl); + if($requestinfo['scheme'] != 'https') return false; + if(!$requestinfo['port']) $requestinfo['port'] = 443; + + // build request + $request = "CONNECT {$requestinfo['host']}:{$requestinfo['port']} HTTP/1.0".HTTP_NL; + $request .= "Host: {$requestinfo['host']}".HTTP_NL; + if($this->proxy_user) { + 'Proxy-Authorization Basic '.base64_encode($this->proxy_user.':'.$this->proxy_pass).HTTP_NL; + } + $request .= HTTP_NL; + + $this->_debug('SSL Tunnel CONNECT',$request); + $this->_sendData($socket, $request, 'SSL Tunnel CONNECT'); + + // read headers from socket + $r_headers = ''; + do{ + $r_line = $this->_readLine($socket, 'headers'); + $r_headers .= $r_line; + }while($r_line != "\r\n" && $r_line != "\n"); + + $this->_debug('SSL Tunnel Response',$r_headers); + if(preg_match('/^HTTP\/1\.0 200/i',$r_headers)){ + if (stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT)) { + $requesturl = $requestinfo['path']; + return true; + } + } + return false; + } + + /** * Safely write data to a socket * * @param handle $socket An open socket handle |