Adapter.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. /**
  3. * Base class for HTTP_Request2 adapters
  4. *
  5. * PHP version 5
  6. *
  7. * LICENSE
  8. *
  9. * This source file is subject to BSD 3-Clause License that is bundled
  10. * with this package in the file LICENSE and available at the URL
  11. * https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
  12. *
  13. * @category HTTP
  14. * @package HTTP_Request2
  15. * @author Alexey Borzov <avb@php.net>
  16. * @copyright 2008-2016 Alexey Borzov <avb@php.net>
  17. * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
  18. * @link http://pear.php.net/package/HTTP_Request2
  19. */
  20. /**
  21. * Class representing a HTTP response
  22. */
  23. require_once 'HTTP/Request2/Response.php';
  24. /**
  25. * Base class for HTTP_Request2 adapters
  26. *
  27. * HTTP_Request2 class itself only defines methods for aggregating the request
  28. * data, all actual work of sending the request to the remote server and
  29. * receiving its response is performed by adapters.
  30. *
  31. * @category HTTP
  32. * @package HTTP_Request2
  33. * @author Alexey Borzov <avb@php.net>
  34. * @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
  35. * @version Release: 2.3.0
  36. * @link http://pear.php.net/package/HTTP_Request2
  37. */
  38. abstract class HTTP_Request2_Adapter
  39. {
  40. /**
  41. * A list of methods that MUST NOT have a request body, per RFC 2616
  42. * @var array
  43. */
  44. protected static $bodyDisallowed = array('TRACE');
  45. /**
  46. * Methods having defined semantics for request body
  47. *
  48. * Content-Length header (indicating that the body follows, section 4.3 of
  49. * RFC 2616) will be sent for these methods even if no body was added
  50. *
  51. * @var array
  52. * @link http://pear.php.net/bugs/bug.php?id=12900
  53. * @link http://pear.php.net/bugs/bug.php?id=14740
  54. */
  55. protected static $bodyRequired = array('POST', 'PUT');
  56. /**
  57. * Request being sent
  58. * @var HTTP_Request2
  59. */
  60. protected $request;
  61. /**
  62. * Request body
  63. * @var string|resource|HTTP_Request2_MultipartBody
  64. * @see HTTP_Request2::getBody()
  65. */
  66. protected $requestBody;
  67. /**
  68. * Length of the request body
  69. * @var integer
  70. */
  71. protected $contentLength;
  72. /**
  73. * Sends request to the remote server and returns its response
  74. *
  75. * @param HTTP_Request2 $request HTTP request message
  76. *
  77. * @return HTTP_Request2_Response
  78. * @throws HTTP_Request2_Exception
  79. */
  80. abstract public function sendRequest(HTTP_Request2 $request);
  81. /**
  82. * Calculates length of the request body, adds proper headers
  83. *
  84. * @param array &$headers associative array of request headers, this method
  85. * will add proper 'Content-Length' and 'Content-Type'
  86. * headers to this array (or remove them if not needed)
  87. */
  88. protected function calculateRequestLength(&$headers)
  89. {
  90. $this->requestBody = $this->request->getBody();
  91. if (is_string($this->requestBody)) {
  92. $this->contentLength = strlen($this->requestBody);
  93. } elseif (is_resource($this->requestBody)) {
  94. $stat = fstat($this->requestBody);
  95. $this->contentLength = $stat['size'];
  96. rewind($this->requestBody);
  97. } else {
  98. $this->contentLength = $this->requestBody->getLength();
  99. $headers['content-type'] = 'multipart/form-data; boundary=' .
  100. $this->requestBody->getBoundary();
  101. $this->requestBody->rewind();
  102. }
  103. if (in_array($this->request->getMethod(), self::$bodyDisallowed)
  104. || 0 == $this->contentLength
  105. ) {
  106. // No body: send a Content-Length header nonetheless (request #12900),
  107. // but do that only for methods that require a body (bug #14740)
  108. if (in_array($this->request->getMethod(), self::$bodyRequired)) {
  109. $headers['content-length'] = 0;
  110. } else {
  111. unset($headers['content-length']);
  112. // if the method doesn't require a body and doesn't have a
  113. // body, don't send a Content-Type header. (request #16799)
  114. unset($headers['content-type']);
  115. }
  116. } else {
  117. if (empty($headers['content-type'])) {
  118. $headers['content-type'] = 'application/x-www-form-urlencoded';
  119. }
  120. // Content-Length should not be sent for chunked Transfer-Encoding (bug #20125)
  121. if (!isset($headers['transfer-encoding'])) {
  122. $headers['content-length'] = $this->contentLength;
  123. }
  124. }
  125. }
  126. }
  127. ?>