Skip to content

Commit 0bb2373

Browse files
authored
API-1853: Add capability to change user-agent header
1 parent e19abf6 commit 0bb2373

File tree

6 files changed

+154
-7
lines changed

6 files changed

+154
-7
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,18 @@ $client->getProductApi()->upsertList([
148148
]);
149149
```
150150

151+
### Headers option
152+
153+
You can make the client send requests with additional headers. Default client headers can be overriden.
154+
155+
```php
156+
$clientBuilder = new \Akeneo\Pim\ApiClient\AkeneoPimClientBuilder(
157+
'http://localhost',
158+
['headers' => ['X-HEADER-NAME' => 'content']]
159+
);
160+
$client = $clientBuilder->buildAuthenticatedByToken('token');
161+
```
162+
151163
## Testing
152164

153165
Do note that you have to delete the `composer.lock` because Doctrine dependencies are loaded.

spec/Client/HttpClientSpec.php

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

55
use Akeneo\Pim\ApiClient\Client\HttpClient;
66
use Akeneo\Pim\ApiClient\Client\HttpClientInterface;
7+
use Akeneo\Pim\ApiClient\Client\Options;
78
use Akeneo\Pim\ApiClient\Exception\HttpException;
89
use PhpSpec\ObjectBehavior;
910
use Psr\Http\Client\ClientInterface;
@@ -18,9 +19,10 @@ class HttpClientSpec extends ObjectBehavior
1819
function let(
1920
ClientInterface $httpClient,
2021
RequestFactoryInterface $requestFactory,
21-
StreamFactoryInterface $streamFactory
22+
StreamFactoryInterface $streamFactory,
23+
Options $options
2224
) {
23-
$this->beConstructedWith($httpClient, $requestFactory, $streamFactory);
25+
$this->beConstructedWith($httpClient, $requestFactory, $streamFactory, $options);
2426
}
2527

2628
function it_is_initializable()
@@ -35,7 +37,8 @@ function it_sends_a_successful_request(
3537
StreamFactoryInterface $streamFactory,
3638
StreamInterface $stream,
3739
RequestInterface $request,
38-
ResponseInterface $response
40+
ResponseInterface $response,
41+
Options $options
3942
) {
4043
$requestFactory->createRequest(
4144
'POST',
@@ -53,6 +56,7 @@ function it_sends_a_successful_request(
5356

5457
$response->getStatusCode()->willReturn(HttpClient::HTTP_OK);
5558

59+
$options->hasHeaders()->willReturn(false);
5660
$request->withBody($stream)->willReturn($request);
5761
$request->withHeader('Content-Type', 'application/json')->willReturn($request);
5862

@@ -73,7 +77,8 @@ function it_throws_an_exception_when_failing_request(
7377
StreamInterface $stream,
7478
RequestInterface $request,
7579
ResponseInterface $response,
76-
StreamInterface $responseBody
80+
StreamInterface $responseBody,
81+
Options $options
7782
) {
7883
$requestFactory->createRequest(
7984
'POST',
@@ -89,6 +94,7 @@ function it_throws_an_exception_when_failing_request(
8994
'http://akeneo.com/api/rest/v1/products/foo'
9095
)->willReturn($request);
9196

97+
$options->hasHeaders()->willReturn(false);
9298
$request->withBody($stream)->willReturn($request);
9399
$request->withHeader('Content-Type', 'application/json')->willReturn($request);
94100

src/AkeneoPimClientBuilder.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
use Akeneo\Pim\ApiClient\Client\AuthenticatedHttpClient;
4141
use Akeneo\Pim\ApiClient\Client\CachedResourceClient;
4242
use Akeneo\Pim\ApiClient\Client\HttpClient;
43+
use Akeneo\Pim\ApiClient\Client\Options;
4344
use Akeneo\Pim\ApiClient\Client\ResourceClient;
4445
use Akeneo\Pim\ApiClient\FileSystem\FileSystemInterface;
4546
use Akeneo\Pim\ApiClient\FileSystem\LocalFileSystem;
@@ -80,14 +81,17 @@ class AkeneoPimClientBuilder
8081
/** @var FileSystemInterface */
8182
protected $fileSystem;
8283

84+
protected Options $options;
85+
8386
protected bool $cacheEnabled = false;
8487

8588
/**
8689
* @param string $baseUri Base uri to request the API
8790
*/
88-
public function __construct(string $baseUri)
91+
public function __construct(string $baseUri, array $options = [])
8992
{
9093
$this->baseUri = $baseUri;
94+
$this->options = Options::fromArray($options);
9195
}
9296

9397
/**
@@ -255,7 +259,7 @@ protected function setUp(Authentication $authentication): array
255259
{
256260
$uriGenerator = new UriGenerator($this->baseUri);
257261

258-
$httpClient = new HttpClient($this->getHttpClient(), $this->getRequestFactory(), $this->getStreamFactory());
262+
$httpClient = new HttpClient($this->getHttpClient(), $this->getRequestFactory(), $this->getStreamFactory(), $this->options);
259263
$authenticationApi = new AuthenticationApi($httpClient, $uriGenerator);
260264
$authenticatedHttpClient = new AuthenticatedHttpClient($httpClient, $authenticationApi, $authentication);
261265

src/Client/HttpClient.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,19 @@ class HttpClient implements HttpClientInterface
3434
protected RequestFactoryInterface $requestFactory;
3535
protected HttpExceptionHandler $httpExceptionHandler;
3636
private StreamFactoryInterface $streamFactory;
37+
private Options $options;
3738

3839
public function __construct(
3940
ClientInterface $httpClient,
4041
RequestFactoryInterface $requestFactory,
41-
StreamFactoryInterface $streamFactory
42+
StreamFactoryInterface $streamFactory,
43+
Options $options
4244
) {
4345
$this->httpClient = $httpClient;
4446
$this->requestFactory = $requestFactory;
4547
$this->streamFactory = $streamFactory;
4648
$this->httpExceptionHandler = new HttpExceptionHandler();
49+
$this->options = $options;
4750
}
4851

4952
/**
@@ -64,6 +67,12 @@ public function sendRequest(string $httpMethod, $uri, array $headers = [], $body
6467
$request = $request->withHeader($header, $content);
6568
}
6669

70+
if ($this->options->hasHeaders()) {
71+
foreach ($this->options->getHeaders() as $header => $content) {
72+
$request = $request->withHeader($header, $content);
73+
}
74+
}
75+
6776
$response = $this->httpClient->sendRequest($request);
6877
$response = $this->httpExceptionHandler->transformResponseToException($request, $response);
6978

src/Client/Options.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Akeneo\Pim\ApiClient\Client;
6+
7+
use Symfony\Component\OptionsResolver\OptionsResolver;
8+
9+
class Options
10+
{
11+
private array $options;
12+
13+
private function __construct(array $options)
14+
{
15+
$this->options = $options;
16+
}
17+
18+
public static function fromArray(array $options): self
19+
{
20+
$resolver = new OptionsResolver();
21+
22+
$resolver->setDefaults([
23+
'headers' => [],
24+
]);
25+
$resolver->setAllowedTypes('headers', 'string[]');
26+
27+
$options = $resolver->resolve($options);
28+
29+
return new self($options);
30+
}
31+
32+
public function hasHeaders(): bool
33+
{
34+
return [] !== $this->options['headers'];
35+
}
36+
37+
/**
38+
* @return string[]
39+
*/
40+
public function getHeaders(): array
41+
{
42+
return $this->options['headers'];
43+
}
44+
}

tests/Client/OptionsTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace Akeneo\Pim\ApiClient\tests\Client;
4+
5+
use Akeneo\Pim\ApiClient\Client\Options;
6+
use Akeneo\Pim\ApiClient\tests\Api\ApiTestCase;
7+
8+
class OptionsTest extends ApiTestCase
9+
{
10+
public function testInvalidOption(): void
11+
{
12+
$this->expectException(\InvalidArgumentException::class);
13+
14+
Options::fromArray(['unknown_option' => 'unknown_value']);
15+
}
16+
17+
/**
18+
* @dataProvider validHeadersOptionProvider
19+
*/
20+
public function testHeadersOption(array $inputOptions, array $expectedHeadersOption, bool $hasHeaders): void
21+
{
22+
$options = Options::fromArray($inputOptions);
23+
24+
$this->assertSame($hasHeaders, $options->hasHeaders());
25+
$this->assertSame($expectedHeadersOption, $options->getHeaders());
26+
}
27+
28+
public function validHeadersOptionProvider(): array
29+
{
30+
return [
31+
'empty array' => [
32+
[],
33+
[],
34+
false,
35+
],
36+
'empty headers option' => [
37+
['headers' => []],
38+
[],
39+
false,
40+
],
41+
'filled headers option' => [
42+
['headers' => ['X-HEADER' => 'content']],
43+
['X-HEADER' => 'content'],
44+
true,
45+
],
46+
];
47+
}
48+
49+
/**
50+
* @dataProvider invalidHeadersOptionProvider
51+
*/
52+
public function testInvalidHeadersOption($invalidValue): void
53+
{
54+
$this->expectException(\InvalidArgumentException::class);
55+
56+
Options::fromArray(['headers' => $invalidValue]);
57+
}
58+
59+
public function invalidHeadersOptionProvider(): array
60+
{
61+
return [
62+
[10],
63+
[10.45],
64+
[true],
65+
[new \StdClass()],
66+
[['X-HEADER' => 10]],
67+
[['X-HEADER' => 10.45]],
68+
[['X-HEADER' => true]],
69+
[['X-HEADER' => new \StdClass()]],
70+
];
71+
}
72+
}

0 commit comments

Comments
 (0)