RequestException.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <?php
  2. namespace GuzzleHttp\Exception;
  3. use GuzzleHttp\BodySummarizer;
  4. use GuzzleHttp\BodySummarizerInterface;
  5. use Psr\Http\Client\RequestExceptionInterface;
  6. use Psr\Http\Message\RequestInterface;
  7. use Psr\Http\Message\ResponseInterface;
  8. /**
  9. * HTTP Request exception
  10. */
  11. class RequestException extends TransferException implements RequestExceptionInterface
  12. {
  13. /**
  14. * @var RequestInterface
  15. */
  16. private $request;
  17. /**
  18. * @var ResponseInterface|null
  19. */
  20. private $response;
  21. /**
  22. * @var array
  23. */
  24. private $handlerContext;
  25. public function __construct(
  26. string $message,
  27. RequestInterface $request,
  28. ?ResponseInterface $response = null,
  29. ?\Throwable $previous = null,
  30. array $handlerContext = []
  31. ) {
  32. // Set the code of the exception if the response is set and not future.
  33. $code = $response ? $response->getStatusCode() : 0;
  34. parent::__construct($message, $code, $previous);
  35. $this->request = $request;
  36. $this->response = $response;
  37. $this->handlerContext = $handlerContext;
  38. }
  39. /**
  40. * Wrap non-RequestExceptions with a RequestException
  41. */
  42. public static function wrapException(RequestInterface $request, \Throwable $e): RequestException
  43. {
  44. return $e instanceof RequestException ? $e : new RequestException($e->getMessage(), $request, null, $e);
  45. }
  46. /**
  47. * Factory method to create a new exception with a normalized error message
  48. *
  49. * @param RequestInterface $request Request sent
  50. * @param ResponseInterface $response Response received
  51. * @param \Throwable|null $previous Previous exception
  52. * @param array $handlerContext Optional handler context
  53. * @param BodySummarizerInterface|null $bodySummarizer Optional body summarizer
  54. */
  55. public static function create(
  56. RequestInterface $request,
  57. ?ResponseInterface $response = null,
  58. ?\Throwable $previous = null,
  59. array $handlerContext = [],
  60. ?BodySummarizerInterface $bodySummarizer = null
  61. ): self {
  62. if (!$response) {
  63. return new self(
  64. 'Error completing request',
  65. $request,
  66. null,
  67. $previous,
  68. $handlerContext
  69. );
  70. }
  71. $level = (int) \floor($response->getStatusCode() / 100);
  72. if ($level === 4) {
  73. $label = 'Client error';
  74. $className = ClientException::class;
  75. } elseif ($level === 5) {
  76. $label = 'Server error';
  77. $className = ServerException::class;
  78. } else {
  79. $label = 'Unsuccessful request';
  80. $className = __CLASS__;
  81. }
  82. $uri = \GuzzleHttp\Psr7\Utils::redactUserInfo($request->getUri());
  83. // Client Error: `GET /` resulted in a `404 Not Found` response:
  84. // <html> ... (truncated)
  85. $message = \sprintf(
  86. '%s: `%s %s` resulted in a `%s %s` response',
  87. $label,
  88. $request->getMethod(),
  89. $uri->__toString(),
  90. $response->getStatusCode(),
  91. $response->getReasonPhrase()
  92. );
  93. $summary = ($bodySummarizer ?? new BodySummarizer())->summarize($response);
  94. if ($summary !== null) {
  95. $message .= ":\n{$summary}\n";
  96. }
  97. return new $className($message, $request, $response, $previous, $handlerContext);
  98. }
  99. /**
  100. * Get the request that caused the exception
  101. */
  102. public function getRequest(): RequestInterface
  103. {
  104. return $this->request;
  105. }
  106. /**
  107. * Get the associated response
  108. */
  109. public function getResponse(): ?ResponseInterface
  110. {
  111. return $this->response;
  112. }
  113. /**
  114. * Check if a response was received
  115. */
  116. public function hasResponse(): bool
  117. {
  118. return $this->response !== null;
  119. }
  120. /**
  121. * Get contextual information about the error from the underlying handler.
  122. *
  123. * The contents of this array will vary depending on which handler you are
  124. * using. It may also be just an empty array. Relying on this data will
  125. * couple you to a specific handler, but can give more debug information
  126. * when needed.
  127. */
  128. public function getHandlerContext(): array
  129. {
  130. return $this->handlerContext;
  131. }
  132. }