Skip to content

Commit c06f154

Browse files
committed
RedirectPlugin: Default to empty path when Location doesn't specify any
1 parent a2dd39f commit c06f154

File tree

4 files changed

+65
-16
lines changed

4 files changed

+65
-16
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Change Log
22

3+
## 2.5.1 - 2022-09-??
4+
5+
### Fixed
6+
7+
- Fixes false positive circular detection in RedirectPlugin in cases when target location does not contain path
8+
39
## 2.5.0 - 2021-11-26
410

511
### Added

spec/Plugin/RedirectPluginSpec.php

+6
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ public function it_replace_full_url(
162162

163163
$request->getUri()->willReturn($uri);
164164
$uri->withScheme('https')->willReturn($uriRedirect);
165+
$uri->withPath('/redirect')->willReturn($uri);
166+
$uri->withQuery('query')->willReturn($uri);
167+
$uri->withFragment('fragment')->willReturn($uri);
165168
$uriRedirect->withHost('server.com')->willReturn($uriRedirect);
166169
$uriRedirect->withPort('8000')->willReturn($uriRedirect);
167170
$uriRedirect->withPath('/redirect')->willReturn($uriRedirect);
@@ -520,6 +523,9 @@ public function it_redirects_http_to_https(
520523
$request->getUri()->willReturn($uri);
521524
$request->withUri($uriRedirect)->willReturn($modifiedRequest);
522525
$uri->__toString()->willReturn('http://my-site.com/original');
526+
$uri->withPath('/original')->willReturn($uri);
527+
$uri->withFragment('')->willReturn($uri);
528+
$uri->withQuery('')->willReturn($uri);
523529

524530
$uri->withScheme('https')->willReturn($uriRedirect);
525531
$uriRedirect->withHost('my-site.com')->willReturn($uriRedirect);

src/Plugin/RedirectPlugin.php

+5-16
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,11 @@ private function createUri(ResponseInterface $redirectResponse, RequestInterface
231231
}
232232

233233
$uri = $originalRequest->getUri();
234+
$uri = $uri
235+
->withPath(array_key_exists('path', $parsedLocation) ? $parsedLocation['path'] : '')
236+
->withQuery(array_key_exists('query', $parsedLocation) ? $parsedLocation['query'] : '')
237+
->withFragment(array_key_exists('fragment', $parsedLocation) ? $parsedLocation['fragment'] : '')
238+
;
234239

235240
if (array_key_exists('scheme', $parsedLocation)) {
236241
$uri = $uri->withScheme($parsedLocation['scheme']);
@@ -244,22 +249,6 @@ private function createUri(ResponseInterface $redirectResponse, RequestInterface
244249
$uri = $uri->withPort($parsedLocation['port']);
245250
}
246251

247-
if (array_key_exists('path', $parsedLocation)) {
248-
$uri = $uri->withPath($parsedLocation['path']);
249-
}
250-
251-
if (array_key_exists('query', $parsedLocation)) {
252-
$uri = $uri->withQuery($parsedLocation['query']);
253-
} else {
254-
$uri = $uri->withQuery('');
255-
}
256-
257-
if (array_key_exists('fragment', $parsedLocation)) {
258-
$uri = $uri->withFragment($parsedLocation['fragment']);
259-
} else {
260-
$uri = $uri->withFragment('');
261-
}
262-
263252
return $uri;
264253
}
265254
}

tests/Plugin/RedirectPluginTest.php

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Plugin;
5+
6+
use Http\Client\Common\Exception\CircularRedirectionException;
7+
use Http\Client\Common\Plugin\RedirectPlugin;
8+
use Http\Promise\FulfilledPromise;
9+
use Nyholm\Psr7\Request;
10+
use Nyholm\Psr7\Response;
11+
use PHPUnit\Framework\TestCase;
12+
use Psr\Http\Message\RequestInterface;
13+
use Psr\Http\Message\ResponseInterface;
14+
15+
class RedirectPluginTest extends TestCase
16+
{
17+
public function testCircularDetection(): void
18+
{
19+
$this->expectException(CircularRedirectionException::class);
20+
(new RedirectPlugin())->handleRequest(
21+
new Request('GET', 'https://example.com/path?query=value'),
22+
function () {
23+
return new FulfilledPromise(new Response(302, ['Location' => 'https://example.com/path?query=value']));
24+
},
25+
function () {}
26+
)->wait();
27+
}
28+
29+
/**
30+
* @testWith ["https://example.com/path?query=value", "https://example.com?query=value", "https://example.com?query=value"]
31+
* ["https://example.com/path?query=value", "https://example.com/?query=value", "https://example.com/?query=value"]
32+
* ["https://example.com", "https://example.com?query=value", "https://example.com?query=value"]
33+
*/
34+
public function testTargetUriMappingFromLocationHeader(string $originalUri, string $locationUri, string $targetUri): void
35+
{
36+
$response = (new RedirectPlugin())->handleRequest(
37+
new Request('GET', $originalUri),
38+
function () use ($locationUri) {
39+
return new FulfilledPromise(new Response(302, ['Location' => $locationUri]));
40+
},
41+
function (RequestInterface $request) {
42+
return new FulfilledPromise(new Response(200, ['uri' => $request->getUri()->__toString()]));
43+
}
44+
)->wait();
45+
$this->assertInstanceOf(ResponseInterface::class, $response);
46+
$this->assertEquals($targetUri, $response->getHeaderLine('uri'));
47+
}
48+
}

0 commit comments

Comments
 (0)