-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from oat-sa/develop
Develop
- Loading branch information
Showing
9 changed files
with
444 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/vendor/ | ||
/.idea/ | ||
composer.phar | ||
composer.lock | ||
.phpunit.result.cache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
CHANGELOG | ||
========= | ||
|
||
0.1.0 | ||
----- | ||
|
||
* Added CorrelationIdsGuzzleMiddleware | ||
* Added GuzzleClientFactory to create guzzle client with CorrelationIdsGuzzleMiddleware enabled |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,87 @@ | ||
# Correlation Ids Guzzle Middleware Library | ||
# Correlation Ids Guzzle Middleware Library | ||
|
||
> PHP library for correlation ids guzzle middleware based on the [correlation ids library](https://github.com/oat-sa/lib-correlation-ids). | ||
## Table of contents | ||
- [Installation](#installation) | ||
- [Principles](#principles) | ||
- [Usage](#usage) | ||
- [Tests](#tests) | ||
|
||
## Installation | ||
|
||
```console | ||
$ composer require oat-sa/lib-correlation-ids-guzzle | ||
``` | ||
|
||
## Principles | ||
|
||
This library provides a ready to use [guzzle](http://docs.guzzlephp.org/en/stable/) middleware that forwards, as request headers, the correlation ids fetched from the [correlation ids registry](https://github.com/oat-sa/lib-correlation-ids/blob/master/src/Registry/CorrelationIdsRegistryInterface.php). | ||
|
||
**Notes** | ||
- the current process correlation id will be forwarded as the parent one, | ||
- the root correlation id will be also forwarded. | ||
|
||
More details about calls chaining available on the [correlation ids library](https://github.com/oat-sa/lib-correlation-ids) documentation. | ||
|
||
## Usage | ||
|
||
### With the provided factory | ||
|
||
The `GuzzleClientFactory` creates for you a guzzle client with the middleware already enabled: | ||
|
||
```php | ||
<?php declare(strict_types=1); | ||
|
||
use OAT\Library\CorrelationIds\Registry\CorrelationIdsRegistry; | ||
use OAT\Library\CorrelationIds\Registry\CorrelationIdsRegistryInterface; | ||
use OAT\Library\CorrelationIdsGuzzle\Factory\GuzzleClientFactory; | ||
use OAT\Library\CorrelationIdsGuzzle\Middleware\CorrelationIdsGuzzleMiddleware; | ||
|
||
/** @var CorrelationIdsRegistryInterface $registry */ | ||
$registry = new CorrelationIdsRegistry(...); | ||
|
||
$clientFactory = new GuzzleClientFactory(new CorrelationIdsGuzzleMiddleware($registry))); | ||
|
||
$client = $clientFactory->create(['some' => 'options']); | ||
|
||
... | ||
|
||
$client->request('GET', 'http://example.com'); // Will forward correlation ids as request headers automatically. | ||
``` | ||
|
||
### Manually | ||
|
||
You need to push the `CorrelationIdsGuzzleMiddleware` to your handler stack as follow: | ||
|
||
```php | ||
<?php declare(strict_types=1); | ||
|
||
use GuzzleHttp\Client; | ||
use GuzzleHttp\HandlerStack; | ||
use GuzzleHttp\Middleware; | ||
use OAT\Library\CorrelationIds\Registry\CorrelationIdsRegistry; | ||
use OAT\Library\CorrelationIds\Registry\CorrelationIdsRegistryInterface; | ||
use OAT\Library\CorrelationIdsGuzzle\Middleware\CorrelationIdsGuzzleMiddleware; | ||
|
||
/** @var CorrelationIdsRegistryInterface $registry */ | ||
$registry = new CorrelationIdsRegistry(...); | ||
|
||
$handlerStack = HandlerStack::create(); | ||
$handlerStack->push(Middleware::mapRequest(new CorrelationIdsGuzzleMiddleware($registry))); | ||
|
||
$client = new Client(['handler' => $handlerStack]); | ||
|
||
... | ||
|
||
$client->request('GET', 'http://example.com'); // Will forward correlation ids as request headers automatically. | ||
``` | ||
**Note**: you can customize the log context key names by providing you own [CorrelationIdsHeaderNamesProviderInterface](https://github.com/oat-sa/lib-correlation-ids/blob/master/src/Provider/CorrelationIdsHeaderNamesProviderInterface.php) implementation and pass it to the `CorrelationIdsGuzzleMiddleware` constructor. | ||
|
||
## Tests | ||
|
||
To run tests: | ||
```console | ||
$ vendor/bin/phpunit | ||
``` | ||
**Note**: see [phpunit.xml.dist](phpunit.xml.dist) for available test suites. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"name": "oat-sa/lib-correlation-ids-guzzle", | ||
"description": "OAT Correlation Ids Guzzle Library", | ||
"type": "library", | ||
"license": "GPL-2.0-only", | ||
"require": { | ||
"php": "^7.1.3", | ||
"oat-sa/lib-correlation-ids": "<1.0", | ||
"guzzlehttp/guzzle": "^6.4" | ||
}, | ||
"require-dev": { | ||
"phpunit/phpunit": "^8.3" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"OAT\\Library\\CorrelationIdsGuzzle\\": "src/" | ||
} | ||
}, | ||
"autoload-dev": { | ||
"psr-4": { | ||
"OAT\\Library\\CorrelationIdsGuzzle\\Tests\\": "tests/" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html --> | ||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.5/phpunit.xsd" | ||
backupGlobals="false" | ||
colors="true" | ||
> | ||
<testsuites> | ||
<testsuite name="Integration"> | ||
<directory>tests/Integration</directory> | ||
</testsuite> | ||
<testsuite name="Unit"> | ||
<directory>tests/Unit</directory> | ||
</testsuite> | ||
</testsuites> | ||
|
||
<filter> | ||
<whitelist processUncoveredFilesFromWhitelist="true"> | ||
<directory>src</directory> | ||
</whitelist> | ||
</filter> | ||
</phpunit> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php declare(strict_types=1); | ||
/** | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; under version 2 | ||
* of the License (non-upgradable). | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
* | ||
* Copyright (c) 2019 (original work) Open Assessment Technologies SA; | ||
*/ | ||
namespace OAT\Library\CorrelationIdsGuzzle\Factory; | ||
|
||
use GuzzleHttp\Client; | ||
use GuzzleHttp\ClientInterface; | ||
use GuzzleHttp\HandlerStack; | ||
use GuzzleHttp\Middleware; | ||
use OAT\Library\CorrelationIdsGuzzle\Middleware\CorrelationIdsGuzzleMiddleware; | ||
|
||
class GuzzleClientFactory | ||
{ | ||
/** @var CorrelationIdsGuzzleMiddleware */ | ||
private $middleware; | ||
|
||
public function __construct(CorrelationIdsGuzzleMiddleware $middleware) | ||
{ | ||
$this->middleware = $middleware; | ||
} | ||
|
||
public function create(array $configuration = []): ClientInterface | ||
{ | ||
$configuration['handler'] = $this->pushMiddleware($configuration['handler'] ?? HandlerStack::create()); | ||
|
||
return new Client($configuration); | ||
} | ||
|
||
private function pushMiddleware(HandlerStack $handlerStack): HandlerStack | ||
{ | ||
$handlerStack->push(Middleware::mapRequest($this->middleware), CorrelationIdsGuzzleMiddleware::class); | ||
|
||
return $handlerStack; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<?php declare(strict_types=1); | ||
/** | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; under version 2 | ||
* of the License (non-upgradable). | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
* | ||
* Copyright (c) 2019 (original work) Open Assessment Technologies SA; | ||
*/ | ||
namespace OAT\Library\CorrelationIdsGuzzle\Middleware; | ||
|
||
use OAT\Library\CorrelationIds\Provider\CorrelationIdsHeaderNamesProvider; | ||
use OAT\Library\CorrelationIds\Provider\CorrelationIdsHeaderNamesProviderInterface; | ||
use OAT\Library\CorrelationIds\Registry\CorrelationIdsRegistryInterface; | ||
use Psr\Http\Message\RequestInterface; | ||
|
||
class CorrelationIdsGuzzleMiddleware | ||
{ | ||
/** @var CorrelationIdsRegistryInterface */ | ||
private $registry; | ||
|
||
/** @var CorrelationIdsHeaderNamesProviderInterface */ | ||
private $provider; | ||
|
||
public function __construct( | ||
CorrelationIdsRegistryInterface $registry, | ||
CorrelationIdsHeaderNamesProviderInterface $provider = null | ||
) { | ||
$this->registry = $registry; | ||
$this->provider = $provider ?? new CorrelationIdsHeaderNamesProvider(); | ||
} | ||
|
||
public function __invoke(RequestInterface $request, array $options = []): RequestInterface | ||
{ | ||
$headers = [ | ||
$this->provider->provideParentCorrelationIdHeaderName() => $this->registry->getCurrentCorrelationId(), | ||
$this->provider->provideRootCorrelationIdHeaderName() => $this->determinateRootCorrelationId(), | ||
]; | ||
|
||
foreach ($headers as $headerName => $headerValue) { | ||
$request = $request->withHeader($headerName, $headerValue); | ||
} | ||
|
||
return $request; | ||
} | ||
|
||
private function determinateRootCorrelationId(): string | ||
{ | ||
$candidates = array_filter([ | ||
$this->registry->getRootCorrelationId(), | ||
$this->registry->getParentCorrelationId(), | ||
$this->registry->getCurrentCorrelationId(), | ||
]); | ||
|
||
return array_shift($candidates) ?? ''; | ||
} | ||
} |
115 changes: 115 additions & 0 deletions
115
tests/Integration/Middleware/CorrelationIdsGuzzleMiddlewareTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
<?php declare(strict_types=1); | ||
/** | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; under version 2 | ||
* of the License (non-upgradable). | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
* | ||
* Copyright (c) 2019 (original work) Open Assessment Technologies SA; | ||
*/ | ||
namespace OAT\Library\CorrelationIdsGuzzle\Tests\Integration\Middleware; | ||
|
||
use GuzzleHttp\Client; | ||
use GuzzleHttp\Handler\MockHandler; | ||
use GuzzleHttp\HandlerStack; | ||
use GuzzleHttp\Middleware; | ||
use GuzzleHttp\Psr7\Response; | ||
use OAT\Library\CorrelationIds\Provider\CorrelationIdsHeaderNamesProviderInterface; | ||
use OAT\Library\CorrelationIds\Registry\CorrelationIdsRegistryInterface; | ||
use OAT\Library\CorrelationIdsGuzzle\Middleware\CorrelationIdsGuzzleMiddleware; | ||
use PHPUnit\Framework\MockObject\MockObject; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
class CorrelationIdsGuzzleMiddlewareTest extends TestCase | ||
{ | ||
/** @var CorrelationIdsRegistryInterface|MockObject */ | ||
private $registryMock; | ||
|
||
/** @var CorrelationIdsHeaderNamesProviderInterface|MockObject */ | ||
private $providerMock; | ||
|
||
/** @var array */ | ||
private $history = []; | ||
|
||
protected function setUp(): void | ||
{ | ||
$this->registryMock = $this->createMock(CorrelationIdsRegistryInterface::class); | ||
$this->providerMock = $this->createMock(CorrelationIdsHeaderNamesProviderInterface::class); | ||
} | ||
|
||
protected function tearDown(): void | ||
{ | ||
$this->history = []; | ||
} | ||
|
||
public function testItForwardsCorrelationIdsAsRequestHeaders(): void | ||
{ | ||
$this->registryMock | ||
->expects($this->exactly(2)) | ||
->method('getCurrentCorrelationId') | ||
->willReturn('current'); | ||
|
||
$this->registryMock | ||
->expects($this->once()) | ||
->method('getParentCorrelationId') | ||
->willReturn('parent'); | ||
|
||
$this->registryMock | ||
->expects($this->once()) | ||
->method('getRootCorrelationId') | ||
->willReturn('root'); | ||
|
||
$this->providerMock | ||
->expects($this->never()) | ||
->method('provideCurrentCorrelationIdHeaderName'); | ||
|
||
$this->providerMock | ||
->expects($this->once()) | ||
->method('provideParentCorrelationIdHeaderName') | ||
->willReturn(CorrelationIdsHeaderNamesProviderInterface::DEFAULT_PARENT_CORRELATION_ID_HEADER_NAME); | ||
|
||
$this->providerMock | ||
->expects($this->once()) | ||
->method('provideRootCorrelationIdHeaderName') | ||
->willReturn(CorrelationIdsHeaderNamesProviderInterface::DEFAULT_ROOT_CORRELATION_ID_HEADER_NAME); | ||
|
||
$client = $this->prepareTestGuzzleClient([new Response()]); | ||
$client->request('POST', 'http://example.com'); | ||
|
||
$executedRequestHeaders = current($this->history)['request']->getHeaders(); | ||
|
||
$this->assertEquals( | ||
['current'], | ||
$executedRequestHeaders[CorrelationIdsHeaderNamesProviderInterface::DEFAULT_PARENT_CORRELATION_ID_HEADER_NAME] | ||
); | ||
|
||
$this->assertEquals( | ||
['root'], | ||
$executedRequestHeaders[CorrelationIdsHeaderNamesProviderInterface::DEFAULT_ROOT_CORRELATION_ID_HEADER_NAME] | ||
); | ||
} | ||
|
||
private function prepareTestGuzzleClient(array $expectedResponses): Client | ||
{ | ||
$handlerStack = HandlerStack::create(new MockHandler($expectedResponses)); | ||
|
||
$handlerStack->push( | ||
Middleware::mapRequest(new CorrelationIdsGuzzleMiddleware($this->registryMock, $this->providerMock)) | ||
); | ||
|
||
$handlerStack->push( | ||
Middleware::history($this->history) | ||
); | ||
|
||
return new Client(['handler' => $handlerStack]); | ||
} | ||
} |
Oops, something went wrong.