EasyHandle.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <?php
  2. namespace GuzzleHttp\Handler;
  3. use GuzzleHttp\Psr7\Response;
  4. use GuzzleHttp\Utils;
  5. use Psr\Http\Message\RequestInterface;
  6. use Psr\Http\Message\ResponseInterface;
  7. use Psr\Http\Message\StreamInterface;
  8. /**
  9. * Represents a cURL easy handle and the data it populates.
  10. *
  11. * @internal
  12. */
  13. final class EasyHandle
  14. {
  15. /**
  16. * @var resource|\CurlHandle cURL resource
  17. */
  18. public $handle;
  19. /**
  20. * @var StreamInterface Where data is being written
  21. */
  22. public $sink;
  23. /**
  24. * @var array Received HTTP headers so far
  25. */
  26. public $headers = [];
  27. /**
  28. * @var ResponseInterface|null Received response (if any)
  29. */
  30. public $response;
  31. /**
  32. * @var RequestInterface Request being sent
  33. */
  34. public $request;
  35. /**
  36. * @var array Request options
  37. */
  38. public $options = [];
  39. /**
  40. * @var int cURL error number (if any)
  41. */
  42. public $errno = 0;
  43. /**
  44. * @var \Throwable|null Exception during on_headers (if any)
  45. */
  46. public $onHeadersException;
  47. /**
  48. * @var \Exception|null Exception during createResponse (if any)
  49. */
  50. public $createResponseException;
  51. /**
  52. * Attach a response to the easy handle based on the received headers.
  53. *
  54. * @throws \RuntimeException if no headers have been received.
  55. */
  56. public function createResponse(): void
  57. {
  58. if (empty($this->headers)) {
  59. throw new \RuntimeException('No headers have been received');
  60. }
  61. // HTTP-version SP status-code SP reason-phrase
  62. $startLine = \explode(' ', \array_shift($this->headers), 3);
  63. $headers = Utils::headersFromLines($this->headers);
  64. $normalizedKeys = Utils::normalizeHeaderKeys($headers);
  65. if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) {
  66. $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']];
  67. unset($headers[$normalizedKeys['content-encoding']]);
  68. if (isset($normalizedKeys['content-length'])) {
  69. $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']];
  70. $bodyLength = (int) $this->sink->getSize();
  71. if ($bodyLength) {
  72. $headers[$normalizedKeys['content-length']] = $bodyLength;
  73. } else {
  74. unset($headers[$normalizedKeys['content-length']]);
  75. }
  76. }
  77. }
  78. $statusCode = (int) $startLine[1];
  79. // Attach a response to the easy handle with the parsed headers.
  80. $this->response = new Response(
  81. $statusCode,
  82. $headers,
  83. $this->sink,
  84. \substr($startLine[0], 5),
  85. isset($startLine[2]) ? (string) $startLine[2] : null
  86. );
  87. }
  88. /**
  89. * @param string $name
  90. *
  91. * @return void
  92. *
  93. * @throws \BadMethodCallException
  94. */
  95. public function __get($name)
  96. {
  97. $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: ' . $name;
  98. throw new \BadMethodCallException($msg);
  99. }
  100. }