From 5a24b06130e3faf2f438669aa4c8d387efa335f2 Mon Sep 17 00:00:00 2001 From: tzfrs Date: Tue, 21 May 2019 16:08:34 +0200 Subject: [PATCH 1/2] MAP-3295 Add ApiKeyMiddleware --- .../Authentication/ApiKeyMiddleware.php | 28 +++++++++++++++++++ .../AuthenticationMiddlewareInterface.php | 11 ++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/Middleware/Authentication/ApiKeyMiddleware.php create mode 100644 src/Middleware/Authentication/AuthenticationMiddlewareInterface.php diff --git a/src/Middleware/Authentication/ApiKeyMiddleware.php b/src/Middleware/Authentication/ApiKeyMiddleware.php new file mode 100644 index 0000000..1986d7f --- /dev/null +++ b/src/Middleware/Authentication/ApiKeyMiddleware.php @@ -0,0 +1,28 @@ +apiKey = $apiKey; + } + + public function authenticate(): Closure + { + return static function (callable $handler) { + return static function (RequestInterface $request, array $options) use ($handler) { + // $request-> + return $handler; + }; + }; + } +} diff --git a/src/Middleware/Authentication/AuthenticationMiddlewareInterface.php b/src/Middleware/Authentication/AuthenticationMiddlewareInterface.php new file mode 100644 index 0000000..7ac28ef --- /dev/null +++ b/src/Middleware/Authentication/AuthenticationMiddlewareInterface.php @@ -0,0 +1,11 @@ + Date: Wed, 22 May 2019 10:54:57 +0200 Subject: [PATCH 2/2] MAP-3295 Add middleware to allow api authentication --- CHANGELOG.md | 8 +++ LICENSE => LICENSE.md | 0 README.md | 50 +++++++++++++++++-- .../Authentication/ApiKeyMiddlewareTest.php | 40 +++++++++++++++ .../Authentication/ApiKeyMiddleware.php | 18 +++++-- src/Middleware/EventDispatchMiddleware.php | 12 ----- src/Middleware/LogMiddleware.php | 27 +++------- 7 files changed, 115 insertions(+), 40 deletions(-) rename LICENSE => LICENSE.md (100%) create mode 100644 Tests/Middleware/Authentication/ApiKeyMiddlewareTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ee386a..4f31e29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All Notable changes to `mapudo/guzzle-bundle` will be documented in this file. Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles. +## [2.4.0] - 2019-05-22 +### Added +- Added middleware to automatically append api key query parameters. +- Added more extensive description for middleware +### Changed +- Changed code style of middleware classes to fit with newest standards WITHOUT breaking BC +- Clean up readme + ## [2.3.0] - 2019-04-12 ### Added - Added functionality to define channels when registering LogMiddleware. This allows a user, to inject a specific logger into the LogMiddleware dependent on the channel. diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/README.md b/README.md index a79992b..3cc06a1 100644 --- a/README.md +++ b/README.md @@ -100,12 +100,15 @@ available to configure via the config. ```php get('guzzle.client.test_client'); -$moreOptions = ['on_stats' => function (\GuzzleHttp\TransferStats $stats) { +$moreOptions = ['on_stats' => static function (TransferStats $stats) { echo $stats->getEffectiveUri() . "\n"; echo $stats->getTransferTime() . "\n"; }]; -$client->requestAsync(\Symfony\Component\HttpFoundation\Request::METHOD_GET, '/path/without/base_uri', $moreOptions); +$client->requestAsync(Request::METHOD_GET, '/path/without/base_uri', $moreOptions); ``` **Note**: *Clear your cache after adding a new log handler or a middleware @@ -174,6 +177,10 @@ For example, to write your own handler, take the response and request array out ```php apiKeyMiddleware = new ApiKeyMiddleware( + 'totallySecretApiKey', + 'api_key' + ); + } + + public function testAuthenticate() + { + $handler = static function (RequestInterface $request) { + Assert::assertSame('api_key=totallySecretApiKey', $request->getUri()->getQuery()); + Assert::assertSame( + 'https://api.google.com/calendar?api_key=totallySecretApiKey', + (string)$request->getUri() + ); + }; + + $request = new Request('GET', 'https://api.google.com/calendar'); + $options = ['options_are_unimportant_here']; + + $this->apiKeyMiddleware->authenticate()($handler)($request, $options); + } +} diff --git a/src/Middleware/Authentication/ApiKeyMiddleware.php b/src/Middleware/Authentication/ApiKeyMiddleware.php index 1986d7f..e53c75c 100644 --- a/src/Middleware/Authentication/ApiKeyMiddleware.php +++ b/src/Middleware/Authentication/ApiKeyMiddleware.php @@ -4,6 +4,7 @@ namespace Mapudo\Bundle\GuzzleBundle\Middleware\Authentication; use Closure; +use GuzzleHttp\Psr7\Uri; use Psr\Http\Message\RequestInterface; final class ApiKeyMiddleware implements AuthenticationMiddlewareInterface @@ -11,17 +12,26 @@ final class ApiKeyMiddleware implements AuthenticationMiddlewareInterface /** @var string */ private $apiKey; + /** @var string */ + private $apiKeyParameterName; + public function __construct(string $apiKey, string $apiKeyParameterName = 'key') { $this->apiKey = $apiKey; + $this->apiKeyParameterName = $apiKeyParameterName; } public function authenticate(): Closure { - return static function (callable $handler) { - return static function (RequestInterface $request, array $options) use ($handler) { - // $request-> - return $handler; + return function (callable $handler) { + return function (RequestInterface $request, array $options) use ($handler) { + $newRequest = $request->withUri(Uri::withQueryValue( + $request->getUri(), + $this->apiKeyParameterName, + $this->apiKey + )); + + return $handler($newRequest, $options); }; }; } diff --git a/src/Middleware/EventDispatchMiddleware.php b/src/Middleware/EventDispatchMiddleware.php index 2205461..4ff7985 100644 --- a/src/Middleware/EventDispatchMiddleware.php +++ b/src/Middleware/EventDispatchMiddleware.php @@ -26,24 +26,12 @@ class EventDispatchMiddleware /** @var string */ protected $clientName; - /** - * EventDispatchMiddleware constructor. - * - * @param EventDispatcherInterface $eventDispatcher - * @param string $clientName - */ public function __construct(EventDispatcherInterface $eventDispatcher, string $clientName) { $this->eventDispatcher = $eventDispatcher; $this->clientName = $clientName; } - /** - * Dispatches an event before the transaction is made (i.e. before the response is being gathered) - * and another event after the transaction is done (i.e. we now got the response) - * - * @return Closure - */ public function dispatch(): Closure { return function (callable $handler) { diff --git a/src/Middleware/LogMiddleware.php b/src/Middleware/LogMiddleware.php index a9e1221..fce96c0 100644 --- a/src/Middleware/LogMiddleware.php +++ b/src/Middleware/LogMiddleware.php @@ -2,6 +2,7 @@ namespace Mapudo\Bundle\GuzzleBundle\Middleware; +use Closure; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\MessageFormatter; use GuzzleHttp\TransferStats; @@ -9,6 +10,7 @@ use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; +use function GuzzleHttp\Promise\rejection_for; /** * Class LogMiddleware @@ -32,13 +34,6 @@ class LogMiddleware /** @var string|null */ protected $clientName; - /** - * LogMiddleware constructor. - * - * @param LoggerInterface $logger - * @param MessageFormatter $formatter - * @param NormalizerInterface $normalizer - */ public function __construct(LoggerInterface $logger, MessageFormatter $formatter, NormalizerInterface $normalizer) { $this->logger = $logger; @@ -46,11 +41,7 @@ public function __construct(LoggerInterface $logger, MessageFormatter $formatter $this->normalizer = $normalizer; } - /** - * Log each request - * @return \Closure - */ - public function log(): \Closure + public function log(): Closure { $logger = $this->logger; $formatter = $this->formatter; @@ -58,7 +49,7 @@ public function log(): \Closure return function (callable $handler) use ($logger, $formatter) { return function (RequestInterface $request, array $options) use ($handler, $logger, $formatter) { $duration = null; - $options['on_stats'] = function (TransferStats $stats) use (&$duration) { + $options['on_stats'] = static function (TransferStats $stats) use (&$duration) { $duration = $stats->getTransferTime(); }; @@ -77,19 +68,13 @@ function ($reason) use ($logger, $request, $formatter, &$duration) { $message = $formatter->format($request, $response, $reason); $logger->error($message, $this->buildContext($request, $response, $duration)); - return \GuzzleHttp\Promise\rejection_for($reason); + return rejection_for($reason); } ); }; }; } - /** - * Sets the client name. Used to distinguish between clients. - * - * @param string $clientName - * @return LogMiddleware - */ public function setClientName(string $clientName): LogMiddleware { $this->clientName = $clientName; @@ -102,6 +87,7 @@ private function buildContext( float $duration = null ): array { $request->getBody()->rewind(); + /** @noinspection PhpUnhandledExceptionInspection */ $context = [ 'request' => $this->normalizer->normalize($request), 'client' => $this->clientName, @@ -109,6 +95,7 @@ private function buildContext( ]; if ($response !== null) { + /** @noinspection PhpUnhandledExceptionInspection */ $context['response'] = $this->normalizer->normalize($response); }