/includes/api-libs/Google/IO/Curl.php

  1. <?php 
  2. /** 
  3. * Copyright 2014 Google Inc. 
  4. * 
  5. * Licensed under the Apache License, Version 2.0 (the "License"); 
  6. * you may not use this file except in compliance with the License. 
  7. * You may obtain a copy of the License at 
  8. * 
  9. * http://www.apache.org/licenses/LICENSE-2.0 
  10. * 
  11. * Unless required by applicable law or agreed to in writing, software 
  12. * distributed under the License is distributed on an "AS IS" BASIS,  
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  14. * See the License for the specific language governing permissions and 
  15. * limitations under the License. 
  16. */ 
  17.  
  18. /** 
  19. * Curl based implementation of Google_IO. 
  20. * 
  21. * @author Stuart Langley <slangley@google.com> 
  22. */ 
  23.  
  24. require_once realpath(dirname(__FILE__) . '/../../../autoload.php'); 
  25.  
  26. class Google_IO_Curl extends Google_IO_Abstract 
  27. // cURL hex representation of version 7.30.0 
  28. const NO_QUIRK_VERSION = 0x071E00; 
  29.  
  30. private $options = array(); 
  31.  
  32. public function __construct(Google_Client $client) 
  33. if (!extension_loaded('curl')) { 
  34. $error = 'The cURL IO handler requires the cURL extension to be enabled'; 
  35. $client->getLogger()->critical($error); 
  36. throw new Google_IO_Exception($error); 
  37.  
  38. parent::__construct($client); 
  39.  
  40. /** 
  41. * Execute an HTTP Request 
  42. * 
  43. * @param Google_HttpRequest $request the http request to be executed 
  44. * @return Google_HttpRequest http request with the response http code,  
  45. * response headers and response body filled in 
  46. * @throws Google_IO_Exception on curl or IO error 
  47. */ 
  48. public function executeRequest(Google_Http_Request $request) 
  49. $curl = curl_init(); 
  50.  
  51. if ($request->getPostBody()) { 
  52. curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getPostBody()); 
  53.  
  54. $requestHeaders = $request->getRequestHeaders(); 
  55. if ($requestHeaders && is_array($requestHeaders)) { 
  56. $curlHeaders = array(); 
  57. foreach ($requestHeaders as $k => $v) { 
  58. $curlHeaders[] = "$k: $v"; 
  59. curl_setopt($curl, CURLOPT_HTTPHEADER, $curlHeaders); 
  60. curl_setopt($curl, CURLOPT_URL, $request->getUrl()); 
  61.  
  62. curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $request->getRequestMethod()); 
  63. curl_setopt($curl, CURLOPT_USERAGENT, $request->getUserAgent()); 
  64.  
  65. curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); 
  66. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); 
  67. // 1 is CURL_SSLVERSION_TLSv1, which is not always defined in PHP. 
  68. curl_setopt($curl, CURLOPT_SSLVERSION, 1); 
  69. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
  70. curl_setopt($curl, CURLOPT_HEADER, true); 
  71.  
  72. if ($request->canGzip()) { 
  73. curl_setopt($curl, CURLOPT_ENCODING, 'gzip, deflate'); 
  74.  
  75. foreach ($this->options as $key => $var) { 
  76. curl_setopt($curl, $key, $var); 
  77.  
  78. if (!isset($this->options[CURLOPT_CAINFO])) { 
  79. curl_setopt($curl, CURLOPT_CAINFO, dirname(__FILE__) . '/cacerts.pem'); 
  80.  
  81. $this->client->getLogger()->debug( 
  82. 'cURL request',  
  83. array( 
  84. 'url' => $request->getUrl(),  
  85. 'method' => $request->getRequestMethod(),  
  86. 'headers' => $requestHeaders,  
  87. 'body' => $request->getPostBody() 
  88. ); 
  89.  
  90. $response = curl_exec($curl); 
  91. if ($response === false) { 
  92. $error = curl_error($curl); 
  93. $code = curl_errno($curl); 
  94. $map = $this->client->getClassConfig('Google_IO_Exception', 'retry_map'); 
  95.  
  96. $this->client->getLogger()->error('cURL ' . $error); 
  97. throw new Google_IO_Exception($error, $code, null, $map); 
  98. $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); 
  99.  
  100. list($responseHeaders, $responseBody) = $this->parseHttpResponse($response, $headerSize); 
  101. $responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); 
  102.  
  103. $this->client->getLogger()->debug( 
  104. 'cURL response',  
  105. array( 
  106. 'code' => $responseCode,  
  107. 'headers' => $responseHeaders,  
  108. 'body' => $responseBody,  
  109. ); 
  110.  
  111. return array($responseBody, $responseHeaders, $responseCode); 
  112.  
  113. /** 
  114. * Set options that update the transport implementation's behavior. 
  115. * @param $options 
  116. */ 
  117. public function setOptions($options) 
  118. $this->options = $options + $this->options; 
  119.  
  120. /** 
  121. * Set the maximum request time in seconds. 
  122. * @param $timeout in seconds 
  123. */ 
  124. public function setTimeout($timeout) 
  125. // Since this timeout is really for putting a bound on the time 
  126. // we'll set them both to the same. If you need to specify a longer 
  127. // CURLOPT_TIMEOUT, or a tigher CONNECTTIMEOUT, the best thing to 
  128. // do is use the setOptions method for the values individually. 
  129. $this->options[CURLOPT_CONNECTTIMEOUT] = $timeout; 
  130. $this->options[CURLOPT_TIMEOUT] = $timeout; 
  131.  
  132. /** 
  133. * Get the maximum request time in seconds. 
  134. * @return timeout in seconds 
  135. */ 
  136. public function getTimeout() 
  137. return $this->options[CURLOPT_TIMEOUT]; 
  138.  
  139. /** 
  140. * Test for the presence of a cURL header processing bug 
  141. * 
  142. * {@inheritDoc} 
  143. * 
  144. * @return boolean 
  145. */ 
  146. protected function needsQuirk() 
  147. $ver = curl_version(); 
  148. $versionNum = $ver['version_number']; 
  149. return $versionNum < Google_IO_Curl::NO_QUIRK_VERSION; 
.