From bbea2140ef541e1fa55dd35490ab95c7232e542e Mon Sep 17 00:00:00 2001 From: Olexiy Kyrychenko Date: Fri, 2 Jul 2021 13:15:24 +0200 Subject: [PATCH 1/3] Added `strict` option for RedirectPlugin not to modify request method on statuses 300, 301, 302 --- CHANGELOG.md | 18 ++++++++---- spec/Plugin/RedirectPluginSpec.php | 47 +++++++++++++++++++++++++++++- src/Plugin/RedirectPlugin.php | 9 ++++++ 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a7b201..2cc7d6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 2.4.0 (unreleased) + +### Added + +- `strict` option to `RedirectPlugin` + ## 2.3.0 - 2020-07-21 ### Fixed @@ -112,7 +118,7 @@ ## 1.7.0 - 2017-11-30 -### Added +### Added - Symfony 4 support @@ -132,12 +138,12 @@ ### Changed -- The `RetryPlugin` does now wait between retries. To disable/change this feature you must write something like: - +- The `RetryPlugin` does now wait between retries. To disable/change this feature you must write something like: + ```php -$plugin = new RetryPlugin(['delay' => function(RequestInterface $request, Exception $e, $retries) { - return 0; -}); +$plugin = new RetryPlugin(['delay' => function(RequestInterface $request, Exception $e, $retries) { + return 0; +}); ``` ### Deprecated diff --git a/spec/Plugin/RedirectPluginSpec.php b/spec/Plugin/RedirectPluginSpec.php index 3342f60..475d458 100644 --- a/spec/Plugin/RedirectPluginSpec.php +++ b/spec/Plugin/RedirectPluginSpec.php @@ -286,11 +286,56 @@ public function it_switch_method_for_302( $request->withUri($uriRedirect)->willReturn($modifiedRequest); $modifiedRequest->getUri()->willReturn($uriRedirect); + $uriRedirect->__toString()->willReturn('/redirect'); + $modifiedRequest->getMethod()->willReturn('POST'); + $modifiedRequest->withMethod('GET')->shouldBeCalled()->willReturn($modifiedRequest); + + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { + if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { + return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); + } + }; + + $first = function (RequestInterface $receivedRequest) use ($modifiedRequest, $promise) { + if (Argument::is($modifiedRequest->getWrappedObject())->scoreArgument($receivedRequest)) { + return $promise->getWrappedObject(); + } + }; + + $promise->getState()->willReturn(Promise::FULFILLED); + $promise->wait()->shouldBeCalled()->willReturn($finalResponse); + + $this->handleRequest($request, $next, $first); + } + + public function it_does_not_switch_method_for_302_with_strict_option( + UriInterface $uri, + UriInterface $uriRedirect, + RequestInterface $request, + ResponseInterface $responseRedirect, + RequestInterface $modifiedRequest, + ResponseInterface $finalResponse, + Promise $promise + ) { + $this->beConstructedWith(['strict' => true]); + + $request->getUri()->willReturn($uri); + $uri->__toString()->willReturn('/original'); + $responseRedirect->getStatusCode()->willReturn(302); + $responseRedirect->hasHeader('Location')->willReturn(true); + $responseRedirect->getHeaderLine('Location')->willReturn('/redirect'); + + $request->getUri()->willReturn($uri); + $uri->withPath('/redirect')->willReturn($uriRedirect); + $uriRedirect->withFragment('')->willReturn($uriRedirect); + $uriRedirect->withQuery('')->willReturn($uriRedirect); + + $request->withUri($uriRedirect)->willReturn($modifiedRequest); $modifiedRequest->getUri()->willReturn($uriRedirect); $uriRedirect->__toString()->willReturn('/redirect'); $modifiedRequest->getMethod()->willReturn('POST'); - $modifiedRequest->withMethod('GET')->willReturn($modifiedRequest); + $modifiedRequest->withMethod('GET')->shouldNotBeCalled(); $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { diff --git a/src/Plugin/RedirectPlugin.php b/src/Plugin/RedirectPlugin.php index 061f35b..2de8925 100644 --- a/src/Plugin/RedirectPlugin.php +++ b/src/Plugin/RedirectPlugin.php @@ -106,6 +106,7 @@ final class RedirectPlugin implements Plugin * * @var bool|string[] $preserve_header True keeps all headers, false remove all of them, an array is interpreted as a list of header names to keep * @var bool $use_default_for_multiple Whether the location header must be directly used for a multiple redirection status code (300). + * @var bool $strict When true, redirect codes 300, 301, 302 will not modify request method and body. * } */ public function __construct(array $config = []) @@ -114,9 +115,11 @@ public function __construct(array $config = []) $resolver->setDefaults([ 'preserve_header' => true, 'use_default_for_multiple' => true, + 'strict' => false, ]); $resolver->setAllowedTypes('preserve_header', ['bool', 'array']); $resolver->setAllowedTypes('use_default_for_multiple', 'bool'); + $resolver->setAllowedTypes('strict', 'bool'); $resolver->setNormalizer('preserve_header', function (OptionsResolver $resolver, $value) { if (is_bool($value) && false === $value) { return []; @@ -128,6 +131,12 @@ public function __construct(array $config = []) $this->preserveHeader = $options['preserve_header']; $this->useDefaultForMultiple = $options['use_default_for_multiple']; + + if ($options['strict']) { + $this->redirectCodes[300]['switch'] = false; + $this->redirectCodes[301]['switch'] = false; + $this->redirectCodes[302]['switch'] = false; + } } /** From c71419b409c6c9b8f97a8053ffdc18929dfc4d63 Mon Sep 17 00:00:00 2001 From: Olexiy Kyrychenko Date: Fri, 2 Jul 2021 17:23:40 +0200 Subject: [PATCH 2/3] Update CHANGELOG.md added more details on the change Co-authored-by: David Buchmann --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cc7d6a..dccc2f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Added -- `strict` option to `RedirectPlugin` +- `strict` option to `RedirectPlugin` to allow preserving the request method on redirections with status 300, 301 and 302. ## 2.3.0 - 2020-07-21 From c20e24737a52515d2acedff1a3bac8b847385758 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Sat, 3 Jul 2021 08:23:09 +0200 Subject: [PATCH 3/3] Update src/Plugin/RedirectPlugin.php --- src/Plugin/RedirectPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugin/RedirectPlugin.php b/src/Plugin/RedirectPlugin.php index 2de8925..488b3aa 100644 --- a/src/Plugin/RedirectPlugin.php +++ b/src/Plugin/RedirectPlugin.php @@ -105,7 +105,7 @@ final class RedirectPlugin implements Plugin * @param array $config { * * @var bool|string[] $preserve_header True keeps all headers, false remove all of them, an array is interpreted as a list of header names to keep - * @var bool $use_default_for_multiple Whether the location header must be directly used for a multiple redirection status code (300). + * @var bool $use_default_for_multiple Whether the location header must be directly used for a multiple redirection status code (300) * @var bool $strict When true, redirect codes 300, 301, 302 will not modify request method and body. * } */