Advertisement
Guest User

Classs

a guest
Mar 18th, 2015
372
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.18 KB | None | 0 0
  1. <?php
  2. namespace GuzzleHttp;
  3.  
  4. use GuzzleHttp\Event\HasEmitterTrait;
  5. use GuzzleHttp\Message\MessageFactory;
  6. use GuzzleHttp\Message\MessageFactoryInterface;
  7. use GuzzleHttp\Message\RequestInterface;
  8. use GuzzleHttp\Message\FutureResponse;
  9. use GuzzleHttp\Ring\Client\Middleware;
  10. use GuzzleHttp\Ring\Client\CurlMultiHandler;
  11. use GuzzleHttp\Ring\Client\CurlHandler;
  12. use GuzzleHttp\Ring\Client\StreamHandler;
  13. use GuzzleHttp\Ring\Core;
  14. use GuzzleHttp\Ring\Future\FutureInterface;
  15. use GuzzleHttp\Exception\RequestException;
  16. use React\Promise\FulfilledPromise;
  17. use React\Promise\RejectedPromise;
  18.  
  19. /**
  20. * HTTP client
  21. */
  22. class Client implements ClientInterface
  23. {
  24. use HasEmitterTrait;
  25.  
  26. /** @var MessageFactoryInterface Request factory used by the client */
  27. private $messageFactory;
  28.  
  29. /** @var Url Base URL of the client */
  30. private $baseUrl;
  31.  
  32. /** @var array Default request options */
  33. private $defaults;
  34.  
  35. /** @var callable Request state machine */
  36. private $fsm;
  37.  
  38. /**
  39. * Clients accept an array of constructor parameters.
  40. *
  41. * Here's an example of creating a client using an URI template for the
  42. * client's base_url and an array of default request options to apply
  43. * to each request:
  44. *
  45. * $client = new Client([
  46. * 'base_url' => [
  47. * 'http://www.foo.com/{version}/',
  48. * ['version' => '123']
  49. * ],
  50. * 'defaults' => [
  51. * 'timeout' => 10,
  52. * 'allow_redirects' => false,
  53. * 'proxy' => '192.168.16.1:10'
  54. * ]
  55. * ]);
  56. *
  57. * @param array $config Client configuration settings
  58. * - base_url: Base URL of the client that is merged into relative URLs.
  59. * Can be a string or an array that contains a URI template followed
  60. * by an associative array of expansion variables to inject into the
  61. * URI template.
  62. * - handler: callable RingPHP handler used to transfer requests
  63. * - message_factory: Factory used to create request and response object
  64. * - defaults: Default request options to apply to each request
  65. * - emitter: Event emitter used for request events
  66. * - fsm: (internal use only) The request finite state machine. A
  67. * function that accepts a transaction and optional final state. The
  68. * function is responsible for transitioning a request through its
  69. * lifecycle events.
  70. */
  71. public function __construct(array $config = [])
  72. {
  73. $this->configureBaseUrl($config);
  74. $this->configureDefaults($config);
  75.  
  76. if (isset($config['emitter'])) {
  77. $this->emitter = $config['emitter'];
  78. }
  79.  
  80. $this->messageFactory = isset($config['message_factory'])
  81. ? $config['message_factory']
  82. : new MessageFactory();
  83.  
  84. if (isset($config['fsm'])) {
  85. $this->fsm = $config['fsm'];
  86. } else {
  87. if (isset($config['handler'])) {
  88. $handler = $config['handler'];
  89. } elseif (isset($config['adapter'])) {
  90. $handler = $config['adapter'];
  91. } else {
  92. $handler = static::getDefaultHandler();
  93. }
  94. $this->fsm = new RequestFsm($handler, $this->messageFactory);
  95. }
  96. }
  97.  
  98. /**
  99. * Create a default handler to use based on the environment
  100. *
  101. * @throws \RuntimeException if no viable Handler is available.
  102. */
  103. public static function getDefaultHandler()
  104. {
  105. $default = $future = $streaming = null;
  106.  
  107. if (extension_loaded('curl')) {
  108. $config = [
  109. 'select_timeout' => getenv('GUZZLE_CURL_SELECT_TIMEOUT') ?: 1
  110. ];
  111. if ($maxHandles = getenv('GUZZLE_CURL_MAX_HANDLES')) {
  112. $config['max_handles'] = $maxHandles;
  113. }
  114. $future = new CurlMultiHandler($config);
  115. if (function_exists('curl_reset')) {
  116. $default = new CurlHandler();
  117. }
  118. }
  119.  
  120. if (ini_get('allow_url_fopen')) {
  121. $streaming = new StreamHandler();
  122. }
  123.  
  124. if (!($default = ($default ?: $future) ?: $streaming)) {
  125. throw new \RuntimeException('Guzzle requires cURL, the '
  126. . 'allow_url_fopen ini setting, or a custom HTTP handler.');
  127. }
  128.  
  129. $handler = $default;
  130.  
  131. if ($streaming && $streaming !== $default) {
  132. $handler = Middleware::wrapStreaming($default, $streaming);
  133. }
  134.  
  135. if ($future) {
  136. $handler = Middleware::wrapFuture($handler, $future);
  137. }
  138.  
  139. return $handler;
  140. }
  141.  
  142. /**
  143. * Get the default User-Agent string to use with Guzzle
  144. *
  145. * @return string
  146. */
  147. public static function getDefaultUserAgent()
  148. {
  149. static $defaultAgent = '';
  150. if (!$defaultAgent) {
  151. $defaultAgent = 'Guzzle/' . self::VERSION;
  152. if (extension_loaded('curl')) {
  153. $defaultAgent .= ' curl/' . curl_version()['version'];
  154. }
  155. $defaultAgent .= ' PHP/' . PHP_VERSION;
  156. }
  157.  
  158. return $defaultAgent;
  159. }
  160.  
  161. public function getDefaultOption($keyOrPath = null)
  162. {
  163. return $keyOrPath === null
  164. ? $this->defaults
  165. : Utils::getPath($this->defaults, $keyOrPath);
  166. }
  167.  
  168. public function setDefaultOption($keyOrPath, $value)
  169. {
  170. Utils::setPath($this->defaults, $keyOrPath, $value);
  171. }
  172.  
  173. public function getBaseUrl()
  174. {
  175. return (string) $this->baseUrl;
  176. }
  177.  
  178. public function createRequest($method, $url = null, array $options = [])
  179. {
  180. $options = $this->mergeDefaults($options);
  181. // Use a clone of the client's emitter
  182. $options['config']['emitter'] = clone $this->getEmitter();
  183. $url = $url || (is_string($url) && strlen($url))
  184. ? $this->buildUrl($url)
  185. : (string) $this->baseUrl;
  186.  
  187. return $this->messageFactory->createRequest($method, $url, $options);
  188. }
  189.  
  190. public function get($url = null, $options = [])
  191. {
  192. return $this->send($this->createRequest('GET', $url, $options));
  193. }
  194.  
  195. public function head($url = null, array $options = [])
  196. {
  197. return $this->send($this->createRequest('HEAD', $url, $options));
  198. }
  199.  
  200. public function delete($url = null, array $options = [])
  201. {
  202. return $this->send($this->createRequest('DELETE', $url, $options));
  203. }
  204.  
  205. public function put($url = null, array $options = [])
  206. {
  207. return $this->send($this->createRequest('PUT', $url, $options));
  208. }
  209.  
  210. public function patch($url = null, array $options = [])
  211. {
  212. return $this->send($this->createRequest('PATCH', $url, $options));
  213. }
  214.  
  215. public function post($url = null, array $options = [])
  216. {
  217. return $this->send($this->createRequest('POST', $url, $options));
  218. }
  219.  
  220. public function options($url = null, array $options = [])
  221. {
  222. return $this->send($this->createRequest('OPTIONS', $url, $options));
  223. }
  224.  
  225. public function send(RequestInterface $request)
  226. {
  227. $isFuture = $request->getConfig()->get('future');
  228. $trans = new Transaction($this, $request, $isFuture);
  229. $fn = $this->fsm;
  230.  
  231. try {
  232. $fn($trans);
  233. if ($isFuture) {
  234. // Turn the normal response into a future if needed.
  235. return $trans->response instanceof FutureInterface
  236. ? $trans->response
  237. : new FutureResponse(new FulfilledPromise($trans->response));
  238. }
  239. // Resolve deep futures if this is not a future
  240. // transaction. This accounts for things like retries
  241. // that do not have an immediate side-effect.
  242. while ($trans->response instanceof FutureInterface) {
  243. $trans->response = $trans->response->wait();
  244. }
  245. return $trans->response;
  246. } catch (\Exception $e) {
  247. if ($isFuture) {
  248. // Wrap the exception in a promise
  249. return new FutureResponse(new RejectedPromise($e));
  250. }
  251. throw RequestException::wrapException($trans->request, $e);
  252. }
  253. }
  254.  
  255. /**
  256. * Get an array of default options to apply to the client
  257. *
  258. * @return array
  259. */
  260. protected function getDefaultOptions()
  261. {
  262. $settings = [
  263. 'allow_redirects' => true,
  264. 'exceptions' => true,
  265. 'decode_content' => true,
  266. 'verify' => true
  267. ];
  268.  
  269. // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set
  270. if ($proxy = getenv('HTTP_PROXY')) {
  271. $settings['proxy']['http'] = $proxy;
  272. }
  273.  
  274. if ($proxy = getenv('HTTPS_PROXY')) {
  275. $settings['proxy']['https'] = $proxy;
  276. }
  277.  
  278. return $settings;
  279. }
  280.  
  281. /**
  282. * Expand a URI template and inherit from the base URL if it's relative
  283. *
  284. * @param string|array $url URL or an array of the URI template to expand
  285. * followed by a hash of template varnames.
  286. * @return string
  287. * @throws \InvalidArgumentException
  288. */
  289. private function buildUrl($url)
  290. {
  291. // URI template (absolute or relative)
  292. if (!is_array($url)) {
  293. return strpos($url, '://')
  294. ? (string) $url
  295. : (string) $this->baseUrl->combine($url);
  296. }
  297.  
  298. if (!isset($url[1])) {
  299. throw new \InvalidArgumentException('You must provide a hash of '
  300. . 'varname options in the second element of a URL array.');
  301. }
  302.  
  303. // Absolute URL
  304. if (strpos($url[0], '://')) {
  305. return Utils::uriTemplate($url[0], $url[1]);
  306. }
  307.  
  308. // Combine the relative URL with the base URL
  309. return (string) $this->baseUrl->combine(
  310. Utils::uriTemplate($url[0], $url[1])
  311. );
  312. }
  313.  
  314. private function configureBaseUrl(&$config)
  315. {
  316. if (!isset($config['base_url'])) {
  317. $this->baseUrl = new Url('', '');
  318. } elseif (!is_array($config['base_url'])) {
  319. $this->baseUrl = Url::fromString($config['base_url']);
  320. } elseif (count($config['base_url']) < 2) {
  321. throw new \InvalidArgumentException('You must provide a hash of '
  322. . 'varname options in the second element of a base_url array.');
  323. } else {
  324. $this->baseUrl = Url::fromString(
  325. Utils::uriTemplate(
  326. $config['base_url'][0],
  327. $config['base_url'][1]
  328. )
  329. );
  330. $config['base_url'] = (string) $this->baseUrl;
  331. }
  332. }
  333.  
  334. private function configureDefaults($config)
  335. {
  336. if (!isset($config['defaults'])) {
  337. $this->defaults = $this->getDefaultOptions();
  338. } else {
  339. $this->defaults = array_replace(
  340. $this->getDefaultOptions(),
  341. $config['defaults']
  342. );
  343. }
  344.  
  345. // Add the default user-agent header
  346. if (!isset($this->defaults['headers'])) {
  347. $this->defaults['headers'] = [
  348. 'User-Agent' => static::getDefaultUserAgent()
  349. ];
  350. } elseif (!Core::hasHeader($this->defaults, 'User-Agent')) {
  351. // Add the User-Agent header if one was not already set
  352. $this->defaults['headers']['User-Agent'] = static::getDefaultUserAgent();
  353. }
  354. }
  355.  
  356. /**
  357. * Merges default options into the array passed by reference.
  358. *
  359. * @param array $options Options to modify by reference
  360. *
  361. * @return array
  362. */
  363. private function mergeDefaults($options)
  364. {
  365. $defaults = $this->defaults;
  366.  
  367. // Case-insensitively merge in default headers if both defaults and
  368. // options have headers specified.
  369. if (!empty($defaults['headers']) && !empty($options['headers'])) {
  370. // Create a set of lowercased keys that are present.
  371. $lkeys = [];
  372. foreach (array_keys($options['headers']) as $k) {
  373. $lkeys[strtolower($k)] = true;
  374. }
  375. // Merge in lowercase default keys when not present in above set.
  376. foreach ($defaults['headers'] as $key => $value) {
  377. if (!isset($lkeys[strtolower($key)])) {
  378. $options['headers'][$key] = $value;
  379. }
  380. }
  381. // No longer need to merge in headers.
  382. unset($defaults['headers']);
  383. }
  384.  
  385. $result = array_replace_recursive($defaults, $options);
  386. foreach ($options as $k => $v) {
  387. if ($v === null) {
  388. unset($result[$k]);
  389. }
  390. }
  391.  
  392. return $result;
  393. }
  394.  
  395. /**
  396. * @deprecated Use {@see GuzzleHttp\Pool} instead.
  397. * @see GuzzleHttp\Pool
  398. */
  399. public function sendAll($requests, array $options = [])
  400. {
  401. Pool::send($this, $requests, $options);
  402. }
  403. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement