headless_cms-1.0.3/modules/headless_cms_notify_webhook/src/HeadlessNotifyWebhookService.php
modules/headless_cms_notify_webhook/src/HeadlessNotifyWebhookService.php
<?php
declare(strict_types=1);
namespace Drupal\headless_cms_notify_webhook;
use Drupal\Core\Queue\QueueFactory;
use Drupal\headless_cms_notify_webhook\Exception\WebhookRequestException;
use Drupal\headless_cms_notify_webhook\Plugin\QueueWorker\HeadlessNotifyWebhookQueueWorker;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Psr7\Request;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
/**
* Service to send webhooks.
*/
class HeadlessNotifyWebhookService {
public function __construct(
protected readonly QueueFactory $queueFactory,
protected readonly ClientInterface $httpClient,
#[Autowire('@logger.channel.headless_cms_notify_webhook')]
protected readonly LoggerInterface $logger,
) {}
/**
* Send a webhook.
*/
public function send(string $url, string $json, bool $useQueue = TRUE): ?ResponseInterface {
// Handle queue.
if ($useQueue) {
$item = new HeadlessNotifyWebhookQueueItem($url, $json);
$queue = $this->queueFactory->get(HeadlessNotifyWebhookQueueWorker::QUEUE_NAME);
$queue->createItem($item->toJson());
return NULL;
}
// Do work.
$request = new Request(
method: 'POST',
uri: $url,
headers: [
'Content-Type' => 'application/json',
],
body: $json
);
try {
$response = $this->httpClient->send($request, [
'connect_timeout' => 5,
]);
$this->logger->info('Successfully sent webhook to: @url', [
'@url' => $url,
]);
return $response;
}
// Handle request errors.
catch (ClientException $e) {
// For every error, except not found.
if ($e->getResponse()->getStatusCode() !== 404) {
$this->logger->error('Webhook request failed with status @status - Payload: @payload', [
'@status' => $e->getResponse()->getStatusCode(),
'@payload' => $request->getBody()->__toString(),
]);
throw new WebhookRequestException($e->getResponse());
}
// Treat not found as a warning and additionally do not throw
// an exception here. If the destination cannot handle the webhook,
// it should not be handled as an error.
$this->logger->warning('Webhook endpoint not implemented by destination: @destination', [
'@destination' => $url,
]);
}
// Handle connection errors.
catch (ConnectException $e) {
$this->logger->error('Webhook request failed. Could not connect to host: @url', [
'@url' => $url,
]);
throw new WebhookRequestException();
}
return NULL;
}
}
