Skip to content
This repository was archived by the owner on Oct 24, 2023. It is now read-only.

Commit 124c004

Browse files
author
Jens Schulze
committed
feat(Client): support creation of correlation id at client side
Closes #328
1 parent c2a0ce3 commit 124c004

File tree

10 files changed

+156
-5
lines changed

10 files changed

+156
-5
lines changed

composer.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,16 @@
5858
"cache/redis-adapter": "^0.4.0",
5959
"cache/filesystem-adapter": "^0.3.0",
6060
"cache/void-adapter": "^0.3",
61-
"incenteev/composer-parameter-handler": "^2.1"
61+
"incenteev/composer-parameter-handler": "^2.1",
62+
"ramsey/uuid": "^3.6"
6263
},
6364
"replaces": {
6465
"commercetools/commons": "*"
6566
},
6667
"suggest": {
6768
"cache/redis-adapter": "For usage of a redis server to store the client access token",
68-
"cache/doctrine-adapter": "For usage of a doctrine cache instance to store the client access token"
69+
"cache/doctrine-adapter": "For usage of a doctrine cache instance to store the client access token",
70+
"ramsey/uuid": "For using the correlation id feature to uniquely identify requests against CTP"
6971
},
7072
"scripts": {
7173
"updateConfig": [

src/Core/Client.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Commercetools\Core;
88

9+
use Commercetools\Core\Client\Adapter\CorrelationIdAdapter;
910
use Commercetools\Core\Response\ErrorResponse;
1011
use Psr\Http\Message\RequestInterface;
1112
use Psr\Http\Message\ResponseInterface;
@@ -206,6 +207,9 @@ public function getHttpClient($options = [])
206207
$this->getConfig()->getMessageFormatter()
207208
);
208209
}
210+
if ($this->getConfig()->getEnableCorrelationId() && $client instanceof CorrelationIdAdapter) {
211+
$client->enableCorrelationId($this->getConfig()->getProject());
212+
}
209213
}
210214

211215
return $this->httpClient;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
/**
3+
* @author @jayS-de <jens.schulze@commercetools.de>
4+
*/
5+
6+
namespace Commercetools\Core\Client\Adapter;
7+
8+
interface CorrelationIdAdapter
9+
{
10+
public function enableCorrelationId($projectKey = null);
11+
}

src/Core/Client/Adapter/Guzzle5Adapter.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace Commercetools\Core\Client\Adapter;
77

8+
use Commercetools\Core\Helper\Subscriber\CorrelationIdSubscriber;
89
use GuzzleHttp\Client;
910
use GuzzleHttp\Exception\RequestException;
1011
use GuzzleHttp\Pool;
@@ -17,7 +18,7 @@
1718
use Commercetools\Core\Error\ApiException;
1819
use Psr\Log\LogLevel;
1920

