TraceableHttpClient.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpClient;
  11. use Psr\Log\LoggerAwareInterface;
  12. use Psr\Log\LoggerInterface;
  13. use Symfony\Component\HttpClient\Response\ResponseStream;
  14. use Symfony\Component\HttpClient\Response\TraceableResponse;
  15. use Symfony\Component\Stopwatch\Stopwatch;
  16. use Symfony\Contracts\HttpClient\HttpClientInterface;
  17. use Symfony\Contracts\HttpClient\ResponseInterface;
  18. use Symfony\Contracts\HttpClient\ResponseStreamInterface;
  19. use Symfony\Contracts\Service\ResetInterface;
  20. /**
  21. * @author Jérémy Romey <jeremy@free-agent.fr>
  22. */
  23. final class TraceableHttpClient implements HttpClientInterface, ResetInterface, LoggerAwareInterface
  24. {
  25. /**
  26. * @var \Symfony\Contracts\HttpClient\HttpClientInterface
  27. */
  28. private $client;
  29. /**
  30. * @var \Symfony\Component\Stopwatch\Stopwatch|null
  31. */
  32. private $stopwatch;
  33. /**
  34. * @var \ArrayObject
  35. */
  36. private $tracedRequests;
  37. /**
  38. * @param \Symfony\Contracts\HttpClient\HttpClientInterface $client
  39. * @param \Symfony\Component\Stopwatch\Stopwatch|null $stopwatch
  40. */
  41. public function __construct($client, $stopwatch = null)
  42. {
  43. $this->client = $client;
  44. $this->stopwatch = $stopwatch;
  45. $this->tracedRequests = new \ArrayObject();
  46. }
  47. /**
  48. * @param string $method
  49. * @param string $url
  50. * @param mixed[] $options
  51. */
  52. public function request($method, $url, $options = [])
  53. {
  54. $content = null;
  55. $traceInfo = [];
  56. $this->tracedRequests[] = [
  57. 'method' => $method,
  58. 'url' => $url,
  59. 'options' => $options,
  60. 'info' => &$traceInfo,
  61. 'content' => &$content,
  62. ];
  63. $onProgress = $options['on_progress'] ?? null;
  64. if (false === ($options['extra']['trace_content'] ?? true)) {
  65. unset($content);
  66. $content = false;
  67. }
  68. $options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use (&$traceInfo, $onProgress) {
  69. $traceInfo = $info;
  70. if (null !== $onProgress) {
  71. $onProgress($dlNow, $dlSize, $info);
  72. }
  73. };
  74. return new TraceableResponse($this->client, $this->client->request($method, $url, $options), $content, ($stopwatch = $this->stopwatch) ? $stopwatch->start("$method $url", 'http_client') : null);
  75. }
  76. /**
  77. * @param \Symfony\Contracts\HttpClient\ResponseInterface|mixed[] $responses
  78. * @param float|null $timeout
  79. */
  80. public function stream($responses, $timeout = null)
  81. {
  82. if ($responses instanceof TraceableResponse) {
  83. $responses = [$responses];
  84. }
  85. return new ResponseStream(TraceableResponse::stream($this->client, $responses, $timeout));
  86. }
  87. public function getTracedRequests()
  88. {
  89. return $this->tracedRequests->getArrayCopy();
  90. }
  91. public function reset()
  92. {
  93. if ($this->client instanceof ResetInterface) {
  94. $this->client->reset();
  95. }
  96. $this->tracedRequests->exchangeArray([]);
  97. }
  98. /**
  99. * @param \Psr\Log\LoggerInterface $logger
  100. */
  101. public function setLogger($logger)
  102. {
  103. if ($this->client instanceof LoggerAwareInterface) {
  104. $this->client->setLogger($logger);
  105. }
  106. }
  107. /**
  108. * @return $this
  109. * @param mixed[] $options
  110. */
  111. public function withOptions($options)
  112. {
  113. $clone = clone $this;
  114. $clone->client = $this->client->withOptions($options);
  115. return $clone;
  116. }
  117. }