GuzzleHttpClient

The W3 Total Cache GuzzleHttp Client class.

Defined (1)

The class is defined in the following location(s).

/lib/Azure/GuzzleHttp/Client.php  
  1. class Client implements ClientInterface 
  2. /** @var array Default request options */ 
  3. private $config; 
  4.  
  5. /** 
  6. * Clients accept an array of constructor parameters. 
  7. * Here's an example of creating a client using a base_uri and an array of 
  8. * default request options to apply to each request: 
  9. * $client = new Client([ 
  10. * 'base_uri' => 'http://www.foo.com/1.0/',  
  11. * 'timeout' => 0,  
  12. * 'allow_redirects' => false,  
  13. * 'proxy' => '192.168.16.1:10' 
  14. * ]); 
  15. * Client configuration settings include the following options: 
  16. * - handler: (callable) Function that transfers HTTP requests over the 
  17. * wire. The function is called with a Psr7\Http\Message\RequestInterface 
  18. * and array of transfer options, and must return a 
  19. * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a 
  20. * Psr7\Http\Message\ResponseInterface on success. "handler" is a 
  21. * constructor only option that cannot be overridden in per/request 
  22. * options. If no handler is provided, a default handler will be created 
  23. * that enables all of the request options below by attaching all of the 
  24. * default middleware to the handler. 
  25. * - base_uri: (string|UriInterface) Base URI of the client that is merged 
  26. * into relative URIs. Can be a string or instance of UriInterface. 
  27. * - **: any request option 
  28. * @param array $config Client configuration settings. 
  29. * @see \GuzzleHttp\RequestOptions for a list of available request options. 
  30. */ 
  31. public function __construct(array $config = []) 
  32. if (!isset($config['handler'])) { 
  33. $config['handler'] = HandlerStack::create(); 
  34.  
  35. // Convert the base_uri to a UriInterface 
  36. if (isset($config['base_uri'])) { 
  37. $config['base_uri'] = Psr7\uri_for($config['base_uri']); 
  38.  
  39. $this->configureDefaults($config); 
  40.  
  41. public function __call($method, $args) 
  42. if (count($args) < 1) { 
  43. throw new \InvalidArgumentException('Magic request methods require a URI and optional options array'); 
  44.  
  45. $uri = $args[0]; 
  46. $opts = isset($args[1]) ? $args[1] : []; 
  47.  
  48. return substr($method, -5) === 'Async' 
  49. ? $this->requestAsync(substr($method, 0, -5), $uri, $opts) 
  50. : $this->request($method, $uri, $opts); 
  51.  
  52. public function sendAsync(RequestInterface $request, array $options = []) 
  53. // Merge the base URI into the request URI if needed. 
  54. $options = $this->prepareDefaults($options); 
  55.  
  56. return $this->transfer( 
  57. $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),  
  58. $options 
  59. ); 
  60.  
  61. public function send(RequestInterface $request, array $options = []) 
  62. $options[RequestOptions::SYNCHRONOUS] = true; 
  63. return $this->sendAsync($request, $options)->wait(); 
  64.  
  65. public function requestAsync($method, $uri = '', array $options = []) 
  66. $options = $this->prepareDefaults($options); 
  67. // Remove request modifying parameter because it can be done up-front. 
  68. $headers = isset($options['headers']) ? $options['headers'] : []; 
  69. $body = isset($options['body']) ? $options['body'] : null; 
  70. $version = isset($options['version']) ? $options['version'] : '1.1'; 
  71. // Merge the URI into the base URI. 
  72. $uri = $this->buildUri($uri, $options); 
  73. if (is_array($body)) { 
  74. $this->invalidBody(); 
  75. $request = new Psr7\Request($method, $uri, $headers, $body, $version); 
  76. // Remove the option so that they are not doubly-applied. 
  77. unset($options['headers'], $options['body'], $options['version']); 
  78.  
  79. return $this->transfer($request, $options); 
  80.  
  81. public function request($method, $uri = '', array $options = []) 
  82. $options[RequestOptions::SYNCHRONOUS] = true; 
  83. return $this->requestAsync($method, $uri, $options)->wait(); 
  84.  
  85. public function getConfig($option = null) 
  86. return $option === null 
  87. ? $this->config 
  88. : (isset($this->config[$option]) ? $this->config[$option] : null); 
  89.  
  90. private function buildUri($uri, array $config) 
  91. // for BC we accept null which would otherwise fail in uri_for 
  92. $uri = Psr7\uri_for($uri === null ? '' : $uri); 
  93.  
  94. if (isset($config['base_uri'])) { 
  95. $uri = Psr7\Uri::resolve(Psr7\uri_for($config['base_uri']), $uri); 
  96.  
  97. return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri; 
  98.  
  99. /** 
  100. * Configures the default options for a client. 
  101. * @param array $config 
  102. */ 
  103. private function configureDefaults(array $config) 
  104. $defaults = [ 
  105. 'allow_redirects' => RedirectMiddleware::$defaultSettings,  
  106. 'http_errors' => true,  
  107. 'decode_content' => true,  
  108. 'verify' => true,  
  109. 'cookies' => false 
  110. ]; 
  111.  
  112. // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set. 
  113.  
  114. // We can only trust the HTTP_PROXY environment variable in a CLI 
  115. // process due to the fact that PHP has no reliable mechanism to 
  116. // get environment variables that start with "HTTP_". 
  117. if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) { 
  118. $defaults['proxy']['http'] = getenv('HTTP_PROXY'); 
  119.  
  120. if ($proxy = getenv('HTTPS_PROXY')) { 
  121. $defaults['proxy']['https'] = $proxy; 
  122.  
  123. if ($noProxy = getenv('NO_PROXY')) { 
  124. $cleanedNoProxy = str_replace(' ', '', $noProxy); 
  125. $defaults['proxy']['no'] = explode(', ', $cleanedNoProxy); 
  126.  
  127. $this->config = $config + $defaults; 
  128.  
  129. if (!empty($config['cookies']) && $config['cookies'] === true) { 
  130. $this->config['cookies'] = new CookieJar(); 
  131.  
  132. // Add the default user-agent header. 
  133. if (!isset($this->config['headers'])) { 
  134. $this->config['headers'] = ['User-Agent' => default_user_agent()]; 
  135. } else { 
  136. // Add the User-Agent header if one was not already set. 
  137. foreach (array_keys($this->config['headers']) as $name) { 
  138. if (strtolower($name) === 'user-agent') { 
  139. return; 
  140. $this->config['headers']['User-Agent'] = default_user_agent(); 
  141.  
  142. /** 
  143. * Merges default options into the array. 
  144. * @param array $options Options to modify by reference 
  145. * @return array 
  146. */ 
  147. private function prepareDefaults($options) 
  148. $defaults = $this->config; 
  149.  
  150. if (!empty($defaults['headers'])) { 
  151. // Default headers are only added if they are not present. 
  152. $defaults['_conditional'] = $defaults['headers']; 
  153. unset($defaults['headers']); 
  154.  
  155. // Special handling for headers is required as they are added as 
  156. // conditional headers and as headers passed to a request ctor. 
  157. if (array_key_exists('headers', $options)) { 
  158. // Allows default headers to be unset. 
  159. if ($options['headers'] === null) { 
  160. $defaults['_conditional'] = null; 
  161. unset($options['headers']); 
  162. } elseif (!is_array($options['headers'])) { 
  163. throw new \InvalidArgumentException('headers must be an array'); 
  164.  
  165. // Shallow merge defaults underneath options. 
  166. $result = $options + $defaults; 
  167.  
  168. // Remove null values. 
  169. foreach ($result as $k => $v) { 
  170. if ($v === null) { 
  171. unset($result[$k]); 
  172.  
  173. return $result; 
  174.  
  175. /** 
  176. * Transfers the given request and applies request options. 
  177. * The URI of the request is not modified and the request options are used 
  178. * as-is without merging in default options. 
  179. * @param RequestInterface $request 
  180. * @param array $options 
  181. * @return Promise\PromiseInterface 
  182. */ 
  183. private function transfer(RequestInterface $request, array $options) 
  184. // save_to -> sink 
  185. if (isset($options['save_to'])) { 
  186. $options['sink'] = $options['save_to']; 
  187. unset($options['save_to']); 
  188.  
  189. // exceptions -> http_errors 
  190. if (isset($options['exceptions'])) { 
  191. $options['http_errors'] = $options['exceptions']; 
  192. unset($options['exceptions']); 
  193.  
  194. $request = $this->applyOptions($request, $options); 
  195. $handler = $options['handler']; 
  196.  
  197. try { 
  198. return Promise\promise_for($handler($request, $options)); 
  199. } catch (\Exception $e) { 
  200. return Promise\rejection_for($e); 
  201.  
  202. /** 
  203. * Applies the array of request options to a request. 
  204. * @param RequestInterface $request 
  205. * @param array $options 
  206. * @return RequestInterface 
  207. */ 
  208. private function applyOptions(RequestInterface $request, array &$options) 
  209. $modify = []; 
  210.  
  211. if (isset($options['form_params'])) { 
  212. if (isset($options['multipart'])) { 
  213. throw new \InvalidArgumentException('You cannot use ' 
  214. . 'form_params and multipart at the same time. Use the ' 
  215. . 'form_params option if you want to send application/' 
  216. . 'x-www-form-urlencoded requests, and the multipart ' 
  217. . 'option to send multipart/form-data requests.'); 
  218. $options['body'] = http_build_query($options['form_params'], '', '&'); 
  219. unset($options['form_params']); 
  220. $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded'; 
  221.  
  222. if (isset($options['multipart'])) { 
  223. $options['body'] = new Psr7\MultipartStream($options['multipart']); 
  224. unset($options['multipart']); 
  225.  
  226. if (isset($options['json'])) { 
  227. $options['body'] = \GuzzleHttp\json_encode($options['json']); 
  228. unset($options['json']); 
  229. $options['_conditional']['Content-Type'] = 'application/json'; 
  230.  
  231. if (!empty($options['decode_content']) 
  232. && $options['decode_content'] !== true 
  233. ) { 
  234. $modify['set_headers']['Accept-Encoding'] = $options['decode_content']; 
  235.  
  236. if (isset($options['headers'])) { 
  237. if (isset($modify['set_headers'])) { 
  238. $modify['set_headers'] = $options['headers'] + $modify['set_headers']; 
  239. } else { 
  240. $modify['set_headers'] = $options['headers']; 
  241. unset($options['headers']); 
  242.  
  243. if (isset($options['body'])) { 
  244. if (is_array($options['body'])) { 
  245. $this->invalidBody(); 
  246. $modify['body'] = Psr7\stream_for($options['body']); 
  247. unset($options['body']); 
  248.  
  249. if (!empty($options['auth']) && is_array($options['auth'])) { 
  250. $value = $options['auth']; 
  251. $type = isset($value[2]) ? strtolower($value[2]) : 'basic'; 
  252. switch ($type) { 
  253. case 'basic': 
  254. $modify['set_headers']['Authorization'] = 'Basic ' 
  255. . base64_encode("$value[0]:$value[1]"); 
  256. break; 
  257. case 'digest': 
  258. // @todo: Do not rely on curl 
  259. $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST; 
  260. $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]"; 
  261. break; 
  262.  
  263. if (isset($options['query'])) { 
  264. $value = $options['query']; 
  265. if (is_array($value)) { 
  266. $value = http_build_query($value, null, '&', PHP_QUERY_RFC3986); 
  267. if (!is_string($value)) { 
  268. throw new \InvalidArgumentException('query must be a string or array'); 
  269. $modify['query'] = $value; 
  270. unset($options['query']); 
  271.  
  272. // Ensure that sink is not an invalid value. 
  273. if (isset($options['sink'])) { 
  274. // TODO: Add more sink validation? 
  275. if (is_bool($options['sink'])) { 
  276. throw new \InvalidArgumentException('sink must not be a boolean'); 
  277.  
  278. $request = Psr7\modify_request($request, $modify); 
  279. if ($request->getBody() instanceof Psr7\MultipartStream) { 
  280. // Use a multipart/form-data POST if a Content-Type is not set. 
  281. $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' 
  282. . $request->getBody()->getBoundary(); 
  283.  
  284. // Merge in conditional headers if they are not present. 
  285. if (isset($options['_conditional'])) { 
  286. // Build up the changes so it's in a single clone of the message. 
  287. $modify = []; 
  288. foreach ($options['_conditional'] as $k => $v) { 
  289. if (!$request->hasHeader($k)) { 
  290. $modify['set_headers'][$k] = $v; 
  291. $request = Psr7\modify_request($request, $modify); 
  292. // Don't pass this internal value along to middleware/handlers. 
  293. unset($options['_conditional']); 
  294.  
  295. return $request; 
  296.  
  297. private function invalidBody() 
  298. throw new \InvalidArgumentException('Passing in the "body" request ' 
  299. . 'option as an array to send a POST request has been deprecated. ' 
  300. . 'Please use the "form_params" request option to send a ' 
  301. . 'application/x-www-form-urlencoded request, or a the "multipart" ' 
  302. . 'request option to send a multipart/form-data request.');