TraceableHttpClient.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. private $client;
  26. private $tracedRequests = [];
  27. private $stopwatch;
  28. public function __construct(HttpClientInterface $client, Stopwatch $stopwatch = null)
  29. {
  30. $this->client = $client;
  31. $this->stopwatch = $stopwatch;
  32. }
  33. /**
  34. * {@inheritdoc}
  35. */
  36. public function request(string $method, string $url, array $options = []): ResponseInterface
  37. {
  38. $content = null;
  39. $traceInfo = [];
  40. $this->tracedRequests[] = [
  41. 'method' => $method,
  42. 'url' => $url,
  43. 'options' => $options,
  44. 'info' => &$traceInfo,
  45. 'content' => &$content,
  46. ];
  47. $onProgress = $options['on_progress'] ?? null;
  48. if (false === ($options['extra']['trace_content'] ?? true)) {
  49. unset($content);
  50. $content = false;
  51. }
  52. $options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use (&$traceInfo, $onProgress) {
  53. $traceInfo = $info;
  54. if (null !== $onProgress) {
  55. $onProgress($dlNow, $dlSize, $info);
  56. }
  57. };
  58. return new TraceableResponse($this->client, $this->client->request($method, $url, $options), $content, null === $this->stopwatch ? null : $this->stopwatch->start("$method $url", 'http_client'));
  59. }
  60. /**
  61. * {@inheritdoc}
  62. */
  63. public function stream($responses, float $timeout = null): ResponseStreamInterface
  64. {
  65. if ($responses instanceof TraceableResponse) {
  66. $responses = [$responses];
  67. } elseif (!is_iterable($responses)) {
  68. throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of TraceableResponse objects, "%s" given.', __METHOD__, get_debug_type($responses)));
  69. }
  70. return new ResponseStream(TraceableResponse::stream($this->client, $responses, $timeout));
  71. }
  72. public function getTracedRequests(): array
  73. {
  74. return $this->tracedRequests;
  75. }
  76. public function reset()
  77. {
  78. if ($this->client instanceof ResetInterface) {
  79. $this->client->reset();
  80. }
  81. $this->tracedRequests = [];
  82. }
  83. /**
  84. * {@inheritdoc}
  85. */
  86. public function setLogger(LoggerInterface $logger): void
  87. {
  88. if ($this->client instanceof LoggerAwareInterface) {
  89. $this->client->setLogger($logger);
  90. }
  91. }
  92. }