20-
class Guzzle5Adapter implements AdapterInterface
21+
class Guzzle5Adapter implements AdapterInterface, CorrelationIdAdapter
2122
{
2223
/**
2324
* @var Client
@@ -68,6 +69,13 @@ public function addHandler($handler)
6869
$this->getEmitter()->attach($handler);
6970
}
7071

72+
public function enableCorrelationId($projectKey = null)
73+
{
74+
if (class_exists('\Ramsey\Uuid\Uuid')) {
75+
$this->getEmitter()->attach(new CorrelationIdSubscriber($projectKey));
76+
};
77+
}
78+
7179
/**
7280
* @internal
7381
* @return \GuzzleHttp\Event\Emitter|\GuzzleHttp\Event\EmitterInterface

src/Core/Client/Adapter/Guzzle6Adapter.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
use Commercetools\Core\Error\Message;
1919
use Commercetools\Core\Error\ApiException;
2020
use Psr\Log\LogLevel;
21+
use Ramsey\Uuid\Uuid;
2122

22-
class Guzzle6Adapter implements AdapterInterface
23+
class Guzzle6Adapter implements AdapterInterface, CorrelationIdAdapter
2324
{
2425
/**
2526
* @var Client
@@ -52,6 +53,20 @@ public function setLogger(LoggerInterface $logger, $logLevel = LogLevel::INFO, $
5253
$this->addHandler(self::log($logger, $formatter, $logLevel));
5354
}
5455

56+
public function enableCorrelationId($projectKey = null)
57+
{
58+
if (class_exists('\Ramsey\Uuid\Uuid')) {
59+
$projectKey = !is_null($projectKey) ? $projectKey : 'php';
60+
$this->addHandler(Middleware::mapRequest(function (RequestInterface $request) use ($projectKey) {
61+
$uuid = Uuid::uuid4()->toString();
62+
return $request->withAddedHeader(
63+
AbstractApiResponse::X_CORRELATION_ID,
64+
$projectKey . '-' . $uuid
65+
);
66+
}));
67+
};
68+
}
69+
5570
/**
5671
* Middleware that logs requests, responses, and errors using a message
5772
* formatter.

src/Core/Config.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ class Config implements ContextAwareInterface
152152

153153
protected $messageFormatter;
154154

155+
protected $enableCorrelationId = false;
156+
155157
/**
156158
* @param array $configValues
157159
* @return static
@@ -405,7 +407,7 @@ public function getThrowExceptions()
405407
*/
406408
public function setThrowExceptions($throwExceptions)
407409
{
408-
$this->throwExceptions = $throwExceptions;
410+
$this->throwExceptions = (bool)$throwExceptions;
409411

410412
return $this;
411413
}
@@ -587,4 +589,22 @@ public function setMessageFormatter($messageFormatter)
587589
$this->messageFormatter = $messageFormatter;
588590
return $this;
589591
}
592+
593+
/**
594+
* @return bool
595+
*/
596+
public function getEnableCorrelationId()
597+
{
598+
return $this->enableCorrelationId;
599+
}
600+
601+
/**
602+
* @param bool $enableCorrelationId
603+
* @return Config
604+
*/
605+
public function setEnableCorrelationId($enableCorrelationId)
606+
{
607+
$this->enableCorrelationId = (bool)$enableCorrelationId;
608+
return $this;
609+
}
590610
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
/**
3+
* @author @jayS-de <jens.schulze@commercetools.de>
4+
*/
5+
6+
namespace Commercetools\Core\Helper\Subscriber;
7+
8+
use Commercetools\Core\Response\AbstractApiResponse;
9+
use GuzzleHttp\Event\BeforeEvent;
10+
use GuzzleHttp\Event\RequestEvents;
11+
use GuzzleHttp\Event\SubscriberInterface;
12+
use Ramsey\Uuid\Uuid;
13+
14+
class CorrelationIdSubscriber implements SubscriberInterface
15+
{
16+
private $projectKey;
17+
18+
public function __construct($projectKey = null)
19+
{
20+
$projectKey = !is_null($projectKey) ? $projectKey : 'php';
21+
$this->projectKey = $projectKey;
22+
}
23+
24+
public function getEvents()
25+
{
26+
return ['before' => ['onBefore', RequestEvents::PREPARE_REQUEST - 10]];
27+
}
28+
29+
public function onBefore(BeforeEvent $event, $name)
30+
{
31+
$event->getRequest()->addHeader(AbstractApiResponse::X_CORRELATION_ID, $this->getCorrelationId());
32+
}
33+
34+
private function getCorrelationId()
35+
{
36+
return $this->projectKey . '-' . Uuid::uuid4()->toString();
37+
}
38+
}

tests/integration/ClientTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
/**
3+
* @author @jayS-de <jens.schulze@commercetools.de>
4+
*/
5+
6+
namespace Commercetools\Core\Project;
7+
8+
use Commercetools\Core\ApiTestCase;
9+
use Commercetools\Core\Model\Project\Project;
10+
use Commercetools\Core\Request\Project\ProjectGetRequest;
11+
use Commercetools\Core\Response\AbstractApiResponse;
12+
13+
class ClientTest extends ApiTestCase
14+
{
15+
public function testCorrelationId()
16+
{
17+
$request = ProjectGetRequest::of();
18+
19+
$response = $request->executeWithClient($this->getClient());
20+
$result = $request->mapResponse($response);
21+
22+
$this->assertInstanceOf(Project::class, $result);
23+
$this->assertStringStartsWith(
24+
$this->getClient()->getConfig()->getProject(),
25+
current($response->getHeader(AbstractApiResponse::X_CORRELATION_ID))
26+
);
27+
}
28+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
/**
3+
* @author @jayS-de <jens.schulze@commercetools.de>
4+
*/
5+
6+
namespace Commercetools\Core\Project;
7+
8+
use Commercetools\Core\ApiTestCase;
9+
use Commercetools\Core\Model\Project\Project;
10+
use Commercetools\Core\Request\Project\ProjectGetRequest;
11+
12+
class ProjectGetRequestTest extends ApiTestCase
13+
{
14+
public function testGetProject()
15+
{
16+
$request = ProjectGetRequest::of();
17+
18+
$response = $request->executeWithClient($this->getClient());
19+
$result = $request->mapResponse($response);
20+
21+
$this->assertInstanceOf(Project::class, $result);
22+
$this->assertSame($this->getClient()->getConfig()->getProject(), $result->getKey());
23+
}
24+
}

tests/myapp.yml.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ parameters:
44
project: Your Commercetools project key
55
oauth_url: https://auth.sphere.io
66
api_url: https://api.sphere.io
7+
enableCorrelationId: 1

0 commit comments

Comments
 (0)