Curl.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <?php
  2. /**
  3. * Curl driver performs external requests using the
  4. * php-curl extension.
  5. *
  6. * NOTE: This driver is not used by default. To use it as default call:
  7. *
  8. * @package KO7\Request
  9. *
  10. * @copyright (c) 2007-2016 Kohana Team
  11. * @copyright (c) since 2016 Koseven Team
  12. * @license https://koseven.dev/LICENSE
  13. *
  14. */
  15. class KO7_Request_Client_Curl extends Request_Client_External {
  16. /**
  17. * Sends the HTTP message [Request] to a remote server and processes
  18. * the response.
  19. *
  20. * @param Request $request request to send
  21. * @param Response $response response to send
  22. *
  23. * @throws Request_Exception
  24. *
  25. * @return Response
  26. */
  27. public function _send_message(Request $request, Response $response): Response
  28. {
  29. $options = [];
  30. // Set the request method
  31. $options = $this->_set_curl_request_method($request, $options);
  32. // Set the request body. This is perfectly legal in CURL even
  33. // if using a request other than POST. PUT does support this method
  34. // and DOES NOT require writing data to disk before putting it, if
  35. // reading the PHP docs you may have got that impression. SdF
  36. // This will also add a Content-Type: application/x-www-form-urlencoded header unless you override it
  37. if ($body = $request->body())
  38. {
  39. $options[CURLOPT_POSTFIELDS] = $body;
  40. }
  41. // Process headers
  42. if ($headers = $request->headers())
  43. {
  44. $http_headers = [];
  45. foreach ($headers as $key => $value)
  46. {
  47. $http_headers[] = $key . ': ' . $value;
  48. }
  49. $options[CURLOPT_HTTPHEADER] = $http_headers;
  50. }
  51. // Process cookies
  52. if ($cookies = $request->cookie())
  53. {
  54. $options[CURLOPT_COOKIE] = http_build_query($cookies, NULL, '; ');
  55. }
  56. // Get any existing response headers
  57. $response_header = $response->headers();
  58. // Implement the standard parsing parameters
  59. $options[CURLOPT_HEADERFUNCTION] = [$response_header, 'parse_header_string'];
  60. $this->_options[CURLOPT_RETURNTRANSFER] = TRUE;
  61. $this->_options[CURLOPT_HEADER] = FALSE;
  62. // Apply any additional options set to
  63. $options += $this->_options;
  64. $uri = $request->uri();
  65. if ($query = $request->query())
  66. {
  67. $uri .= '?' . http_build_query($query, NULL, '&');
  68. }
  69. //Suppress warning: Array keys must be CURLOPT constants or equivalent integer values
  70. $curlopt_constants_hash = array_flip(get_defined_constants(true)['curl']);
  71. foreach ($options as $option_key => $option_value) {
  72. if ( !isset($curlopt_constants_hash[$option_key]) ) {
  73. throw new Request_Exception(
  74. 'CURL options are invalid :$option_key in :options', [':$option_key' => $option_key]
  75. );
  76. }
  77. }
  78. // Open a new remote connection
  79. $curl = curl_init($uri);
  80. // Set connection options - Throws an Exception if options are invalid
  81. try
  82. {
  83. curl_setopt_array($curl, $options);
  84. }
  85. catch (Exception $e)
  86. {
  87. throw new Request_Exception($e->getMessage());
  88. }
  89. // Get the response body
  90. $body = curl_exec($curl);
  91. // Get the response information
  92. $code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
  93. if ($body === FALSE)
  94. {
  95. $error = curl_error($curl);
  96. }
  97. // Close the connection
  98. curl_close($curl);
  99. if (isset($error))
  100. {
  101. throw new Request_Exception(
  102. 'Error fetching remote :url [ status :code ] :error',
  103. [':url' => $request->url(), ':code' => $code, ':error' => $error]
  104. );
  105. }
  106. // Build the response
  107. $response->status($code)->body($body);
  108. return $response;
  109. }
  110. /**
  111. * Sets the appropriate curl request options. Uses the responding option
  112. * for POST or CURLOPT_CUSTOMREQUEST otherwise
  113. *
  114. * @param Request $request
  115. * @param array $options
  116. *
  117. * @return array
  118. */
  119. public function _set_curl_request_method(Request $request, array $options)
  120. {
  121. if ($request->method() === Request::POST)
  122. {
  123. $options[CURLOPT_POST] = TRUE;
  124. }
  125. else
  126. {
  127. $options[CURLOPT_CUSTOMREQUEST] = $request->method();
  128. }
  129. return $options;
  130. }
  131. }