From c26ac438e3068bccc65c4a3c6feee72644cd88da Mon Sep 17 00:00:00 2001 From: demyashev Date: Fri, 6 Dec 2024 01:50:41 +0300 Subject: [PATCH 1/3] [+] Guzzle Transpost --- composer.json | 5 +- src/Catcher.php | 3 +- src/Exception/TransportException.php | 7 +++ src/Handler.php | 5 +- src/Options.php | 12 ++++ src/Transport.php | 92 ++++++++++++++++++++++++++++ src/Transport/CurlTransport.php | 39 +++--------- src/Transport/GuzzleTransport.php | 36 +++++++---- src/Transport/TransportInterface.php | 31 ---------- tests/Unit/OptionsTest.php | 13 +++- 10 files changed, 160 insertions(+), 83 deletions(-) create mode 100644 src/Exception/TransportException.php create mode 100644 src/Transport.php delete mode 100644 src/Transport/TransportInterface.php diff --git a/composer.json b/composer.json index b045d46..72dd446 100644 --- a/composer.json +++ b/composer.json @@ -9,11 +9,12 @@ "ext-curl": "*", "ext-json": "*", "php": "^7.2 || ^8.0", - "jean85/pretty-package-versions": "^1.5 || ^2.0" + "jean85/pretty-package-versions": "^1.5 || ^2.0", + "guzzlehttp/guzzle": "^7.9" }, "require-dev": { "phpunit/phpunit": "^8.2", - "friendsofphp/php-cs-fixer": "^2.15", + "friendsofphp/php-cs-fixer": "^2.19", "symfony/var-dumper": "^5.2" }, "autoload": { diff --git a/src/Catcher.php b/src/Catcher.php index 17f84c1..44a811e 100644 --- a/src/Catcher.php +++ b/src/Catcher.php @@ -6,7 +6,6 @@ use Hawk\Addons\Environment; use Hawk\Addons\Headers; -use Hawk\Transport\CurlTransport; use Throwable; /** @@ -157,7 +156,7 @@ private function __construct(array $options) $builder->registerAddon(new Headers()); $builder->registerAddon(new Environment()); - $transport = new CurlTransport($options->getUrl(), $options->getTimeout()); + $transport = Transport::init($options); $this->handler = new Handler($options, $transport, $builder); diff --git a/src/Exception/TransportException.php b/src/Exception/TransportException.php new file mode 100644 index 0000000..af4657d --- /dev/null +++ b/src/Exception/TransportException.php @@ -0,0 +1,7 @@ +options = $options; diff --git a/src/Options.php b/src/Options.php index 52f3886..f9434e9 100644 --- a/src/Options.php +++ b/src/Options.php @@ -44,6 +44,11 @@ class Options */ private $timeout = 2; + /** + * @var string + */ + private $transport = 'curl'; + /** * Map of accepted option keys to class properties. */ @@ -59,6 +64,7 @@ class Options 'beforeSend' => 'beforeSend', 'before_send' => 'beforeSend', 'timeout' => 'timeout', + 'transport' => 'transport', ]; /** @@ -91,6 +97,7 @@ private function setOption(string $key, $value): void case 'integrationToken': case 'release': case 'url': + case 'transport': if (!is_string($value)) { throw new \InvalidArgumentException("Option '$key' must be a string."); } @@ -169,4 +176,9 @@ public function getTimeout(): int { return $this->timeout; } + + public function getTransport(): string + { + return $this->transport; + } } diff --git a/src/Transport.php b/src/Transport.php new file mode 100644 index 0000000..fff2cc3 --- /dev/null +++ b/src/Transport.php @@ -0,0 +1,92 @@ +getTransport(), $transports)) { + throw new TransportException('Invalid transport specified'); + } + + return new $transports[$options->getTransport()]($options); + } + + public static function getTransports(): array + { + return [ + 'curl' => CurlTransport::class, + 'guzzle' => GuzzleTransport::class, + ]; + } + + public function __construct(Options $options) + { + $this->url = $options->getUrl(); + $this->timeout = $options->getTimeout(); + } + + /** + * Returns URL that object must send an Event + * + * @return string + */ + public function getUrl(): string + { + return $this->url; + } + + public function getTimeout(): int + { + return $this->timeout; + } + + /** + * Sends an Event + * + * @param Event $event + * + * @return mixed + */ + public function send(Event $event) + { + $response = $this->_send($event); + + try { + $data = json_decode($response, true); + } catch (\Exception $e) { + $data = null; + } + + return $data; + } + + protected function _send(Event $event): string + { + throw new TransportException('Not implemented transport method _send()'); + } +} diff --git a/src/Transport/CurlTransport.php b/src/Transport/CurlTransport.php index 1b55e5a..9520877 100644 --- a/src/Transport/CurlTransport.php +++ b/src/Transport/CurlTransport.php @@ -5,51 +5,30 @@ namespace Hawk\Transport; use Hawk\Event; +use Hawk\Options; +use Hawk\Transport; /** * Class CurlTransport is a transport object * * @package Hawk\Transport */ -class CurlTransport implements TransportInterface +class CurlTransport extends Transport { - /** - * URL to send occurred event - * - * @var string - */ - private $url; - - /** - * CURLOPT_TIMEOUT - * - * @var int - */ - private $timeout; - /** * CurlTransport constructor. * - * @param string $url - */ - public function __construct(string $url, int $timeout) - { - $this->url = $url; - $this->timeout = $timeout; - } - - /** - * @inheritDoc + * @param Options $options */ - public function getUrl(): string + public function __construct(Options $options) { - return $this->url; + parent::__construct($options); } /** * @inheritDoc */ - public function send(Event $event) + protected function _send(Event $event): string { /** * If php-curl is not available then throw an exception @@ -59,12 +38,12 @@ public function send(Event $event) } $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, $this->url); + curl_setopt($curl, CURLOPT_URL, $this->getUrl()); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($event, JSON_UNESCAPED_UNICODE)); curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout); + curl_setopt($curl, CURLOPT_TIMEOUT, $this->getTimeout()); $response = curl_exec($curl); curl_close($curl); diff --git a/src/Transport/GuzzleTransport.php b/src/Transport/GuzzleTransport.php index 6ff5153..0e87164 100644 --- a/src/Transport/GuzzleTransport.php +++ b/src/Transport/GuzzleTransport.php @@ -5,34 +5,46 @@ namespace Hawk\Transport; use Hawk\Event; +use Hawk\Options; +use Hawk\Transport; /** * Class GuzzleTransport * * @package Hawk\Transport */ -class GuzzleTransport implements TransportInterface +class GuzzleTransport extends Transport { - private $url; - - public function __construct(string $url) - { - $this->url = $url; - } + /** + * @var \GuzzleHttp\Client + */ + private $client; /** - * @inheritDoc + * GuzzleTransport constructor. + * + * @param Options $options */ - public function getUrl(): string + public function __construct(Options $options) { - return $this->url; + parent::__construct($options); + + $this->client = new \GuzzleHttp\Client(); } /** * @inheritDoc */ - public function send(Event $event): void + protected function _send(Event $event): string { - // TODO: Implement send() method. + $response = $this->client->post($this->getUrl(), [ + 'headers' => [ + 'Content-Type' => 'application/json', + ], + 'body' => json_encode($event, JSON_UNESCAPED_UNICODE), + 'timeout' => $this->getTimeout(), + ]); + + return $response->getBody()->getContents(); } } diff --git a/src/Transport/TransportInterface.php b/src/Transport/TransportInterface.php deleted file mode 100644 index dcc2428..0000000 --- a/src/Transport/TransportInterface.php +++ /dev/null @@ -1,31 +0,0 @@ -assertEmpty($options->getIntegrationToken()); $this->assertEmpty($options->getRelease()); $this->assertEquals('https://k1.hawk.so/', $options->getUrl()); + $this->assertEquals(2, $options->getTimeout()); + $this->assertEquals('curl', $options->getTransport()); $this->assertEquals(error_reporting(), $options->getErrorTypes()); + $this->assertArrayHasKey($options->getTransport(), Transport::getTransports()); } public function testCustomOptions(): void @@ -27,8 +31,9 @@ public function testCustomOptions(): void 'integrationToken' => 'myToken', 'release' => '123', 'error_types' => 11, - 'beforeSend' => function () { - } + 'beforeSend' => function () {}, + 'timeout' => 60, + 'transport' => 'guzzle', ]; $options = new Options($config); @@ -37,7 +42,9 @@ public function testCustomOptions(): void 'integrationToken' => $options->getIntegrationToken(), 'release' => $options->getRelease(), 'error_types' => $options->getErrorTypes(), - 'beforeSend' => $options->getBeforeSend() + 'beforeSend' => $options->getBeforeSend(), + 'timeout' => $options->getTimeout(), + 'transport' => $options->getTransport(), ]); } } From 718efa5e8db54d103bd96cc1ae0bc527a9af4e2d Mon Sep 17 00:00:00 2001 From: demyashev Date: Fri, 6 Dec 2024 02:15:53 +0300 Subject: [PATCH 2/3] [*] composer version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 72dd446..14b7b20 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "PHP errors Catcher module for Hawk.so", "keywords": ["hawk", "php", "error", "catcher"], "type": "library", - "version": "2.2.8", + "version": "2.2.9", "license": "MIT", "require": { "ext-curl": "*", From 9de7db9cd2bdd540b4c5c192d223067b9aa244f3 Mon Sep 17 00:00:00 2001 From: demyashev Date: Fri, 6 Dec 2024 02:37:14 +0300 Subject: [PATCH 3/3] [*] Hawk\Transport::_send --- src/Transport.php | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Transport.php b/src/Transport.php index fff2cc3..5c9963c 100644 --- a/src/Transport.php +++ b/src/Transport.php @@ -13,7 +13,7 @@ * * @package Hawk\Transport */ -class Transport +abstract class Transport { /** * @var string @@ -25,6 +25,13 @@ class Transport */ protected $timeout; + /** + * @param Options $options + * + * @return static + * + * @throws TransportException + */ public static function init(Options $options) { $transports = self::getTransports(); @@ -36,6 +43,9 @@ public static function init(Options $options) return new $transports[$options->getTransport()]($options); } + /** + * @return string[] + */ public static function getTransports(): array { return [ @@ -44,6 +54,9 @@ public static function getTransports(): array ]; } + /** + * @param Options $options + */ public function __construct(Options $options) { $this->url = $options->getUrl(); @@ -60,6 +73,11 @@ public function getUrl(): string return $this->url; } + /** + * Returns total timeout of the request in seconds + * + * @return int + */ public function getTimeout(): int { return $this->timeout; @@ -85,8 +103,6 @@ public function send(Event $event) return $data; } - protected function _send(Event $event): string - { - throw new TransportException('Not implemented transport method _send()'); - } + + abstract protected function _send(Event $event): string; }