1<?php 2/** 3 * Copyright 2007-2016 Horde LLC (http://www.horde.org/) 4 * 5 * @author Chuck Hagenbuch <chuck@horde.org> 6 * @license http://www.horde.org/licenses/bsd BSD 7 * @category Horde 8 * @package Http 9 */ 10 11/** 12 * An HTTP client. 13 * 14 * @author Chuck Hagenbuch <chuck@horde.org> 15 * @license http://www.horde.org/licenses/bsd BSD 16 * @category Horde 17 * @package Http 18 * 19 * @property boolean $httpMethodOverride 20 * @see $_httpMethodOverride 21 * @property Horde_Http_Request_Base $request 22 * A concrete request instance. 23 * @property-write string|Horde_Url $request.uri 24 * Default URI if not specified for individual 25 * requests. 26 * @property-write array $request.headers 27 * Hash with additional request headers. 28 * @property-write string $request.method 29 * Default request method if not specified for 30 * individual requests. 31 * @property-write array|string $request.data 32 * POST data fields or POST/PUT data body. 33 * @property-write string $request.username 34 * Authentication user name. 35 * @property-write string $request.password 36 * Authentication password. 37 * @property-write string $request.authenticationScheme 38 * Authentication method, one of the 39 * Horde_Http::AUTH_* constants. 40 * @property-write string $request.proxyServer 41 * Host name of a proxy server. 42 * @property-write integer $request.proxyPort 43 * Port number of a proxy server. 44 * @property-write integer $request.proxyType 45 * Proxy server type, one of the 46 * Horde_Http::PROXY_* constants. 47 * @property-write string $request.proxyUsername 48 * Proxy authentication user name. 49 * @property-write string $request.proxyPassword 50 * Proxy authentication password. 51 * @property-write string $request.proxyAuthenticationScheme 52 * Proxy authentication method, one of the 53 * Horde_Http::AUTH_* constants. 54 * @property-write integer $request.redirects 55 * Maximum number of redirects to follow. 56 * @property-write integer $request.timeout 57 * Timeout in seconds. 58 * @property-write boolean $request.verifyPeer 59 * Verify SSL peer certificates? 60 */ 61class Horde_Http_Client 62{ 63 /** 64 * The current HTTP request. 65 * 66 * @var Horde_Http_Request_Base 67 */ 68 protected $_request; 69 70 /** 71 * The previous HTTP request. 72 * 73 * @var Horde_Http_Request_Base 74 */ 75 protected $_lastRequest; 76 77 /** 78 * The most recent HTTP response. 79 * 80 * @var Horde_Http_Response_Base 81 */ 82 protected $_lastResponse; 83 84 /** 85 * Use POST instead of PUT and DELETE, sending X-HTTP-Method-Override with 86 * the intended method name instead. 87 * 88 * @var boolean 89 */ 90 protected $_httpMethodOverride = false; 91 92 /** 93 * Horde_Http_Client constructor. 94 * 95 * @param array $args Any Http_Client settings to initialize in the 96 * constructor. See the class properties for available 97 * settings. 98 */ 99 public function __construct($args = array()) 100 { 101 // Set or create request object 102 if (isset($args['request'])) { 103 $this->_request = $args['request']; 104 unset($args['request']); 105 } else { 106 $requestFactory = new Horde_Http_Request_Factory(); 107 $this->_request = $requestFactory->create(); 108 } 109 110 foreach ($args as $key => $val) { 111 $this->$key = $val; 112 } 113 } 114 115 /** 116 * Sends a GET request. 117 * 118 * @param string $uri Request URI. 119 * @param array $headers Additional request headers. 120 * 121 * @throws Horde_Http_Exception 122 * @return Horde_Http_Response_Base 123 */ 124 public function get($uri = null, $headers = array()) 125 { 126 return $this->request('GET', $uri, null, $headers); 127 } 128 129 /** 130 * Sends a POST request. 131 * 132 * @param string $uri Request URI. 133 * @param array|string $data Data fields or data body. 134 * @param array $headers Additional request headers. 135 * 136 * @throws Horde_Http_Exception 137 * @return Horde_Http_Response_Base 138 */ 139 public function post($uri = null, $data = null, $headers = array()) 140 { 141 return $this->request('POST', $uri, $data, $headers); 142 } 143 144 /** 145 * Sends a PUT request. 146 * 147 * @param string $uri Request URI. 148 * @param string $data Data body. 149 * @param array $headers Additional request headers. 150 * 151 * @throws Horde_Http_Exception 152 * @return Horde_Http_Response_Base 153 */ 154 public function put($uri = null, $data = null, $headers = array()) 155 { 156 if ($this->_httpMethodOverride) { 157 $headers = array_merge( 158 array('X-HTTP-Method-Override' => 'PUT'), 159 $headers 160 ); 161 return $this->post($uri, $data, $headers); 162 } 163 164 return $this->request('PUT', $uri, $data, $headers); 165 } 166 167 /** 168 * Sends a DELETE request. 169 * 170 * @param string $uri Request URI. 171 * @param array $headers Additional request headers. 172 * 173 * @throws Horde_Http_Exception 174 * @return Horde_Http_Response_Base 175 */ 176 public function delete($uri = null, $headers = array()) 177 { 178 if ($this->_httpMethodOverride) { 179 $headers = array_merge( 180 array('X-HTTP-Method-Override' => 'DELETE'), 181 $headers 182 ); 183 return $this->post($uri, null, $headers); 184 } 185 186 return $this->request('DELETE', $uri, null, $headers); 187 } 188 189 /** 190 * Sends a HEAD request. 191 * 192 * @param string $uri Request URI. 193 * @param array $headers Additional request headers. 194 * 195 * @throws Horde_Http_Exception 196 * @return Horde_Http_Response_Base 197 */ 198 public function head($uri = null, $headers = array()) 199 { 200 return $this->request('HEAD', $uri, null, $headers); 201 } 202 203 /** 204 * Sends an HTTP request. 205 * 206 * @param string $method HTTP request method (GET, PUT, etc.) 207 * @param string|Horde_Url $uri URI to request, if different from 208 * $this->uri 209 * @param string|array $data Request data. Array of form data that will 210 * be encoded automatically, or a raw string. 211 * @param array $headers Any headers specific to this request. They 212 * will be combined with $this->_headers, and 213 * override headers of the same name for this 214 * request only. 215 * 216 * @throws Horde_Http_Exception 217 * @return Horde_Http_Response_Base 218 */ 219 public function request( 220 $method, $uri = null, $data = null, $headers = array() 221 ) 222 { 223 if ($method !== null) { 224 $this->request->method = $method; 225 } 226 if ($uri !== null) { 227 $this->request->uri = $uri; 228 } 229 if ($data !== null) { 230 $this->request->data = $data; 231 } 232 if (count($headers)) { 233 $this->request->setHeaders($headers); 234 } 235 236 $this->_lastRequest = $this->_request; 237 $this->_lastResponse = $this->_request->send(); 238 239 return $this->_lastResponse; 240 } 241 242 /** 243 * Returns a client parameter. 244 * 245 * @param string $name The parameter to return. 246 * 247 * @return mixed The parameter value. 248 */ 249 public function __get($name) 250 { 251 return isset($this->{'_' . $name}) ? $this->{'_' . $name} : null; 252 } 253 254 /** 255 * Sets a client parameter. 256 * 257 * @param string $name The parameter to set. 258 * @param mixed $value The parameter value. 259 */ 260 public function __set($name, $value) 261 { 262 if ((strpos($name, '.') === false)) { 263 if (isset($this->{'_' . $name})) { 264 $this->{'_' . $name} = $value; 265 return true; 266 } else { 267 throw new Horde_Http_Exception('unknown parameter: "' . $name . '"'); 268 } 269 } 270 271 list($object, $objectkey) = explode('.', $name, 2); 272 if ($object == 'request') { 273 $this->$object->$objectkey = $value; 274 return true; 275 } elseif ($object == 'client') { 276 $objectKey = '_' . $objectKey; 277 $this->$objectKey = $value; 278 return true; 279 } 280 281 throw new Horde_Http_Exception('unknown parameter: "' . $name . '"'); 282 } 283} 284