Skip to content

Commit ee39c1d

Browse files
committed
redirection to different domain must not keep previous port
1 parent 76730e3 commit ee39c1d

File tree

3 files changed

+45
-5
lines changed

3 files changed

+45
-5
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
### Fixed
66

7-
- Fixes false positive circular detection in RedirectPlugin in cases when target location does not contain path
7+
- [RedirectPlugin] Fixed handling of redirection to different domain with default port
8+
- [RedirectPlugin] Fixed false positive circular detection in RedirectPlugin in cases when target location does not contain path
89

910
## 2.5.0 - 2021-11-26
1011

src/Plugin/RedirectPlugin.php

+24-1
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,29 @@ private function createUri(ResponseInterface $redirectResponse, RequestInterface
231231
}
232232

233233
$uri = $originalRequest->getUri();
234+
235+
// Redirections can either use an absolute uri or a relative reference https://www.rfc-editor.org/rfc/rfc3986#section-4.2
236+
// If relative, we need to check if we have an absolute path or not
237+
238+
$path = array_key_exists('path', $parsedLocation) ? $parsedLocation['path'] : '';
239+
if (!array_key_exists('host', $parsedLocation) && '/' !== $location[0]) {
240+
// this is a relative-path reference
241+
$originalPath = $uri->getPath();
242+
if ('' === $path) {
243+
$path = $originalPath;
244+
} elseif (($pos = strrpos($originalPath, '/')) !== false) {
245+
$path = substr($originalPath, 0, $pos+1).$path;
246+
} else {
247+
$path = '/'.$path;
248+
}
249+
/* replace '/./' or '/foo/../' with '/' */
250+
$re = ['#(/\./)#', '#/(?!\.\.)[^/]+/\.\./#'];
251+
for( $n=1; $n>0; $path=preg_replace( $re, '/', $path, -1, $n ) ) {
252+
// keep looping until all is resolved
253+
}
254+
}
234255
$uri = $uri
235-
->withPath(array_key_exists('path', $parsedLocation) ? $parsedLocation['path'] : '')
256+
->withPath($path)
236257
->withQuery(array_key_exists('query', $parsedLocation) ? $parsedLocation['query'] : '')
237258
->withFragment(array_key_exists('fragment', $parsedLocation) ? $parsedLocation['fragment'] : '')
238259
;
@@ -247,6 +268,8 @@ private function createUri(ResponseInterface $redirectResponse, RequestInterface
247268

248269
if (array_key_exists('port', $parsedLocation)) {
249270
$uri = $uri->withPort($parsedLocation['port']);
271+
} elseif (array_key_exists('host', $parsedLocation)) {
272+
$uri = $uri->withPort(null);
250273
}
251274

252275
return $uri;

tests/Plugin/RedirectPluginTest.php

+19-3
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,26 @@ function () {}
2626
)->wait();
2727
}
2828

29+
public function provideRedirections(): array
30+
{
31+
return [
32+
'no path on target' => ["https://example.com/path?query=value", "https://example.com?query=value", "https://example.com?query=value"],
33+
'root path on target' => ["https://example.com/path?query=value", "https://example.com/?query=value", "https://example.com/?query=value"],
34+
'redirect to query' => ["https://example.com", "https://example.com?query=value", "https://example.com?query=value"],
35+
'redirect to different domain without port' => ["https://example.com:8000", "https://foo.com?query=value", "https://foo.com?query=value"],
36+
'network-path redirect, preserve scheme' => ["https://example.com:8000", "//foo.com/path?query=value", "https://foo.com/path?query=value"],
37+
'absolute-path redirect, preserve host' => ["https://example.com:8000", "/path?query=value", "https://example.com:8000/path?query=value"],
38+
'relative-path redirect, append' => ["https://example.com:8000/path/", "sub/path?query=value", "https://example.com:8000/path/sub/path?query=value"],
39+
'relative-path on non-folder' => ["https://example.com:8000/path/foo", "sub/path?query=value", "https://example.com:8000/path/sub/path?query=value"],
40+
'relative-path moving up' => ["https://example.com:8000/path/", "../other?query=value", "https://example.com:8000/other?query=value"],
41+
'relative-path with ./' => ["https://example.com:8000/path/", "./other?query=value", "https://example.com:8000/path/other?query=value"],
42+
'relative-path with //' => ["https://example.com:8000/path/", "other//sub?query=value", "https://example.com:8000/path/other//sub?query=value"],
43+
'relative-path redirect with only query' => ["https://example.com:8000/path", "?query=value", "https://example.com:8000/path?query=value"],
44+
];
45+
}
46+
2947
/**
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"]
48+
* @dataProvider provideRedirections
3349
*/
3450
public function testTargetUriMappingFromLocationHeader(string $originalUri, string $locationUri, string $targetUri): void
3551
{

0 commit comments

Comments
 (0)