Skip to content

Commit baefb00

Browse files
committed
Merge pull request #45 from php-http/options-resolver
use options resolver where applicable, fix decoder plugin gzip handling
2 parents 7431044 + 2e484a6 commit baefb00

7 files changed

+76
-23
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Change Log
22

3+
### Changed
4+
5+
- Using array options for DecoderPlugin, RedirectPlugin and RetryPlugin
6+
7+
### Fixed
8+
9+
- Decoder plugin no longer sends accept header for encodings that require gzip if gzip is not available
310

411
## 0.1.0 - 2016-01-13
512

spec/DecoderPluginSpec.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ function it_decodes_inflate(RequestInterface $request, ResponseInterface $respon
116116

117117
function it_does_not_decode_with_content_encoding(RequestInterface $request, ResponseInterface $response)
118118
{
119-
$this->beConstructedWith(false);
119+
$this->beConstructedWith(['use_content_encoding' => false]);
120120

121121
$request->withHeader('TE', ['gzip', 'deflate', 'compress', 'chunked'])->shouldBeCalled()->willReturn($request);
122122
$request->withHeader('Accept-Encoding', ['gzip', 'deflate', 'compress'])->shouldNotBeCalled();

spec/RedirectPluginSpec.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ function it_throw_multi_redirect_exception_on_300(RequestInterface $request, Res
223223
}
224224
};
225225

226-
$this->beConstructedWith(true, false);
226+
$this->beConstructedWith(['preserve_header' => true, 'use_default_for_multiple' => false]);
227227
$responseRedirect->getStatusCode()->willReturn('300');
228228

229229
$promise = $this->handleRequest($request, $next, function () {});
@@ -301,7 +301,7 @@ function it_clears_headers(
301301
ResponseInterface $finalResponse,
302302
Promise $promise
303303
) {
304-
$this->beConstructedWith(['Accept']);
304+
$this->beConstructedWith(['preserve_header' => ['Accept']]);
305305

306306
$request->getRequestTarget()->willReturn('/original');
307307

@@ -377,9 +377,9 @@ function it_throws_circular_redirection_exception(UriInterface $uri, UriInterfac
377377

378378
class RedirectPluginStub extends RedirectPlugin
379379
{
380-
public function __construct(UriInterface $uri, $storedUrl, $status, $preserveHeader = true, $useDefaultForMultiple = true)
380+
public function __construct(UriInterface $uri, $storedUrl, $status, array $config = [])
381381
{
382-
parent::__construct($preserveHeader, $useDefaultForMultiple);
382+
parent::__construct($config);
383383

384384
$this->redirectStorage[$storedUrl] = [
385385
'uri' => $uri,

src/CachePlugin.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class CachePlugin implements Plugin
3232
private $config;
3333

3434
/**
35-
* Available options are
35+
* Available options for $config are
3636
* - respect_cache_headers: Whether to look at the cache directives or ignore them.
3737
* - default_ttl: If we do not respect cache headers or can't calculate a good ttl, use this value.
3838
*

src/DecoderPlugin.php

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,15 @@
99
use Psr\Http\Message\RequestInterface;
1010
use Psr\Http\Message\ResponseInterface;
1111
use Psr\Http\Message\StreamInterface;
12+
use Symfony\Component\OptionsResolver\OptionsResolver;
1213

1314
/**
1415
* Allow to decode response body with a chunk, deflate, compress or gzip encoding.
1516
*
17+
* If zlib is not installed, only chunked encoding can be handled.
18+
*
19+
* If Content-Encoding is not disabled, the plugin will add an Accept-Encoding header for the encoding methods it supports.
20+
*
1621
* @author Joel Wurtz <[email protected]>
1722
*/
1823
class DecoderPlugin implements Plugin
@@ -25,25 +30,35 @@ class DecoderPlugin implements Plugin
2530
private $useContentEncoding;
2631

2732
/**
28-
* @param bool $useContentEncoding Whether this plugin decode stream with value in the Content-Encoding header (default to true).
33+
* Available options for $config are:
34+
* - use_content_encoding: Whether this plugin should look at the Content-Encoding header first or only at the Transfer-Encoding (defaults to true).
2935
*
30-
* If set to false only the Transfer-Encoding header will be used.
36+
* @param array $config
3137
*/
32-
public function __construct($useContentEncoding = true)
38+
public function __construct(array $config = [])
3339
{
34-
$this->useContentEncoding = $useContentEncoding;
40+
$resolver = new OptionsResolver();
41+
$resolver->setDefaults([
42+
'use_content_encoding' => true,
43+
]);
44+
$resolver->setAllowedTypes('use_content_encoding', 'bool');
45+
$options = $resolver->resolve($config);
46+
47+
$this->useContentEncoding = $options['use_content_encoding'];
3548
}
3649

3750
/**
3851
* {@inheritdoc}
3952
*/
4053
public function handleRequest(RequestInterface $request, callable $next, callable $first)
4154
{
42-
$request = $request->withHeader('TE', ['gzip', 'deflate', 'compress', 'chunked']);
55+
$encodings = extension_loaded('zlib') ? ['gzip', 'deflate', 'compress'] : [];
4356

44-
if ($this->useContentEncoding) {
45-
$request = $request->withHeader('Accept-Encoding', ['gzip', 'deflate', 'compress']);
57+
if ($this->useContentEncoding && count($encodings)) {
58+
$request = $request->withHeader('Accept-Encoding', $encodings);
4659
}
60+
$encodings[] = 'chunked';
61+
$request = $request->withHeader('TE', $encodings);
4762

4863
return $next($request)->then(function (ResponseInterface $response) {
4964
return $this->decodeResponse($response);

src/RedirectPlugin.php

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Psr\Http\Message\RequestInterface;
1010
use Psr\Http\Message\ResponseInterface;
1111
use Psr\Http\Message\UriInterface;
12+
use Symfony\Component\OptionsResolver\OptionsResolver;
1213

1314
/**
1415
* Follow redirections.
@@ -74,7 +75,7 @@ class RedirectPlugin implements Plugin
7475
*
7576
* true will keep all previous headers (default value)
7677
* false will ditch all previous headers
77-
* string[] will keep only headers specified in this array
78+
* string[] will keep only headers with the specified names
7879
*/
7980
protected $preserveHeader;
8081

@@ -98,13 +99,32 @@ class RedirectPlugin implements Plugin
9899
protected $circularDetection = [];
99100

100101
/**
101-
* @param bool $preserveHeader
102-
* @param bool $useDefaultForMultiple
102+
* Available options for $config are:
103+
* - preserve_header: bool|string[] True keeps all headers, false remove all of them, an array is interpreted as a list of header names to keep.
104+
* - use_default_for_multiple: Whether the location header must be directly used for a multiple redirection status code (300).
105+
*
106+
* @param array $config
103107
*/
104-
public function __construct($preserveHeader = true, $useDefaultForMultiple = true)
108+
public function __construct(array $config = [])
105109
{
106-
$this->useDefaultForMultiple = $useDefaultForMultiple;
107-
$this->preserveHeader = false === $preserveHeader ? [] : $preserveHeader;
110+
$resolver = new OptionsResolver();
111+
$resolver->setDefaults([
112+
'preserve_header' => true,
113+
'use_default_for_multiple' => true,
114+
]);
115+
$resolver->setAllowedTypes('preserve_header', ['bool', 'array']);
116+
$resolver->setAllowedTypes('use_default_for_multiple', 'bool');
117+
$resolver->setNormalizer('preserve_header', function (OptionsResolver $resolver, $value) {
118+
if (is_bool($value) && false === $value) {
119+
return [];
120+
}
121+
122+
return $value;
123+
});
124+
$options = $resolver->resolve($config);
125+
126+
$this->preserveHeader = $options['preserve_header'];
127+
$this->useDefaultForMultiple = $options['use_default_for_multiple'];
108128
}
109129

110130
/**

src/RetryPlugin.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
use Http\Client\Exception;
66
use Psr\Http\Message\RequestInterface;
77
use Psr\Http\Message\ResponseInterface;
8+
use Symfony\Component\OptionsResolver\OptionsResolver;
89

910
/**
10-
* Retry the request if it has somehow failed.
11+
* Retry the request if an exception is thrown.
1112
*
1213
* By default will retry only one time.
1314
*
@@ -30,11 +31,21 @@ class RetryPlugin implements Plugin
3031
private $retryStorage = [];
3132

3233
/**
33-
* @param int $retry Number of retry before sending an exception
34+
* Available options for $config are:
35+
* - retries: Number of retries to attempt if an exception occurs before letting the exception bubble up.
36+
*
37+
* @param array $config
3438
*/
35-
public function __construct($retry = 1)
39+
public function __construct(array $config = [])
3640
{
37-
$this->retry = $retry;
41+
$resolver = new OptionsResolver();
42+
$resolver->setDefaults([
43+
'retries' => 1,
44+
]);
45+
$resolver->setAllowedTypes('retries', 'int');
46+
$options = $resolver->resolve($config);
47+
48+
$this->retry = $options['retries'];
3849
}
3950

4051
/**

0 commit comments

Comments
 (0)