Stream.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. /**
  3. * [Request_Client_External] Stream driver performs external requests using php
  4. * sockets. To use this driver, ensure the following is completed
  5. * before executing an external request- ideally in the application bootstrap.
  6. *
  7. * @example
  8. *
  9. * // In application bootstrap
  10. * Request_Client_External::$client = 'Request_Client_Stream';
  11. *
  12. * @package Kohana
  13. * @category Base
  14. * @author Kohana Team
  15. * @copyright (c) Kohana Team
  16. * @license https://koseven.ga/LICENSE.md
  17. * @uses [PHP Streams](http://php.net/manual/en/book.stream.php)
  18. */
  19. class Kohana_Request_Client_Stream extends Request_Client_External {
  20. /**
  21. * Sends the HTTP message [Request] to a remote server and processes
  22. * the response.
  23. *
  24. * @param Request $request request to send
  25. * @param Response $request response to send
  26. * @return Response
  27. * @uses [PHP cURL](http://php.net/manual/en/book.curl.php)
  28. */
  29. public function _send_message(Request $request, Response $response)
  30. {
  31. // Calculate stream mode
  32. $mode = ($request->method() === HTTP_Request::GET) ? 'r' : 'r+';
  33. // Process cookies
  34. if ($cookies = $request->cookie())
  35. {
  36. $request->headers('cookie', http_build_query($cookies, '', '; '));
  37. }
  38. // Get the message body
  39. $body = $request->body();
  40. if (is_resource($body))
  41. {
  42. $body = stream_get_contents($body);
  43. }
  44. // Set the content length
  45. $request->headers('content-length', (string) strlen($body));
  46. list($protocol) = explode('/', $request->protocol());
  47. // Create the context
  48. $options = [
  49. strtolower($protocol) => [
  50. 'method' => $request->method(),
  51. 'header' => (string) $request->headers(),
  52. 'content' => $body
  53. ]
  54. ];
  55. // Create the context stream
  56. $context = stream_context_create($options);
  57. stream_context_set_option($context, $this->_options);
  58. $uri = $request->uri();
  59. if ($query = $request->query())
  60. {
  61. $uri .= '?'.http_build_query($query, '', '&');
  62. }
  63. $stream = fopen($uri, $mode, FALSE, $context);
  64. $meta_data = stream_get_meta_data($stream);
  65. // Get the HTTP response code
  66. $http_response = array_shift($meta_data['wrapper_data']);
  67. if (preg_match_all('/(\w+\/\d\.\d) (\d{3})/', $http_response, $matches) !== FALSE)
  68. {
  69. $protocol = $matches[1][0];
  70. $status = (int) $matches[2][0];
  71. }
  72. else
  73. {
  74. $protocol = NULL;
  75. $status = NULL;
  76. }
  77. // Get any exisiting response headers
  78. $response_header = $response->headers();
  79. // Process headers
  80. array_map([$response_header, 'parse_header_string'], [], $meta_data['wrapper_data']);
  81. $response->status($status)
  82. ->protocol($protocol)
  83. ->body(stream_get_contents($stream));
  84. // Close the stream after use
  85. fclose($stream);
  86. return $response;
  87. }
  88. }