Ver código fonte

Replace Curl with SocketHandler in FleepHookHandler

Ando Roots 11 anos atrás
pai
commit
b25697a3f0

+ 37 - 60
src/Monolog/Handler/FleepHookHandler.php

@@ -22,32 +22,18 @@ use Monolog\Logger;
  * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation
  * @author Ando Roots <ando@sqroot.eu>
  */
-class FleepHookHandler extends AbstractProcessingHandler
+class FleepHookHandler extends SocketHandler
 {
 
-    const HOOK_ENDPOINT = 'https://fleep.io/hook/';
+    const FLEEP_HOST = 'fleep.io';
+
+    const FLEEP_HOOK_URI = '/hook/';
 
     /**
      * @var string Webhook token (specifies the conversation where logs are sent)
      */
     protected $token;
 
-    /**
-     * @var string Full URI to the webhook endpoint (HOOK_ENDPOINT + token)
-     */
-    protected $url;
-
-    /**
-     * @var array Default options to Curl
-     */
-    protected $curlOptions = array(
-        CURLOPT_POST => true,
-        CURLOPT_HTTPHEADER => array(
-            'Content-Type: application/x-www-form-urlencoded'
-        ),
-        CURLOPT_RETURNTRANSFER => true
-    );
-
     /**
      * Construct a new Fleep.io Handler.
      *
@@ -57,26 +43,18 @@ class FleepHookHandler extends AbstractProcessingHandler
      * @param string $token Webhook token
      * @param bool|int $level The minimum logging level at which this handler will be triggered
      * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
-     * @throws \LogicException
+     * @throws MissingExtensionException
      */
     public function __construct($token, $level = Logger::DEBUG, $bubble = true)
     {
-        if (!extension_loaded('curl')) {
-            throw new \LogicException('The curl extension is needed to use FleepHookHandler');
+        if (!extension_loaded('openssl')) {
+            throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler');
         }
 
         $this->token = $token;
-        $this->url = self::HOOK_ENDPOINT . $this->token;
 
-        parent::__construct($level, $bubble);
-    }
-
-    /**
-     * @return array
-     */
-    public function getCurlOptions()
-    {
-        return $this->curlOptions;
+        $connectionString = 'ssl://' . self::FLEEP_HOST . ':443';
+        parent::__construct($connectionString, $level, $bubble);
     }
 
     /**
@@ -97,59 +75,58 @@ class FleepHookHandler extends AbstractProcessingHandler
      *
      * @param array $record
      */
-    protected function write(array $record)
+    public function write(array $record)
     {
-        $this->send($record['formatted']);
+        parent::write($record);
+        $this->closeSocket();
     }
 
 
     /**
-     * Prepares the record for sending to Fleep
+     * {@inheritdoc}
      *
-     * @param string $message The formatted log message to send
+     * @param  array $record
+     * @return string
      */
-    protected function send($message)
+    protected function generateDataStream($record)
     {
-        $this->addCurlOptions(
-            array(
-                CURLOPT_POSTFIELDS => http_build_query(array('message' => $message)),
-                CURLOPT_URL => $this->url,
-            )
-        );
-
-        $this->execCurl($this->curlOptions);
+        $content = $this->buildContent($record);
 
+        return $this->buildHeader($content) . $content;
     }
 
+
     /**
-     * Sends a new Curl request
+     * Builds the header of the API Call
      *
-     * @param array $options Curl parameters, including the endpoint URL and POST payload
+     * @param  string $content
+     * @return string
      */
-    protected function execCurl(array $options)
+    private function buildHeader($content)
     {
-        $curl = curl_init();
+        $header = "POST " . self::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n";
+        $header .= "Host: " . self::FLEEP_HOST . "\r\n";
+        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
+        $header .= "Content-Length: " . strlen($content) . "\r\n";
+        $header .= "\r\n";
 
-        curl_setopt_array($curl, $options);
-
-        curl_exec($curl);
-        curl_close($curl);
+        return $header;
     }
 
 
     /**
-     * Adds or overwrites a curl option
+     * Builds the body of API call
      *
-     * @param array $options An assoc array of Curl options, indexed by CURL_* constants
-     * @return $this
+     * @param  array $record
+     * @return string
      */
-    public function addCurlOptions(array $options)
+    private function buildContent($record)
     {
-        $this->curlOptions = array_replace(
-            $this->curlOptions,
-            $options
+        $dataArray = array(
+            'message' => $record['formatted']
         );
 
-        return $this;
+        return http_build_query($dataArray);
     }
+
 }

+ 4 - 129
tests/Monolog/Handler/FleepHookHandlerTest.php

@@ -33,24 +33,16 @@ class FleepHookHandlerTest extends TestCase
      */
     private $handler;
 
-    /**
-     * @var Logger
-     */
-    private $logger;
-
     public function setUp()
     {
         parent::setUp();
 
-        if (!extension_loaded('curl')) {
-            $this->markTestSkipped('This test requires curl extension to run');
+        if (!extension_loaded('openssl')) {
+            $this->markTestSkipped('This test requires openssl extension to run');
         }
 
         // Create instances of the handler and logger for convenience
         $this->handler = new FleepHookHandler(self::TOKEN);
-        $this->logger = new Logger('test');
-        $this->logger->pushHandler($this->handler);
-
     }
 
     /**
@@ -58,47 +50,10 @@ class FleepHookHandlerTest extends TestCase
      */
     public function testConstructorSetsExpectedDefaults()
     {
-        // Test that the $token is saved when calling the constructor
-        $token = self::TOKEN;
-        $handler = $this->mockHandler(array('execCurl'));
-        $handler->expects($this->once())
-            ->method('execCurl')
-            ->with(
-                $this->callback(
-                    function ($curlOpts) use ($token) {
-                        return substr($curlOpts[CURLOPT_URL], -strlen($token)) === $token;
-                    }
-                )
-            );
-
-        $this->sendLog($handler);
-
-        // Test that default values are assigned to $level and $bubble
         $this->assertEquals(Logger::DEBUG, $this->handler->getLevel());
         $this->assertEquals(true, $this->handler->getBubble());
     }
 
-    /**
-     * @covers ::write
-     */
-    public function testWriteSendsFormattedMessageToFleep()
-    {
-        $handler = $this->mockHandler(array('send'));
-
-        $message = 'theCakeIsALie';
-        $handler->expects($this->once())
-            ->method('send')
-            ->with(
-                $this->callback(
-                    function ($message) {
-                        return strstr($message, 'theCakeIsALie') && strstr($message, 'channel.ALERT');
-                    }
-                )
-            );
-
-        $this->sendLog($handler, $message);
-    }
-
     /**
      * @covers ::getDefaultFormatter
      */
@@ -125,91 +80,11 @@ class FleepHookHandlerTest extends TestCase
     }
 
     /**
-     * Tests that the URL to which the message is posted is of correct format
-     *
-     * Example: https://fleep.io/hook/mTZG6s-XRfKdNTJtpVyVaV
      * @covers ::__construct
      */
-    public function testFleepEndpointUrlIsConstructedCorrectly()
-    {
-        $handler = $this->mockHandler(array('execCurl'));
-
-        $token = self::TOKEN;
-
-        // Set up expectation to execCurl: receive curlOpts array where URL is correct
-        $handler->expects($this->once())
-            ->method('execCurl')
-            ->with(
-                $this->callback(
-                    function (array $curlOpts) use ($token) {
-                        return $curlOpts[CURLOPT_URL] === FleepHookHandler::HOOK_ENDPOINT . $token;
-                    }
-                )
-            );
-        $this->sendLog($handler);
-    }
-
-    /**
-     * Tests that the log message is added to the POST content, under the 'message' key
-     *
-     * @covers ::send
-     */
-    public function testSendAddsMessageToCurlOpts()
-    {
-        $handler = $this->mockHandler(array('execCurl'));
-        $handler->expects($this->once())
-            ->method('execCurl')
-            ->with(
-                $this->callback(
-                    function ($curlOpts) {
-                        parse_str($curlOpts[CURLOPT_POSTFIELDS], $body);
-                        return isset($body['message']) && strstr($body['message'], 'msg');
-                    }
-                )
-            );
-
-        $this->sendLog($handler, 'msg');
-    }
-
-    /**
-     * @covers ::addCurlOptions
-     */
-    public function testAddCurlOptionsLeavesUnspecifiedOptionsIntact()
-    {
-        $this->handler->addCurlOptions(array(CURLOPT_PROXY => 'http://localhost:3128'));
-        $this->assertArrayHasKey(CURLOPT_POST, $this->handler->getCurlOptions(), 'addCurlOpts deleted a key!');
-    }
-
-    public function testAddCurlOptionsAddsANewCurlOption()
-    {
-        $proxy = 'http://localhost:3128';
-        $this->handler->addCurlOptions(array(CURLOPT_PROXY => $proxy));
-        $options = $this->handler->getCurlOptions();
-        $this->assertEquals($options[CURLOPT_PROXY], $proxy);
-    }
-
-    /**
-     * Helper method for simulating a long sending event from the logger
-     *
-     * @param FleepHookHandler $handler
-     * @param string $message
-     */
-    private function sendLog(FleepHookHandler $handler, $message = 'test')
-    {
-        $logger = new Logger('channel');
-        $logger->pushHandler($handler);
-        $logger->addAlert($message);
-    }
-
-    /**
-     * Helper method for constructing a new mock of FleepHookHandler
-     *
-     * @param array $methods
-     * @return \PHPUnit_Framework_MockObject_MockObject
-     */
-    private function mockHandler(array $methods)
+    public function testConnectionStringisConstructedCorrectly()
     {
-        return $this->getMock('Monolog\Handler\FleepHookHandler', $methods, array(self::TOKEN));
+        $this->assertEquals('ssl://' . FleepHookHandler::FLEEP_HOST . ':443', $this->handler->getConnectionString());
     }
 
 }