External.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <?php
  2. /**
  3. * [Request_Client_External] provides a wrapper for all external request
  4. * processing. This class should be extended by all drivers handling external
  5. * requests.
  6. *
  7. * Supported out of the box:
  8. * - Curl (default)
  9. * - PECL HTTP
  10. * - Streams
  11. *
  12. * To select a specific external driver to use as the default driver, set the
  13. * following property within the Application bootstrap. Alternatively, the
  14. * client can be injected into the request object.
  15. *
  16. * @example
  17. *
  18. * // In application bootstrap
  19. * Request_Client_External::$client = 'Request_Client_Stream';
  20. *
  21. * // Add client to request
  22. * $request = Request::factory('http://some.host.tld/foo/bar')
  23. * ->client(Request_Client_External::factory('Request_Client_HTTP));
  24. *
  25. * @package Kohana
  26. * @category Base
  27. * @author Kohana Team
  28. * @copyright (c) Kohana Team
  29. * @license https://koseven.ga/LICENSE.md
  30. * @uses [PECL HTTP](http://php.net/manual/en/book.http.php)
  31. */
  32. abstract class Kohana_Request_Client_External extends Request_Client {
  33. /**
  34. * Use:
  35. * - Request_Client_Curl (default)
  36. * - Request_Client_HTTP
  37. * - Request_Client_Stream
  38. *
  39. * @var string defines the external client to use by default
  40. */
  41. public static $client = 'Request_Client_Curl';
  42. /**
  43. * Factory method to create a new Request_Client_External object based on
  44. * the client name passed, or defaulting to Request_Client_External::$client
  45. * by default.
  46. *
  47. * Request_Client_External::$client can be set in the application bootstrap.
  48. *
  49. * @param array $params parameters to pass to the client
  50. * @param string $client external client to use
  51. * @return Request_Client_External
  52. * @throws Request_Exception
  53. */
  54. public static function factory(array $params = [], $client = NULL)
  55. {
  56. if ($client === NULL)
  57. {
  58. $client = Request_Client_External::$client;
  59. }
  60. $client = new $client($params);
  61. if ( ! $client instanceof Request_Client_External)
  62. {
  63. throw new Request_Exception('Selected client is not a Request_Client_External object.');
  64. }
  65. return $client;
  66. }
  67. /**
  68. * @var array curl options
  69. * @link http://www.php.net/manual/function.curl-setopt
  70. * @link http://www.php.net/manual/http.request.options
  71. */
  72. protected $_options = [];
  73. /**
  74. * Processes the request, executing the controller action that handles this
  75. * request, determined by the [Route].
  76. *
  77. * 1. Before the controller action is called, the [Controller::before] method
  78. * will be called.
  79. * 2. Next the controller action will be called.
  80. * 3. After the controller action is called, the [Controller::after] method
  81. * will be called.
  82. *
  83. * By default, the output from the controller is captured and returned, and
  84. * no headers are sent.
  85. *
  86. * $request->execute();
  87. *
  88. * @param Request $request A request object
  89. * @param Response $response A response object
  90. * @return Response
  91. * @throws Kohana_Exception
  92. * @uses [Kohana::$profiling]
  93. * @uses [Profiler]
  94. */
  95. public function execute_request(Request $request, Response $response)
  96. {
  97. if (Kohana::$profiling)
  98. {
  99. // Set the benchmark name
  100. $benchmark = '"'.$request->uri().'"';
  101. if ($request !== Request::$initial AND Request::$current)
  102. {
  103. // Add the parent request uri
  104. $benchmark .= ' « "'.Request::$current->uri().'"';
  105. }
  106. // Start benchmarking
  107. $benchmark = Profiler::start('Requests', $benchmark);
  108. }
  109. // Store the current active request and replace current with new request
  110. $previous = Request::$current;
  111. Request::$current = $request;
  112. // Resolve the POST fields
  113. if ($post = $request->post())
  114. {
  115. $request->body(http_build_query($post, '', '&'))
  116. ->headers('content-type', 'application/x-www-form-urlencoded; charset='.Kohana::$charset);
  117. }
  118. $request->headers('content-length', (string) $request->content_length());
  119. // If Kohana expose, set the user-agent
  120. if (Kohana::$expose)
  121. {
  122. $request->headers('user-agent', Kohana::version());
  123. }
  124. try
  125. {
  126. $response = $this->_send_message($request, $response);
  127. }
  128. catch (Exception $e)
  129. {
  130. // Restore the previous request
  131. Request::$current = $previous;
  132. if (isset($benchmark))
  133. {
  134. // Delete the benchmark, it is invalid
  135. Profiler::delete($benchmark);
  136. }
  137. // Re-throw the exception
  138. throw $e;
  139. }
  140. // Restore the previous request
  141. Request::$current = $previous;
  142. if (isset($benchmark))
  143. {
  144. // Stop the benchmark
  145. Profiler::stop($benchmark);
  146. }
  147. // Return the response
  148. return $response;
  149. }
  150. /**
  151. * Set and get options for this request.
  152. *
  153. * @param mixed $key Option name, or array of options
  154. * @param mixed $value Option value
  155. * @return mixed
  156. * @return Request_Client_External
  157. */
  158. public function options($key = NULL, $value = NULL)
  159. {
  160. if ($key === NULL)
  161. return $this->_options;
  162. if (is_array($key))
  163. {
  164. $this->_options = $key;
  165. }
  166. elseif ($value === NULL)
  167. {
  168. return Arr::get($this->_options, $key);
  169. }
  170. else
  171. {
  172. $this->_options[$key] = $value;
  173. }
  174. return $this;
  175. }
  176. /**
  177. * Sends the HTTP message [Request] to a remote server and processes
  178. * the response.
  179. *
  180. * @param Request $request Request to send
  181. * @param Response $response Response to send
  182. * @return Response
  183. */
  184. abstract protected function _send_message(Request $request, Response $response);
  185. }