diff --git a/src/Common/Api/OperatorTrait.php b/src/Common/Api/OperatorTrait.php index fe1de8a7..5d2e94da 100644 --- a/src/Common/Api/OperatorTrait.php +++ b/src/Common/Api/OperatorTrait.php @@ -105,9 +105,8 @@ protected function sendRequest(Operation $operation, array $userValues = [], boo $options += $userValues['requestOptions']; } - if ($operation->getSkipAuth()) { - $options['openstack.skip_auth'] = true; - } + $options['openstack.skip_auth'] = $operation->getSkipAuth(); + print_r($options); return $this->client->$method($operation->getMethod(), $uri, $options); } diff --git a/src/Common/Auth/AuthHandler.php b/src/Common/Auth/AuthHandler.php index 28df0d1c..48739d10 100644 --- a/src/Common/Auth/AuthHandler.php +++ b/src/Common/Auth/AuthHandler.php @@ -43,7 +43,12 @@ public function __invoke(RequestInterface $request, array $options) { $fn = $this->nextHandler; - if (isset($options['openstack.skip_auth']) && $options['openstack.skip_auth']) { + if (!isset($options['openstack.skip_auth'])){ + // Deprecated. Left for backward compatibility only. + if ($this->shouldIgnore($request)) { + return $fn($request, $options); + } + } else if ($options['openstack.skip_auth']) { return $fn($request, $options); } @@ -55,4 +60,13 @@ public function __invoke(RequestInterface $request, array $options) return $fn(Utils::modifyRequest($request, $modify), $options); } + + /** + * Internal method which prevents infinite recursion. For certain requests, like the initial + * auth call itself, we do NOT want to send a token. + */ + private function shouldIgnore(RequestInterface $request): bool + { + return false !== strpos((string) $request->getUri(), 'tokens') && 'POST' == $request->getMethod(); + } } diff --git a/tests/unit/Common/Auth/AuthHandlerTest.php b/tests/unit/Common/Auth/AuthHandlerTest.php index 2ada179a..d7301899 100644 --- a/tests/unit/Common/Auth/AuthHandlerTest.php +++ b/tests/unit/Common/Auth/AuthHandlerTest.php @@ -38,6 +38,14 @@ public function test_it_should_bypass_auth_http_requests() self::assertEquals($request, call_user_func_array($this->handler, [$request, ['openstack.skip_auth' => true]])); } + public function test_it_should_bypass_auth_http_requests_backward_compatibility() + { + // Fake a Keystone request + $request = new Request('POST', 'https://my-openstack.org:5000/v2.0/tokens'); + + self::assertEquals($request, call_user_func_array($this->handler, [$request, []])); + } + public function test_it_should_generate_a_new_token_if_the_current_token_is_either_expired_or_not_set() { $token = $this->prophesize(Token::class); diff --git a/tests/unit/TestCase.php b/tests/unit/TestCase.php index 7ba925bf..658548a7 100644 --- a/tests/unit/TestCase.php +++ b/tests/unit/TestCase.php @@ -6,6 +6,7 @@ use GuzzleHttp\Psr7\Message; use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Utils; +use Prophecy\Prophecy\MethodProphecy; abstract class TestCase extends \PHPUnit\Framework\TestCase { @@ -42,9 +43,12 @@ protected function getFixture($file) return Message::parseResponse(file_get_contents($path)); } - protected function setupMock($method, $path, $body = null, array $headers = [], $response = null, $skipAuth = false) + protected function setupMock($method, $path, $body = null, array $headers = [], $response = null, $skipAuth = false): MethodProphecy { - $options = ['headers' => $headers]; + $options = [ + 'headers' => $headers, + 'openstack.skip_auth' => $skipAuth, + ]; if (!empty($body)) { $options[is_array($body) ? 'json' : 'body'] = $body; @@ -54,11 +58,7 @@ protected function setupMock($method, $path, $body = null, array $headers = [], $response = $this->getFixture($response); } - if ($skipAuth) { - $options['openstack.skip_auth'] = true; - } - - $this->client + return $this->client ->request($method, $path, $options) ->shouldBeCalled() ->willReturn($response);