Added basic implementation for new webhook events

This commit is contained in:
Alejandro Celaya 2019-12-27 09:25:07 +01:00
parent 34d8b396a4
commit 3fdba53995
4 changed files with 106 additions and 0 deletions

View file

@ -10,6 +10,7 @@ return [
'hostname' => '', 'hostname' => '',
], ],
'validate_url' => true, 'validate_url' => true,
'visits_webhooks' => [],
], ],
]; ];

View file

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core; namespace Shlinkio\Shlink\Core;
use GuzzleHttp\ClientInterface;
use Shlinkio\Shlink\CLI\Util\GeolocationDbUpdater; use Shlinkio\Shlink\CLI\Util\GeolocationDbUpdater;
use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface; use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface;
use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory; use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory;
@ -16,6 +17,9 @@ return [
EventDispatcher\ShortUrlVisited::class => [ EventDispatcher\ShortUrlVisited::class => [
EventDispatcher\LocateShortUrlVisit::class, EventDispatcher\LocateShortUrlVisit::class,
], ],
EventDispatcher\ShortUrlLocated::class => [
EventDispatcher\NotifyVisitToWebHooks::class,
],
], ],
], ],
@ -32,6 +36,12 @@ return [
'Logger_Shlink', 'Logger_Shlink',
GeolocationDbUpdater::class, GeolocationDbUpdater::class,
], ],
EventDispatcher\NotifyVisitToWebHooks::class => [
'httpClient',
'em',
'Logger_Shlink',
'config.url_shortener.visits_webhooks',
],
], ],
]; ];

View file

@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\EventDispatcher;
use Doctrine\ORM\EntityManagerInterface;
use Fig\Http\Message\RequestMethodInterface;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\RequestOptions;
use Psr\Log\LoggerInterface;
use Shlinkio\Shlink\Core\Entity\Visit;
use function Functional\map;
class NotifyVisitToWebHooks
{
/** @var ClientInterface */
private $httpClient;
/** @var EntityManagerInterface */
private $em;
/** @var LoggerInterface */
private $logger;
/** @var array */
private $webhooks;
public function __construct(
ClientInterface $httpClient,
EntityManagerInterface $em,
LoggerInterface $logger,
array $webhooks
) {
$this->httpClient = $httpClient;
$this->em = $em;
$this->logger = $logger;
$this->webhooks = $webhooks;
}
public function __invoke(ShortUrlLocated $shortUrlLocated): void
{
$visitId = $shortUrlLocated->visitId();
/** @var Visit|null $visit */
$visit = $this->em->find(Visit::class, $visitId);
if ($visit === null) {
$this->logger->warning('Tried to notify webhooks for visit with id "{visitId}", but it does not exist.', [
'visitId' => $visitId,
]);
return;
}
$requestOptions = [
RequestOptions::TIMEOUT => 10,
RequestOptions::JSON => $visit->jsonSerialize(),
];
$requestPromises = map($this->webhooks, function (string $webhook) use ($requestOptions, $visitId) {
$promise = $this->httpClient->requestAsync(RequestMethodInterface::METHOD_POST, $webhook, $requestOptions);
return $promise->otherwise(function () use ($webhook, $visitId) {
// Log failures
$this->logger->warning('Failed to notify visit with id "{visitId}" to "{webhook}" webhook', [
'visitId' => $visitId,
'webhook' => $webhook,
]);
});
});
}
}

View file

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\EventDispatcher;
use JsonSerializable;
final class ShortUrlLocated implements JsonSerializable
{
/** @var string */
private $visitId;
public function __construct(string $visitId)
{
$this->visitId = $visitId;
}
public function visitId(): string
{
return $this->visitId;
}
public function jsonSerialize(): array
{
return ['visitId' => $this->visitId];
}
}