2008-05-30 11:40:08 +00:00
< ? php
/**
* HTTP Socket connection class .
*
2017-06-10 21:33:55 +00:00
* CakePHP ( tm ) : Rapid Development Framework ( https :// cakephp . org )
2017-06-10 22:10:52 +00:00
* Copyright ( c ) Cake Software Foundation , Inc . ( https :// cakefoundation . org )
2008-05-30 11:40:08 +00:00
*
* Licensed under The MIT License
2013-02-08 12:22:51 +00:00
* For full copyright and license information , please see the LICENSE . txt
2008-05-30 11:40:08 +00:00
* Redistributions of files must retain the above copyright notice .
*
2017-06-10 22:10:52 +00:00
* @ copyright Copyright ( c ) Cake Software Foundation , Inc . ( https :// cakefoundation . org )
2017-06-10 21:33:55 +00:00
* @ link https :// cakephp . org CakePHP ( tm ) Project
2011-07-26 06:16:14 +00:00
* @ package Cake . Network . Http
2008-10-30 17:30:26 +00:00
* @ since CakePHP ( tm ) v 1.2 . 0
2017-06-10 22:23:14 +00:00
* @ license https :// opensource . org / licenses / mit - license . php MIT License
2008-05-30 11:40:08 +00:00
*/
2013-05-30 22:11:14 +00:00
2010-12-15 05:50:02 +00:00
App :: uses ( 'CakeSocket' , 'Network' );
2010-12-11 05:47:55 +00:00
App :: uses ( 'Router' , 'Routing' );
2012-11-11 19:23:17 +00:00
App :: uses ( 'Hash' , 'Utility' );
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2013-10-09 23:38:16 +00:00
* CakePHP network socket connection class .
2008-05-30 11:40:08 +00:00
*
2010-01-25 16:01:05 +00:00
* Core base class for HTTP network communication . HttpSocket can be used as an
* Object Oriented replacement for cURL in many places .
2008-05-30 11:40:08 +00:00
*
2011-07-26 06:16:14 +00:00
* @ package Cake . Network . Http
2008-05-30 11:40:08 +00:00
*/
class HttpSocket extends CakeSocket {
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2009-05-07 18:49:21 +00:00
* When one activates the $quirksMode by setting it to true , all checks meant to
* enforce RFC 2616 ( HTTP / 1.1 specs ) .
2008-05-30 11:40:08 +00:00
* will be disabled and additional measures to deal with non - standard responses will be enabled .
*
2014-07-03 13:36:42 +00:00
* @ var bool
2008-05-30 11:40:08 +00:00
*/
2010-04-04 07:14:00 +00:00
public $quirksMode = false ;
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2010-12-06 14:04:00 +00:00
* Contain information about the last request ( read only )
2008-05-30 11:40:08 +00:00
*
* @ var array
*/
2010-04-04 07:14:00 +00:00
public $request = array (
2008-05-30 11:40:08 +00:00
'method' => 'GET' ,
'uri' => array (
'scheme' => 'http' ,
'host' => null ,
'port' => 80 ,
'user' => null ,
'pass' => null ,
'path' => null ,
'query' => null ,
'fragment' => null
),
'version' => '1.1' ,
'body' => '' ,
'line' => null ,
'header' => array (
'Connection' => 'close' ,
'User-Agent' => 'CakePHP'
),
'raw' => null ,
2011-11-13 16:45:33 +00:00
'redirect' => false ,
2012-11-11 19:23:17 +00:00
'cookies' => array (),
2008-05-30 11:40:08 +00:00
);
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2010-12-06 14:04:00 +00:00
* Contain information about the last response ( read only )
2010-12-04 02:58:49 +00:00
*
* @ var array
2015-10-17 02:09:12 +00:00
*/
2010-12-14 03:07:25 +00:00
public $response = null ;
2009-07-24 19:18:37 +00:00
2010-12-14 04:46:31 +00:00
/**
2013-10-23 02:59:50 +00:00
* Response class name
2010-12-14 04:46:31 +00:00
*
* @ var string
*/
2012-11-11 02:41:24 +00:00
public $responseClass = 'HttpSocketResponse' ;
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2010-12-06 14:04:00 +00:00
* Configuration settings for the HttpSocket and the requests
2008-05-30 11:40:08 +00:00
*
* @ var array
*/
2010-04-04 07:14:00 +00:00
public $config = array (
2008-05-30 11:40:08 +00:00
'persistent' => false ,
2010-01-25 16:01:05 +00:00
'host' => 'localhost' ,
'protocol' => 'tcp' ,
'port' => 80 ,
'timeout' => 30 ,
2012-11-11 19:23:17 +00:00
'ssl_verify_peer' => true ,
2013-05-30 13:06:10 +00:00
'ssl_allow_self_signed' => false ,
2012-11-11 19:23:17 +00:00
'ssl_verify_depth' => 5 ,
'ssl_verify_host' => true ,
2008-05-30 11:40:08 +00:00
'request' => array (
'uri' => array (
2012-02-02 02:10:56 +00:00
'scheme' => array ( 'http' , 'https' ),
2008-05-30 11:40:08 +00:00
'host' => 'localhost' ,
2012-02-02 02:10:56 +00:00
'port' => array ( 80 , 443 )
2008-05-30 11:40:08 +00:00
),
2011-11-13 16:45:33 +00:00
'redirect' => false ,
2012-11-11 19:23:17 +00:00
'cookies' => array (),
2008-05-30 11:40:08 +00:00
)
);
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2010-12-03 02:46:11 +00:00
* Authentication settings
2008-05-30 11:40:08 +00:00
*
2010-12-03 02:46:11 +00:00
* @ var array
*/
protected $_auth = array ();
2010-12-04 01:10:07 +00:00
/**
* Proxy settings
*
* @ var array
*/
protected $_proxy = array ();
2010-12-10 14:08:49 +00:00
/**
* Resource to receive the content of request
*
* @ var mixed
2008-05-30 11:40:08 +00:00
*/
2010-12-10 14:08:49 +00:00
protected $_contentResource = null ;
2008-05-30 11:40:08 +00:00
/**
* Build an HTTP Socket using the specified configuration .
*
2013-10-22 04:09:34 +00:00
* You can use a URL string to set the URL and use default configurations for
2010-01-25 16:01:05 +00:00
* all other options :
*
2017-06-10 21:33:55 +00:00
* `$http = new HttpSocket('https://cakephp.org/');`
2010-01-25 16:01:05 +00:00
*
* Or use an array to configure multiple options :
*
2015-01-09 12:47:25 +00:00
* `` `
2010-11-13 04:05:44 +00:00
* $http = new HttpSocket ( array (
2010-01-25 16:01:05 +00:00
* 'host' => 'cakephp.org' ,
* 'timeout' => 20
* ));
2015-01-09 12:47:25 +00:00
* `` `
2010-01-25 16:01:05 +00:00
*
* See HttpSocket :: $config for options that can be used .
*
2013-04-29 09:05:17 +00:00
* @ param string | array $config Configuration information , either a string URL or an array of options .
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:19:38 +00:00
public function __construct ( $config = array ()) {
2008-05-30 11:40:08 +00:00
if ( is_string ( $config )) {
2009-05-07 18:49:21 +00:00
$this -> _configUri ( $config );
2008-05-30 11:40:08 +00:00
} elseif ( is_array ( $config )) {
if ( isset ( $config [ 'request' ][ 'uri' ]) && is_string ( $config [ 'request' ][ 'uri' ])) {
2009-05-07 18:49:21 +00:00
$this -> _configUri ( $config [ 'request' ][ 'uri' ]);
2008-05-30 11:40:08 +00:00
unset ( $config [ 'request' ][ 'uri' ]);
}
2012-03-11 01:57:18 +00:00
$this -> config = Hash :: merge ( $this -> config , $config );
2008-05-30 11:40:08 +00:00
}
parent :: __construct ( $this -> config );
}
2009-07-24 19:18:37 +00:00
2010-12-03 02:46:11 +00:00
/**
2011-12-04 18:45:53 +00:00
* Set authentication settings .
*
2012-12-22 22:48:15 +00:00
* Accepts two forms of parameters . If all you need is a username + password , as with
2011-12-04 18:45:53 +00:00
* Basic authentication you can do the following :
*
2015-01-09 12:47:25 +00:00
* `` `
2011-12-04 18:45:53 +00:00
* $http -> configAuth ( 'Basic' , 'mark' , 'secret' );
2015-01-09 12:47:25 +00:00
* `` `
2011-12-04 18:45:53 +00:00
*
* If you are using an authentication strategy that requires more inputs , like Digest authentication
* you can call `configAuth()` with an array of user information .
*
2015-01-09 12:47:25 +00:00
* `` `
2011-12-04 18:45:53 +00:00
* $http -> configAuth ( 'Digest' , array (
* 'user' => 'mark' ,
* 'pass' => 'secret' ,
* 'realm' => 'my-realm' ,
* 'nonce' => 1235
* ));
2015-01-09 12:47:25 +00:00
* `` `
2011-12-04 18:45:53 +00:00
*
* To remove any set authentication strategy , call `configAuth()` with no parameters :
*
* `$http->configAuth();`
2010-12-03 02:46:11 +00:00
*
2010-12-04 01:10:07 +00:00
* @ param string $method Authentication method ( ie . Basic , Digest ) . If empty , disable authentication
2012-05-13 00:43:31 +00:00
* @ param string | array $user Username for authentication . Can be an array with settings to authentication class
2010-12-03 02:46:11 +00:00
* @ param string $pass Password for authentication
* @ return void
*/
2010-12-13 01:48:04 +00:00
public function configAuth ( $method , $user = null , $pass = null ) {
2010-12-03 02:46:11 +00:00
if ( empty ( $method )) {
$this -> _auth = array ();
return ;
}
if ( is_array ( $user )) {
$this -> _auth = array ( $method => $user );
return ;
}
$this -> _auth = array ( $method => compact ( 'user' , 'pass' ));
}
2010-12-04 01:10:07 +00:00
/**
* Set proxy settings
*
2012-05-13 00:43:31 +00:00
* @ param string | array $host Proxy host . Can be an array with settings to authentication class
2014-07-03 13:36:42 +00:00
* @ param int $port Port . Default 3128.
2010-12-04 01:10:07 +00:00
* @ param string $method Proxy method ( ie , Basic , Digest ) . If empty , disable proxy authentication
* @ param string $user Username if your proxy need authentication
* @ param string $pass Password to proxy authentication
* @ return void
*/
2010-12-13 01:48:04 +00:00
public function configProxy ( $host , $port = 3128 , $method = null , $user = null , $pass = null ) {
2010-12-04 01:10:07 +00:00
if ( empty ( $host )) {
$this -> _proxy = array ();
return ;
}
if ( is_array ( $host )) {
$this -> _proxy = $host + array ( 'host' => null );
return ;
}
$this -> _proxy = compact ( 'host' , 'port' , 'method' , 'user' , 'pass' );
}
2010-12-10 14:08:49 +00:00
/**
* Set the resource to receive the request content . This resource must support fwrite .
*
2014-07-03 13:36:42 +00:00
* @ param resource | bool $resource Resource or false to disable the resource use
2010-12-10 14:08:49 +00:00
* @ return void
2011-07-31 20:55:52 +00:00
* @ throws SocketException
2010-12-10 14:08:49 +00:00
*/
public function setContentResource ( $resource ) {
if ( $resource === false ) {
$this -> _contentResource = null ;
return ;
}
if ( ! is_resource ( $resource )) {
2011-03-20 15:35:43 +00:00
throw new SocketException ( __d ( 'cake_dev' , 'Invalid resource.' ));
2010-12-10 14:08:49 +00:00
}
$this -> _contentResource = $resource ;
}
2008-05-30 11:40:08 +00:00
/**
2010-01-25 16:01:05 +00:00
* Issue the specified request . HttpSocket :: get () and HttpSocket :: post () wrap this
* method and provide a more granular interface .
2008-05-30 11:40:08 +00:00
*
2012-05-13 00:43:31 +00:00
* @ param string | array $request Either an URI string , or an array defining host / uri
2018-12-28 13:19:26 +00:00
* @ return false | HttpSocketResponse false on error , HttpSocketResponse on success
2011-07-31 20:55:52 +00:00
* @ throws SocketException
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:19:38 +00:00
public function request ( $request = array ()) {
2008-05-30 11:40:08 +00:00
$this -> reset ( false );
if ( is_string ( $request )) {
$request = array ( 'uri' => $request );
} elseif ( ! is_array ( $request )) {
return false ;
}
if ( ! isset ( $request [ 'uri' ])) {
$request [ 'uri' ] = null ;
}
2009-05-07 18:49:21 +00:00
$uri = $this -> _parseUri ( $request [ 'uri' ]);
2008-05-30 11:40:08 +00:00
if ( ! isset ( $uri [ 'host' ])) {
$host = $this -> config [ 'host' ];
}
if ( isset ( $request [ 'host' ])) {
$host = $request [ 'host' ];
unset ( $request [ 'host' ]);
}
$request [ 'uri' ] = $this -> url ( $request [ 'uri' ]);
2009-05-07 18:49:21 +00:00
$request [ 'uri' ] = $this -> _parseUri ( $request [ 'uri' ], true );
2012-03-11 01:57:18 +00:00
$this -> request = Hash :: merge ( $this -> request , array_diff_key ( $this -> config [ 'request' ], array ( 'cookies' => true )), $request );
2008-05-30 11:40:08 +00:00
2009-05-07 18:49:21 +00:00
$this -> _configUri ( $this -> request [ 'uri' ]);
2008-05-30 11:40:08 +00:00
2010-12-11 18:49:19 +00:00
$Host = $this -> request [ 'uri' ][ 'host' ];
if ( ! empty ( $this -> config [ 'request' ][ 'cookies' ][ $Host ])) {
if ( ! isset ( $this -> request [ 'cookies' ])) {
$this -> request [ 'cookies' ] = array ();
}
if ( ! isset ( $request [ 'cookies' ])) {
$request [ 'cookies' ] = array ();
}
$this -> request [ 'cookies' ] = array_merge ( $this -> request [ 'cookies' ], $this -> config [ 'request' ][ 'cookies' ][ $Host ], $request [ 'cookies' ]);
}
2008-05-30 11:40:08 +00:00
if ( isset ( $host )) {
$this -> config [ 'host' ] = $host ;
}
2014-06-12 00:04:58 +00:00
2010-12-06 13:28:40 +00:00
$this -> _setProxy ();
2010-12-10 12:38:49 +00:00
$this -> request [ 'proxy' ] = $this -> _proxy ;
2008-05-30 11:40:08 +00:00
$cookies = null ;
if ( is_array ( $this -> request [ 'header' ])) {
if ( ! empty ( $this -> request [ 'cookies' ])) {
$cookies = $this -> buildCookies ( $this -> request [ 'cookies' ]);
}
2011-12-06 13:59:51 +00:00
$scheme = '' ;
2010-07-23 03:13:19 +00:00
$port = 0 ;
2011-12-06 13:59:51 +00:00
if ( isset ( $this -> request [ 'uri' ][ 'scheme' ])) {
$scheme = $this -> request [ 'uri' ][ 'scheme' ];
2010-07-23 03:13:19 +00:00
}
if ( isset ( $this -> request [ 'uri' ][ 'port' ])) {
$port = $this -> request [ 'uri' ][ 'port' ];
}
2014-12-09 02:17:35 +00:00
if (( $scheme === 'http' && $port != 80 ) ||
2011-12-06 13:59:51 +00:00
( $scheme === 'https' && $port != 443 ) ||
2010-07-23 03:13:19 +00:00
( $port != 80 && $port != 443 )
) {
$Host .= ':' . $port ;
}
$this -> request [ 'header' ] = array_merge ( compact ( 'Host' ), $this -> request [ 'header' ]);
2008-05-30 11:40:08 +00:00
}
2010-12-03 02:46:11 +00:00
if ( isset ( $this -> request [ 'uri' ][ 'user' ], $this -> request [ 'uri' ][ 'pass' ])) {
2010-12-13 01:48:04 +00:00
$this -> configAuth ( 'Basic' , $this -> request [ 'uri' ][ 'user' ], $this -> request [ 'uri' ][ 'pass' ]);
2013-03-28 03:11:16 +00:00
} elseif ( isset ( $this -> request [ 'auth' ], $this -> request [ 'auth' ][ 'method' ], $this -> request [ 'auth' ][ 'user' ], $this -> request [ 'auth' ][ 'pass' ])) {
$this -> configAuth ( $this -> request [ 'auth' ][ 'method' ], $this -> request [ 'auth' ][ 'user' ], $this -> request [ 'auth' ][ 'pass' ]);
2008-05-30 11:40:08 +00:00
}
2014-08-21 16:19:25 +00:00
$authHeader = Hash :: get ( $this -> request , 'header.Authorization' );
if ( empty ( $authHeader )) {
$this -> _setAuth ();
$this -> request [ 'auth' ] = $this -> _auth ;
}
2008-05-30 11:40:08 +00:00
if ( is_array ( $this -> request [ 'body' ])) {
2013-03-14 00:22:50 +00:00
$this -> request [ 'body' ] = http_build_query ( $this -> request [ 'body' ], '' , '&' );
2008-05-30 11:40:08 +00:00
}
if ( ! empty ( $this -> request [ 'body' ]) && ! isset ( $this -> request [ 'header' ][ 'Content-Type' ])) {
$this -> request [ 'header' ][ 'Content-Type' ] = 'application/x-www-form-urlencoded' ;
}
if ( ! empty ( $this -> request [ 'body' ]) && ! isset ( $this -> request [ 'header' ][ 'Content-Length' ])) {
$this -> request [ 'header' ][ 'Content-Length' ] = strlen ( $this -> request [ 'body' ]);
}
2014-06-12 14:37:03 +00:00
if ( isset ( $this -> request [ 'uri' ][ 'scheme' ]) && $this -> request [ 'uri' ][ 'scheme' ] === 'https' && in_array ( $this -> config [ 'protocol' ], array ( false , 'tcp' ))) {
2014-06-12 13:47:40 +00:00
$this -> config [ 'protocol' ] = 'ssl' ;
2014-06-12 00:04:58 +00:00
}
2008-05-30 11:40:08 +00:00
2009-07-15 19:15:14 +00:00
$connectionType = null ;
if ( isset ( $this -> request [ 'header' ][ 'Connection' ])) {
$connectionType = $this -> request [ 'header' ][ 'Connection' ];
}
2009-07-20 16:31:56 +00:00
$this -> request [ 'header' ] = $this -> _buildHeader ( $this -> request [ 'header' ]) . $cookies ;
2008-05-30 11:40:08 +00:00
if ( empty ( $this -> request [ 'line' ])) {
2009-05-07 18:49:21 +00:00
$this -> request [ 'line' ] = $this -> _buildRequestLine ( $this -> request );
2008-05-30 11:40:08 +00:00
}
if ( $this -> quirksMode === false && $this -> request [ 'line' ] === false ) {
2010-12-14 03:07:25 +00:00
return false ;
2008-05-30 11:40:08 +00:00
}
2010-12-06 05:23:09 +00:00
$this -> request [ 'raw' ] = '' ;
2008-05-30 11:40:08 +00:00
if ( $this -> request [ 'line' ] !== false ) {
$this -> request [ 'raw' ] = $this -> request [ 'line' ];
}
if ( $this -> request [ 'header' ] !== false ) {
$this -> request [ 'raw' ] .= $this -> request [ 'header' ];
}
$this -> request [ 'raw' ] .= " \r \n " ;
$this -> request [ 'raw' ] .= $this -> request [ 'body' ];
2015-10-13 01:56:20 +00:00
// SSL context is set during the connect() method.
2008-05-30 11:40:08 +00:00
$this -> write ( $this -> request [ 'raw' ]);
$response = null ;
2010-12-10 14:08:49 +00:00
$inHeader = true ;
2015-07-28 02:12:25 +00:00
while (( $data = $this -> read ()) !== false ) {
2010-12-10 14:08:49 +00:00
if ( $this -> _contentResource ) {
if ( $inHeader ) {
$response .= $data ;
$pos = strpos ( $response , " \r \n \r \n " );
if ( $pos !== false ) {
$pos += 4 ;
$data = substr ( $response , $pos );
fwrite ( $this -> _contentResource , $data );
$response = substr ( $response , 0 , $pos );
$inHeader = false ;
}
} else {
fwrite ( $this -> _contentResource , $data );
fflush ( $this -> _contentResource );
}
} else {
$response .= $data ;
}
2008-05-30 11:40:08 +00:00
}
2010-12-06 14:03:22 +00:00
if ( $connectionType === 'close' ) {
2008-05-30 11:40:08 +00:00
$this -> disconnect ();
}
2011-04-10 21:27:44 +00:00
list ( $plugin , $responseClass ) = pluginSplit ( $this -> responseClass , true );
2012-04-07 00:38:14 +00:00
App :: uses ( $responseClass , $plugin . 'Network/Http' );
2011-04-10 21:27:44 +00:00
if ( ! class_exists ( $responseClass )) {
2011-03-20 15:35:43 +00:00
throw new SocketException ( __d ( 'cake_dev' , 'Class %s not found.' , $this -> responseClass ));
2010-12-14 04:46:31 +00:00
}
$this -> response = new $responseClass ( $response );
2012-11-11 19:23:17 +00:00
2010-12-14 03:07:25 +00:00
if ( ! empty ( $this -> response -> cookies )) {
2010-12-11 18:49:19 +00:00
if ( ! isset ( $this -> config [ 'request' ][ 'cookies' ][ $Host ])) {
$this -> config [ 'request' ][ 'cookies' ][ $Host ] = array ();
}
2010-12-14 03:07:25 +00:00
$this -> config [ 'request' ][ 'cookies' ][ $Host ] = array_merge ( $this -> config [ 'request' ][ 'cookies' ][ $Host ], $this -> response -> cookies );
2008-05-30 11:40:08 +00:00
}
2012-02-23 13:38:02 +00:00
if ( $this -> request [ 'redirect' ] && $this -> response -> isRedirect ()) {
2014-11-06 03:18:48 +00:00
$location = trim ( $this -> response -> getHeader ( 'Location' ), '=' );
$request [ 'uri' ] = str_replace ( '%2F' , '/' , $location );
2011-11-13 16:45:33 +00:00
$request [ 'redirect' ] = is_int ( $this -> request [ 'redirect' ]) ? $this -> request [ 'redirect' ] - 1 : $this -> request [ 'redirect' ];
2011-11-08 17:55:58 +00:00
$this -> response = $this -> request ( $request );
}
2008-05-30 11:40:08 +00:00
2010-12-14 03:07:25 +00:00
return $this -> response ;
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Issues a GET request to the specified URI , query , and request .
*
2010-01-25 16:01:05 +00:00
* Using a string uri and an array of query string parameters :
*
* `$response = $http->get('http://google.com/search', array('q' => 'cakephp', 'client' => 'safari'));`
*
* Would do a GET request to `http://google.com/search?q=cakephp&client=safari`
*
* You could express the same thing using a uri array and query string parameters :
*
2015-01-09 12:47:25 +00:00
* `` `
2010-01-25 16:01:05 +00:00
* $response = $http -> get (
* array ( 'host' => 'google.com' , 'path' => '/search' ),
* array ( 'q' => 'cakephp' , 'client' => 'safari' )
* );
2015-01-09 12:47:25 +00:00
* `` `
2010-01-25 16:01:05 +00:00
*
2012-05-13 00:43:31 +00:00
* @ param string | array $uri URI to request . Either a string uri , or a uri array , see HttpSocket :: _parseUri ()
2010-01-25 16:01:05 +00:00
* @ param array $query Querystring parameters to append to URI
2008-05-30 11:40:08 +00:00
* @ param array $request An indexed array with indexes such as 'method' or uri
2018-12-28 13:19:26 +00:00
* @ return false | HttpSocketResponse Result of request , either false on failure or the response to the request .
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:19:38 +00:00
public function get ( $uri = null , $query = array (), $request = array ()) {
2019-01-11 12:20:09 +00:00
$uri = $this -> _parseUri ( $uri , $this -> config [ 'request' ][ 'uri' ]);
if ( isset ( $uri [ 'query' ])) {
$uri [ 'query' ] = array_merge ( $uri [ 'query' ], $query );
} else {
$uri [ 'query' ] = $query ;
2008-05-30 11:40:08 +00:00
}
2019-01-11 12:20:09 +00:00
$uri = $this -> _buildUri ( $uri );
2008-05-30 11:40:08 +00:00
2012-03-11 01:57:18 +00:00
$request = Hash :: merge ( array ( 'method' => 'GET' , 'uri' => $uri ), $request );
2008-05-30 11:40:08 +00:00
return $this -> request ( $request );
}
2014-07-14 19:34:27 +00:00
/**
2014-07-21 02:00:07 +00:00
* Issues a HEAD request to the specified URI , query , and request .
*
2014-07-14 19:34:27 +00:00
* By definition HEAD request are identical to GET request except they return no response body . This means that all
* information and examples relevant to GET also applys to HEAD .
*
2014-07-21 02:00:07 +00:00
* @ param string | array $uri URI to request . Either a string URI , or a URI array , see HttpSocket :: _parseUri ()
2014-07-14 19:34:27 +00:00
* @ param array $query Querystring parameters to append to URI
* @ param array $request An indexed array with indexes such as 'method' or uri
2018-12-28 13:19:26 +00:00
* @ return false | HttpSocketResponse Result of request , either false on failure or the response to the request .
2014-07-14 19:34:27 +00:00
*/
public function head ( $uri = null , $query = array (), $request = array ()) {
2019-01-11 12:20:09 +00:00
$uri = $this -> _parseUri ( $uri , $this -> config [ 'request' ][ 'uri' ]);
if ( isset ( $uri [ 'query' ])) {
$uri [ 'query' ] = array_merge ( $uri [ 'query' ], $query );
} else {
$uri [ 'query' ] = $query ;
2014-07-14 19:34:27 +00:00
}
2019-01-11 12:20:09 +00:00
$uri = $this -> _buildUri ( $uri );
2014-07-14 19:34:27 +00:00
$request = Hash :: merge ( array ( 'method' => 'HEAD' , 'uri' => $uri ), $request );
return $this -> request ( $request );
}
2008-05-30 11:40:08 +00:00
/**
* Issues a POST request to the specified URI , query , and request .
*
2013-10-22 04:09:34 +00:00
* `post()` can be used to post simple data arrays to a URL :
2010-01-25 16:01:05 +00:00
*
2015-01-09 12:47:25 +00:00
* `` `
2010-01-25 16:01:05 +00:00
* $response = $http -> post ( 'http://example.com' , array (
* 'username' => 'batman' ,
* 'password' => 'bruce_w4yne'
* ));
2015-01-09 12:47:25 +00:00
* `` `
2010-01-25 16:01:05 +00:00
*
2012-05-13 00:43:31 +00:00
* @ param string | array $uri URI to request . See HttpSocket :: _parseUri ()
2013-09-18 01:17:26 +00:00
* @ param array $data Array of request body data keys and values .
2008-05-30 11:40:08 +00:00
* @ param array $request An indexed array with indexes such as 'method' or uri
2018-12-28 13:19:26 +00:00
* @ return false | HttpSocketResponse Result of request , either false on failure or the response to the request .
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:19:38 +00:00
public function post ( $uri = null , $data = array (), $request = array ()) {
2012-03-11 01:57:18 +00:00
$request = Hash :: merge ( array ( 'method' => 'POST' , 'uri' => $uri , 'body' => $data ), $request );
2008-05-30 11:40:08 +00:00
return $this -> request ( $request );
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Issues a PUT request to the specified URI , query , and request .
*
2012-05-13 00:43:31 +00:00
* @ param string | array $uri URI to request , See HttpSocket :: _parseUri ()
2013-09-18 01:17:26 +00:00
* @ param array $data Array of request body data keys and values .
2008-05-30 11:40:08 +00:00
* @ param array $request An indexed array with indexes such as 'method' or uri
2018-12-28 13:19:26 +00:00
* @ return false | HttpSocketResponse Result of request
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:19:38 +00:00
public function put ( $uri = null , $data = array (), $request = array ()) {
2012-03-11 01:57:18 +00:00
$request = Hash :: merge ( array ( 'method' => 'PUT' , 'uri' => $uri , 'body' => $data ), $request );
2008-05-30 11:40:08 +00:00
return $this -> request ( $request );
}
2009-07-24 19:18:37 +00:00
2013-06-04 20:46:15 +00:00
/**
* Issues a PATCH request to the specified URI , query , and request .
*
* @ param string | array $uri URI to request , See HttpSocket :: _parseUri ()
2013-09-18 01:17:26 +00:00
* @ param array $data Array of request body data keys and values .
2013-06-04 20:46:15 +00:00
* @ param array $request An indexed array with indexes such as 'method' or uri
2018-12-28 13:19:26 +00:00
* @ return false | HttpSocketResponse Result of request
2013-06-04 20:46:15 +00:00
*/
public function patch ( $uri = null , $data = array (), $request = array ()) {
$request = Hash :: merge ( array ( 'method' => 'PATCH' , 'uri' => $uri , 'body' => $data ), $request );
return $this -> request ( $request );
}
2008-05-30 11:40:08 +00:00
/**
* Issues a DELETE request to the specified URI , query , and request .
*
2012-05-13 00:43:31 +00:00
* @ param string | array $uri URI to request ( see { @ link _parseUri ()})
2013-09-18 01:17:26 +00:00
* @ param array $data Array of request body data keys and values .
2008-05-30 11:40:08 +00:00
* @ param array $request An indexed array with indexes such as 'method' or uri
2018-12-28 13:19:26 +00:00
* @ return false | HttpSocketResponse Result of request
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:19:38 +00:00
public function delete ( $uri = null , $data = array (), $request = array ()) {
2012-03-11 01:57:18 +00:00
$request = Hash :: merge ( array ( 'method' => 'DELETE' , 'uri' => $uri , 'body' => $data ), $request );
2008-05-30 11:40:08 +00:00
return $this -> request ( $request );
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2013-04-29 09:05:17 +00:00
* Normalizes URLs into a $uriTemplate . If no template is provided
* a default one will be used . Will generate the URL using the
2010-01-25 16:01:05 +00:00
* current config information .
*
* ### Usage:
*
* After configuring part of the request parameters , you can use url () to generate
2013-04-29 09:05:17 +00:00
* URLs .
2010-01-25 16:01:05 +00:00
*
2015-01-09 12:47:25 +00:00
* `` `
2017-06-10 22:43:06 +00:00
* $http = new HttpSocket ( 'https://www.cakephp.org' );
2010-01-25 16:01:05 +00:00
* $url = $http -> url ( '/search?q=bar' );
2015-01-09 12:47:25 +00:00
* `` `
2010-01-25 16:01:05 +00:00
*
2017-06-10 22:43:06 +00:00
* Would return `https://cakephp.org/search?q=bar`
2010-01-25 16:01:05 +00:00
*
* url () can also be used with custom templates :
*
* `$url = $http->url('http://www.cakephp/search?q=socket', '/%path?%query');`
*
* Would return `/search?q=socket` .
2008-05-30 11:40:08 +00:00
*
2014-05-31 21:36:05 +00:00
* @ param string | array $url Either a string or array of URL options to create a URL with .
2013-04-29 09:05:17 +00:00
* @ param string $uriTemplate A template string to use for URL formatting .
* @ return mixed Either false on failure or a string containing the composed URL .
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:19:38 +00:00
public function url ( $url = null , $uriTemplate = null ) {
2013-08-16 18:12:49 +00:00
if ( $url === null ) {
2008-05-30 11:40:08 +00:00
$url = '/' ;
}
if ( is_string ( $url )) {
2012-02-02 02:10:56 +00:00
$scheme = $this -> config [ 'request' ][ 'uri' ][ 'scheme' ];
if ( is_array ( $scheme )) {
$scheme = $scheme [ 0 ];
}
$port = $this -> config [ 'request' ][ 'uri' ][ 'port' ];
if ( is_array ( $port )) {
$port = $port [ 0 ];
}
2020-03-20 20:10:58 +00:00
if ( $url [ 0 ] === '/' ) {
2012-02-02 02:10:56 +00:00
$url = $this -> config [ 'request' ][ 'uri' ][ 'host' ] . ':' . $port . $url ;
2008-05-30 11:40:08 +00:00
}
if ( ! preg_match ( '/^.+:\/\/|\*|^\//' , $url )) {
2012-02-02 02:10:56 +00:00
$url = $scheme . '://' . $url ;
2008-05-30 11:40:08 +00:00
}
} elseif ( ! is_array ( $url ) && ! empty ( $url )) {
return false ;
}
$base = array_merge ( $this -> config [ 'request' ][ 'uri' ], array ( 'scheme' => array ( 'http' , 'https' ), 'port' => array ( 80 , 443 )));
2009-05-07 18:49:21 +00:00
$url = $this -> _parseUri ( $url , $base );
2008-05-30 11:40:08 +00:00
if ( empty ( $url )) {
$url = $this -> config [ 'request' ][ 'uri' ];
}
if ( ! empty ( $uriTemplate )) {
2009-05-07 18:49:21 +00:00
return $this -> _buildUri ( $url , $uriTemplate );
2008-05-30 11:40:08 +00:00
}
2009-05-07 18:49:21 +00:00
return $this -> _buildUri ( $url );
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2010-11-10 01:03:43 +00:00
* Set authentication in request
2008-05-30 11:40:08 +00:00
*
2010-11-10 01:03:43 +00:00
* @ return void
2010-12-15 04:01:00 +00:00
* @ throws SocketException
2008-05-30 11:40:08 +00:00
*/
2010-11-10 01:03:43 +00:00
protected function _setAuth () {
2010-12-03 02:46:11 +00:00
if ( empty ( $this -> _auth )) {
2010-11-13 19:21:52 +00:00
return ;
2008-05-30 11:40:08 +00:00
}
2010-12-03 02:46:11 +00:00
$method = key ( $this -> _auth );
2011-02-22 04:28:46 +00:00
list ( $plugin , $authClass ) = pluginSplit ( $method , true );
$authClass = Inflector :: camelize ( $authClass ) . 'Authentication' ;
App :: uses ( $authClass , $plugin . 'Network/Http' );
if ( ! class_exists ( $authClass )) {
2011-03-20 15:35:43 +00:00
throw new SocketException ( __d ( 'cake_dev' , 'Unknown authentication method.' ));
2008-05-30 11:40:08 +00:00
}
2010-12-01 15:49:03 +00:00
if ( ! method_exists ( $authClass , 'authentication' )) {
2013-08-16 10:06:36 +00:00
throw new SocketException ( __d ( 'cake_dev' , 'The %s does not support authentication.' , $authClass ));
2009-07-15 19:15:14 +00:00
}
2010-12-19 22:38:21 +00:00
call_user_func_array ( " $authClass ::authentication " , array ( $this , & $this -> _auth [ $method ]));
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2010-12-01 15:46:13 +00:00
* Set the proxy configuration and authentication
2008-05-30 11:40:08 +00:00
*
2010-12-01 15:46:13 +00:00
* @ return void
2010-12-15 04:01:00 +00:00
* @ throws SocketException
2008-05-30 11:40:08 +00:00
*/
2010-12-06 13:28:40 +00:00
protected function _setProxy () {
2010-12-04 01:10:07 +00:00
if ( empty ( $this -> _proxy ) || ! isset ( $this -> _proxy [ 'host' ], $this -> _proxy [ 'port' ])) {
2010-12-01 15:46:13 +00:00
return ;
2008-05-30 11:40:08 +00:00
}
2010-12-04 01:10:07 +00:00
$this -> config [ 'host' ] = $this -> _proxy [ 'host' ];
$this -> config [ 'port' ] = $this -> _proxy [ 'port' ];
2015-03-17 12:40:36 +00:00
$this -> config [ 'proxy' ] = true ;
2008-05-30 11:40:08 +00:00
2010-12-04 01:10:07 +00:00
if ( empty ( $this -> _proxy [ 'method' ]) || ! isset ( $this -> _proxy [ 'user' ], $this -> _proxy [ 'pass' ])) {
2010-12-01 15:46:13 +00:00
return ;
2008-05-30 11:40:08 +00:00
}
2011-02-22 04:28:46 +00:00
list ( $plugin , $authClass ) = pluginSplit ( $this -> _proxy [ 'method' ], true );
$authClass = Inflector :: camelize ( $authClass ) . 'Authentication' ;
2012-03-04 16:18:20 +00:00
App :: uses ( $authClass , $plugin . 'Network/Http' );
2011-02-22 04:28:46 +00:00
if ( ! class_exists ( $authClass )) {
2011-03-20 15:35:43 +00:00
throw new SocketException ( __d ( 'cake_dev' , 'Unknown authentication method for proxy.' ));
2008-05-30 11:40:08 +00:00
}
2010-12-01 15:49:03 +00:00
if ( ! method_exists ( $authClass , 'proxyAuthentication' )) {
2013-08-16 10:06:36 +00:00
throw new SocketException ( __d ( 'cake_dev' , 'The %s does not support proxy authentication.' , $authClass ));
2008-05-30 11:40:08 +00:00
}
2010-12-19 22:38:21 +00:00
call_user_func_array ( " $authClass ::proxyAuthentication " , array ( $this , & $this -> _proxy ));
2015-12-11 13:44:46 +00:00
if ( ! empty ( $this -> request [ 'header' ][ 'Proxy-Authorization' ])) {
$this -> config [ 'proxyauth' ] = $this -> request [ 'header' ][ 'Proxy-Authorization' ];
if ( $this -> request [ 'uri' ][ 'scheme' ] === 'https' ) {
$this -> request [ 'header' ] = Hash :: remove ( $this -> request [ 'header' ], 'Proxy-Authorization' );
}
}
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Parses and sets the specified URI into current request configuration .
*
2012-05-13 00:43:31 +00:00
* @ param string | array $uri URI , See HttpSocket :: _parseUri ()
2014-07-03 13:36:42 +00:00
* @ return bool If uri has merged in config
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:21:28 +00:00
protected function _configUri ( $uri = null ) {
2008-05-30 11:40:08 +00:00
if ( empty ( $uri )) {
return false ;
}
if ( is_array ( $uri )) {
2009-05-07 18:49:21 +00:00
$uri = $this -> _parseUri ( $uri );
2008-05-30 11:40:08 +00:00
} else {
2009-05-07 18:49:21 +00:00
$uri = $this -> _parseUri ( $uri , true );
2008-05-30 11:40:08 +00:00
}
if ( ! isset ( $uri [ 'host' ])) {
return false ;
}
$config = array (
'request' => array (
2010-12-03 02:46:11 +00:00
'uri' => array_intersect_key ( $uri , $this -> config [ 'request' ][ 'uri' ])
2008-05-30 11:40:08 +00:00
)
);
2012-03-11 01:57:18 +00:00
$this -> config = Hash :: merge ( $this -> config , $config );
$this -> config = Hash :: merge ( $this -> config , array_intersect_key ( $this -> config [ 'request' ][ 'uri' ], $this -> config ));
2010-12-06 06:02:23 +00:00
return true ;
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Takes a $uri array and turns it into a fully qualified URL string
*
2012-05-13 00:43:31 +00:00
* @ param string | array $uri Either A $uri array , or a request string . Will use $this -> config if left empty .
2010-01-25 16:01:05 +00:00
* @ param string $uriTemplate The Uri template / format to use .
2011-12-02 05:58:09 +00:00
* @ return mixed A fully qualified URL formatted according to $uriTemplate , or false on failure
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:21:28 +00:00
protected function _buildUri ( $uri = array (), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment' ) {
2008-05-30 11:40:08 +00:00
if ( is_string ( $uri )) {
$uri = array ( 'host' => $uri );
}
2009-05-07 18:49:21 +00:00
$uri = $this -> _parseUri ( $uri , true );
2008-05-30 11:40:08 +00:00
if ( ! is_array ( $uri ) || empty ( $uri )) {
return false ;
}
2024-01-09 19:35:08 +00:00
$uri [ 'path' ] = preg_replace ( '/^\//' , '' , $uri [ 'path' ]);
2013-03-14 00:22:50 +00:00
$uri [ 'query' ] = http_build_query ( $uri [ 'query' ], '' , '&' );
2012-02-01 11:04:52 +00:00
$uri [ 'query' ] = rtrim ( $uri [ 'query' ], '=' );
2008-05-30 11:40:08 +00:00
$stripIfEmpty = array (
'query' => '?%query' ,
'fragment' => '#%fragment' ,
2009-11-13 19:42:40 +00:00
'user' => '%user:%pass@' ,
'host' => '%host:%port/'
2008-05-30 11:40:08 +00:00
);
foreach ( $stripIfEmpty as $key => $strip ) {
if ( empty ( $uri [ $key ])) {
2024-01-09 19:35:08 +00:00
$uriTemplate = str_replace ( $strip , '' , $uriTemplate );
2008-05-30 11:40:08 +00:00
}
}
$defaultPorts = array ( 'http' => 80 , 'https' => 443 );
if ( array_key_exists ( $uri [ 'scheme' ], $defaultPorts ) && $defaultPorts [ $uri [ 'scheme' ]] == $uri [ 'port' ]) {
2024-01-09 19:35:08 +00:00
$uriTemplate = str_replace ( ':%port' , '' , $uriTemplate );
2008-05-30 11:40:08 +00:00
}
foreach ( $uri as $property => $value ) {
2024-01-09 19:35:08 +00:00
$uriTemplate = str_replace ( '%' . $property , ( string ) $value , $uriTemplate );
2008-05-30 11:40:08 +00:00
}
if ( $uriTemplate === '/*' ) {
$uriTemplate = '*' ;
}
return $uriTemplate ;
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Parses the given URI and breaks it down into pieces as an indexed array with elements
* such as 'scheme' , 'port' , 'query' .
*
2012-05-13 00:43:31 +00:00
* @ param string | array $uri URI to parse
2014-07-03 13:36:42 +00:00
* @ param bool | array $base If true use default URI config , otherwise indexed array to set 'scheme' , 'host' , 'port' , etc .
2017-10-03 15:22:42 +00:00
* @ return array | bool Parsed URI
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:21:28 +00:00
protected function _parseUri ( $uri = null , $base = array ()) {
2008-05-30 11:40:08 +00:00
$uriBase = array (
'scheme' => array ( 'http' , 'https' ),
'host' => null ,
'port' => array ( 80 , 443 ),
'user' => null ,
'pass' => null ,
'path' => '/' ,
'query' => null ,
'fragment' => null
);
if ( is_string ( $uri )) {
$uri = parse_url ( $uri );
}
if ( ! is_array ( $uri ) || empty ( $uri )) {
return false ;
}
if ( $base === true ) {
$base = $uriBase ;
}
if ( isset ( $base [ 'port' ], $base [ 'scheme' ]) && is_array ( $base [ 'port' ]) && is_array ( $base [ 'scheme' ])) {
if ( isset ( $uri [ 'scheme' ]) && ! isset ( $uri [ 'port' ])) {
$base [ 'port' ] = $base [ 'port' ][ array_search ( $uri [ 'scheme' ], $base [ 'scheme' ])];
} elseif ( isset ( $uri [ 'port' ]) && ! isset ( $uri [ 'scheme' ])) {
$base [ 'scheme' ] = $base [ 'scheme' ][ array_search ( $uri [ 'port' ], $base [ 'port' ])];
}
}
if ( is_array ( $base ) && ! empty ( $base )) {
$uri = array_merge ( $base , $uri );
}
if ( isset ( $uri [ 'scheme' ]) && is_array ( $uri [ 'scheme' ])) {
$uri [ 'scheme' ] = array_shift ( $uri [ 'scheme' ]);
}
if ( isset ( $uri [ 'port' ]) && is_array ( $uri [ 'port' ])) {
$uri [ 'port' ] = array_shift ( $uri [ 'port' ]);
}
if ( array_key_exists ( 'query' , $uri )) {
2009-05-07 18:49:21 +00:00
$uri [ 'query' ] = $this -> _parseQuery ( $uri [ 'query' ]);
2008-05-30 11:40:08 +00:00
}
if ( ! array_intersect_key ( $uriBase , $uri )) {
return false ;
}
return $uri ;
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* This function can be thought of as a reverse to PHP5 ' s http_build_query () . It takes a given query string and turns it into an array and
2011-12-02 05:58:09 +00:00
* supports nesting by using the php bracket syntax . So this means you can parse queries like :
2008-05-30 11:40:08 +00:00
*
* - ? key [ subKey ] = value
* - ? key [] = value1 & key [] = value2
*
2010-12-04 02:58:49 +00:00
* A leading '?' mark in $query is optional and does not effect the outcome of this function .
2010-01-25 16:01:05 +00:00
* For the complete capabilities of this implementation take a look at HttpSocketTest :: testparseQuery ()
2008-05-30 11:40:08 +00:00
*
2012-05-13 00:43:31 +00:00
* @ param string | array $query A query string to parse into an array or an array to return directly " as is "
2010-01-25 16:01:05 +00:00
* @ return array The $query parsed into a possibly multi - level array . If an empty $query is
* given , an empty array is returned .
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:21:28 +00:00
protected function _parseQuery ( $query ) {
2008-05-30 11:40:08 +00:00
if ( is_array ( $query )) {
return $query ;
}
2012-03-09 02:05:28 +00:00
$parsedQuery = array ();
if ( is_string ( $query ) && ! empty ( $query )) {
$query = preg_replace ( '/^\?/' , '' , $query );
$items = explode ( '&' , $query );
foreach ( $items as $item ) {
if ( strpos ( $item , '=' ) !== false ) {
list ( $key , $value ) = explode ( '=' , $item , 2 );
} else {
$key = $item ;
$value = null ;
}
$key = urldecode ( $key );
$value = urldecode ( $value );
if ( preg_match_all ( '/\[([^\[\]]*)\]/iUs' , $key , $matches )) {
$subKeys = $matches [ 1 ];
$rootKey = substr ( $key , 0 , strpos ( $key , '[' ));
if ( ! empty ( $rootKey )) {
array_unshift ( $subKeys , $rootKey );
}
$queryNode =& $parsedQuery ;
foreach ( $subKeys as $subKey ) {
if ( ! is_array ( $queryNode )) {
$queryNode = array ();
}
if ( $subKey === '' ) {
$queryNode [] = array ();
end ( $queryNode );
$subKey = key ( $queryNode );
}
$queryNode =& $queryNode [ $subKey ];
}
$queryNode = $value ;
continue ;
}
if ( ! isset ( $parsedQuery [ $key ])) {
$parsedQuery [ $key ] = $value ;
} else {
$parsedQuery [ $key ] = ( array ) $parsedQuery [ $key ];
$parsedQuery [ $key ][] = $value ;
}
}
}
2008-05-30 11:40:08 +00:00
return $parsedQuery ;
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Builds a request line according to HTTP / 1.1 specs . Activate quirks mode to work outside specs .
*
* @ param array $request Needs to contain a 'uri' key . Should also contain a 'method' key , otherwise defaults to GET .
* @ return string Request line
2010-12-15 04:01:00 +00:00
* @ throws SocketException
2008-05-30 11:40:08 +00:00
*/
2014-11-25 03:23:12 +00:00
protected function _buildRequestLine ( $request = array ()) {
2008-05-30 11:40:08 +00:00
$asteriskMethods = array ( 'OPTIONS' );
if ( is_string ( $request )) {
$isValid = preg_match ( " /(.+) (.+) (.+) \r \n /U " , $request , $match );
2013-02-12 02:38:08 +00:00
if ( ! $this -> quirksMode && ( ! $isValid || ( $match [ 2 ] === '*' && ! in_array ( $match [ 3 ], $asteriskMethods )))) {
2011-03-20 15:35:43 +00:00
throw new SocketException ( __d ( 'cake_dev' , 'HttpSocket::_buildRequestLine - Passed an invalid request line string. Activate quirks mode to do this.' ));
2008-05-30 11:40:08 +00:00
}
return $request ;
} elseif ( ! is_array ( $request )) {
return false ;
} elseif ( ! array_key_exists ( 'uri' , $request )) {
return false ;
}
2012-11-14 11:36:55 +00:00
$request [ 'uri' ] = $this -> _parseUri ( $request [ 'uri' ]);
2014-04-07 23:25:14 +00:00
$request += array ( 'method' => 'GET' );
2015-03-19 15:19:49 +00:00
if ( ! empty ( $this -> _proxy [ 'host' ]) && $request [ 'uri' ][ 'scheme' ] !== 'https' ) {
2010-12-01 15:46:13 +00:00
$request [ 'uri' ] = $this -> _buildUri ( $request [ 'uri' ], '%scheme://%host:%port/%path?%query' );
} else {
$request [ 'uri' ] = $this -> _buildUri ( $request [ 'uri' ], '/%path?%query' );
}
2008-05-30 11:40:08 +00:00
if ( ! $this -> quirksMode && $request [ 'uri' ] === '*' && ! in_array ( $request [ 'method' ], $asteriskMethods )) {
2011-03-20 15:35:43 +00:00
throw new SocketException ( __d ( 'cake_dev' , 'HttpSocket::_buildRequestLine - The "*" asterisk character is only allowed for the following methods: %s. Activate quirks mode to work outside of HTTP/1.1 specs.' , implode ( ',' , $asteriskMethods )));
2008-05-30 11:40:08 +00:00
}
2014-11-25 03:23:12 +00:00
$version = isset ( $request [ 'version' ]) ? $request [ 'version' ] : '1.1' ;
return $request [ 'method' ] . ' ' . $request [ 'uri' ] . ' HTTP/' . $version . " \r \n " ;
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Builds the header .
*
* @ param array $header Header to build
2014-05-31 21:36:05 +00:00
* @ param string $mode Mode
2008-05-30 11:40:08 +00:00
* @ return string Header built from array
*/
2010-04-05 03:21:28 +00:00
protected function _buildHeader ( $header , $mode = 'standard' ) {
2008-05-30 11:40:08 +00:00
if ( is_string ( $header )) {
return $header ;
} elseif ( ! is_array ( $header )) {
return false ;
}
2010-11-13 23:44:11 +00:00
$fieldsInHeader = array ();
foreach ( $header as $key => $value ) {
$lowKey = strtolower ( $key );
if ( array_key_exists ( $lowKey , $fieldsInHeader )) {
$header [ $fieldsInHeader [ $lowKey ]] = $value ;
unset ( $header [ $key ]);
} else {
$fieldsInHeader [ $lowKey ] = $key ;
}
}
2008-05-30 11:40:08 +00:00
$returnHeader = '' ;
foreach ( $header as $field => $contents ) {
2013-02-12 02:38:08 +00:00
if ( is_array ( $contents ) && $mode === 'standard' ) {
2009-11-19 22:13:35 +00:00
$contents = implode ( ',' , $contents );
2008-05-30 11:40:08 +00:00
}
foreach (( array ) $contents as $content ) {
$contents = preg_replace ( " / \r \n (?![ \t ])/ " , " \r \n " , $content );
2009-05-07 18:49:21 +00:00
$field = $this -> _escapeToken ( $field );
2008-05-30 11:40:08 +00:00
2010-12-14 13:11:36 +00:00
$returnHeader .= $field . ': ' . $contents . " \r \n " ;
2008-05-30 11:40:08 +00:00
}
}
return $returnHeader ;
}
/**
2010-01-25 16:01:05 +00:00
* Builds cookie headers for a request .
2008-05-30 11:40:08 +00:00
*
2013-04-19 01:23:40 +00:00
* Cookies can either be in the format returned in responses , or
* a simple key => value pair .
*
2010-01-25 16:01:05 +00:00
* @ param array $cookies Array of cookies to send with the request .
* @ return string Cookie header string to be sent with the request .
2008-05-30 11:40:08 +00:00
*/
2010-12-04 02:58:49 +00:00
public function buildCookies ( $cookies ) {
2008-05-30 11:40:08 +00:00
$header = array ();
foreach ( $cookies as $name => $cookie ) {
2013-04-19 01:22:50 +00:00
if ( is_array ( $cookie )) {
$value = $this -> _escapeToken ( $cookie [ 'value' ], array ( ';' ));
} else {
$value = $this -> _escapeToken ( $cookie , array ( ';' ));
}
$header [] = $name . '=' . $value ;
2008-05-30 11:40:08 +00:00
}
2010-12-04 02:58:49 +00:00
return $this -> _buildHeader ( array ( 'Cookie' => implode ( '; ' , $header )), 'pragmatic' );
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Escapes a given $token according to RFC 2616 ( HTTP 1.1 specs )
*
* @ param string $token Token to escape
2014-05-31 21:36:05 +00:00
* @ param array $chars Characters to escape
2008-05-30 11:40:08 +00:00
* @ return string Escaped token
*/
2010-12-04 02:58:49 +00:00
protected function _escapeToken ( $token , $chars = null ) {
$regex = '/([' . implode ( '' , $this -> _tokenEscapeChars ( true , $chars )) . '])/' ;
2008-05-30 11:40:08 +00:00
$token = preg_replace ( $regex , '"\\1"' , $token );
return $token ;
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Gets escape chars according to RFC 2616 ( HTTP 1.1 specs ) .
*
2014-07-03 13:36:42 +00:00
* @ param bool $hex true to get them as HEX values , false otherwise
2014-05-31 21:36:05 +00:00
* @ param array $chars Characters to escape
2008-05-30 11:40:08 +00:00
* @ return array Escape chars
*/
2010-12-04 02:58:49 +00:00
protected function _tokenEscapeChars ( $hex = true , $chars = null ) {
2008-05-30 11:40:08 +00:00
if ( ! empty ( $chars )) {
$escape = $chars ;
} else {
$escape = array ( '"' , " ( " , " ) " , " < " , " > " , " @ " , " , " , " ; " , " : " , " \\ " , " / " , " [ " , " ] " , " ? " , " = " , " { " , " } " , " " );
for ( $i = 0 ; $i <= 31 ; $i ++ ) {
$escape [] = chr ( $i );
}
$escape [] = chr ( 127 );
}
2012-09-14 17:26:30 +00:00
if ( ! $hex ) {
2008-05-30 11:40:08 +00:00
return $escape ;
}
foreach ( $escape as $key => $char ) {
2010-12-04 02:58:49 +00:00
$escape [ $key ] = '\\x' . str_pad ( dechex ( ord ( $char )), 2 , '0' , STR_PAD_LEFT );
2008-05-30 11:40:08 +00:00
}
return $escape ;
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
2016-04-08 12:33:26 +00:00
* Resets the state of this HttpSocket instance to it ' s initial state ( before CakeObject :: __construct got executed ) or does
2008-05-30 11:40:08 +00:00
* the same thing partially for the request and the response property only .
*
2014-07-03 13:36:42 +00:00
* @ param bool $full If set to false only HttpSocket :: response and HttpSocket :: request are reset
* @ return bool True on success
2008-05-30 11:40:08 +00:00
*/
2010-04-05 03:19:38 +00:00
public function reset ( $full = true ) {
2008-05-30 11:40:08 +00:00
static $initalState = array ();
if ( empty ( $initalState )) {
$initalState = get_class_vars ( __CLASS__ );
}
2010-12-06 05:56:16 +00:00
if ( ! $full ) {
2008-05-30 11:40:08 +00:00
$this -> request = $initalState [ 'request' ];
$this -> response = $initalState [ 'response' ];
return true ;
}
parent :: reset ( $initalState );
return true ;
}
2012-03-04 16:18:20 +00:00
2008-05-30 11:40:08 +00:00
}
2014-06-12 00:04:58 +00:00