<?php
namespace EightPoints\Bundle\GuzzleBundle\Middleware;
use EightPoints\Bundle\GuzzleBundle\Log\Logger;
use EightPoints\Bundle\GuzzleBundle\Log\LoggerInterface;
use EightPoints\Bundle\GuzzleBundle\DataCollector\HttpDataCollector;
use Psr\Http\Message\RequestInterface;
use GuzzleHttp\TransferStats;
class RequestTimeMiddleware
{
/** @var \EightPoints\Bundle\GuzzleBundle\Log\LoggerInterface */
protected $logger;
/** @var \EightPoints\Bundle\GuzzleBundle\DataCollector\HttpDataCollector */
private $dataCollector;
/**
* @param \EightPoints\Bundle\GuzzleBundle\Log\LoggerInterface $logger
* @param \EightPoints\Bundle\GuzzleBundle\DataCollector\HttpDataCollector $dataCollector
*/
public function __construct(LoggerInterface $logger, HttpDataCollector $dataCollector)
{
$this->logger = $logger;
$this->dataCollector = $dataCollector;
}
/**
* @param callable $handler
*
* @return \Closure
*/
public function __invoke(callable $handler) : \Closure
{
return function (RequestInterface $request, array $options) use ($handler) {
$options['on_stats'] = $this->getOnStatsCallback(
isset($options['on_stats']) ? $options['on_stats'] : null,
isset($options['request_id']) ? $options['request_id'] : null
);
// Continue the handler chain.
return $handler($request, $options);
};
}
/**
* Create callback for on_stats options.
* If request has on_stats option, it will be called inside of this callback.
*
* @param null|callable $initialOnStats
* @param null|string $requestId
*
* @return \Closure
*/
protected function getOnStatsCallback(?callable $initialOnStats, ?string $requestId) : \Closure
{
return function (TransferStats $stats) use ($initialOnStats, $requestId) {
if (is_callable($initialOnStats)) {
call_user_func($initialOnStats, $stats);
}
$this->dataCollector->addTotalTime((float)$stats->getTransferTime());
if (($this->logger instanceof Logger) && $requestId) {
$this->logger->addTransferTimeByRequestId($requestId, (float)$stats->getTransferTime());
}
};
}
}