<?php
declare(strict_types=1);
namespace App\DataCollector;
use App\DataCollector\Model\HttpClientFlowCall;
use App\Event\HttpClient\Events;
use App\Event\HttpClient\HttpClientRequestEvent;
use App\Event\HttpClient\HttpClientResponseEvent;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
class HttpClientDataCollector extends DataCollector implements EventSubscriberInterface
{
protected $data = [
'calls' => null
];
public function __construct()
{
$this->data['calls'] = new ArrayCollection();
}
public function collect(Request $request, Response $response, \Throwable $exception = null)
{
//nothing to do here, please look into event's method
}
public function getName()
{
return 'http_client.collector';
}
public static function getSubscribedEvents()
{
return [
Events::HTTP_CALL_OUTGOING => 'onRequest',
Events::HTTP_CALL_INCOMING => 'onResponse',
];
}
public function getCalls() : ArrayCollection
{
return $this->data['calls'];
}
public function reset()
{
// TODO: Implement reset() method.
}
public function onRequest(HttpClientRequestEvent $requestEvent) : void
{
$httpClientFlowCall = new HttpClientFlowCall();
$httpClientFlowCall->setRequestId($requestEvent->getRequestIdentifier());
$httpClientFlowCall->setRequestMethod($requestEvent->getMethod());
$httpClientFlowCall->setRequestUrl($requestEvent->getRequest()->getUrl());
$httpClientFlowCall->setRequestParameters($requestEvent->getRequest()->getParameters() ?? []);
$httpClientFlowCall->setRequestBody($requestEvent->getRequest()->getBody());
$httpClientFlowCall->setRequestHeaders($requestEvent->getRequest()->getHeaders());
$requestBodyRaw = $httpClientFlowCall->getRequestBody();
$decodedRequestBody = null;
if ($requestBodyRaw !== null){
try{
$decodedRequestBody = @\json_decode($requestBodyRaw, true, 1024, JSON_THROW_ON_ERROR);
}
catch(\Exception){
$decodedRequestBody = null;
}
}
if (\is_array($decodedRequestBody)){
try{
$decodedRequestBody = @\json_encode($decodedRequestBody, JSON_PRETTY_PRINT);
}
catch(\Exception){
$decodedRequestBody = null;
}
}
else{
$decodedRequestBody = null;
}
$httpClientFlowCall->setRequestBodyDecoded($decodedRequestBody);
$collection = $this->data['calls'];
assert($collection instanceof ArrayCollection);
$collection->add($httpClientFlowCall);
}
public function onResponse(HttpClientResponseEvent $responseEvent) : void
{
$response = $responseEvent->getResponse();
$collection = $this->data['calls'];
assert($collection instanceof ArrayCollection);
$filteredCollection = $collection->filter(fn (HttpClientFlowCall $call) =>
$call->getRequestId() === $responseEvent->getRequestIdentifier()
);
$httpClientFlowCall = $filteredCollection->first() === false ? null :
$filteredCollection->first();
assert($httpClientFlowCall instanceof HttpClientFlowCall || $httpClientFlowCall === null);
$httpResponseStatusCode = (int) $response->getStatusCode();
$responseRawBody = (string) $response->getRawBody();
try{
$responseDecoded = json_decode($responseRawBody, true, 1024, JSON_THROW_ON_ERROR);
}
catch(\Exception){
$responseDecoded = null;
}
if (\is_array($responseDecoded)){
try{
$responseDecoded = \json_encode($responseDecoded, JSON_PRETTY_PRINT);
}
catch(\Exception){
$responseDecoded = null;
}
}
$httpClientFlowCall->setResponseStatusCode($httpResponseStatusCode);
$httpClientFlowCall->setResponseRawBody($responseRawBody);
$httpClientFlowCall->setResponseDecoded($responseDecoded);
}
}