Skip to content

Commit b61d827

Browse files
committed
Replaced URI parsing using Guzzle lib with local parsing.
1 parent 1444ccc commit b61d827

File tree

3 files changed

+157
-24
lines changed

3 files changed

+157
-24
lines changed

composer.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
"require": {
1616
"php": "^8.1",
1717
"ext-mbstring": "*",
18-
"guzzlehttp/psr7": "^2.0",
1918
"phpunit/phpunit": "^9.5 | ^10.0 | ^11.0 | ^12",
2019
"symfony/css-selector": ">=4.4.24 <8.0"
2120
},

src/Util/Uri.php

Lines changed: 99 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace Codeception\Util;
66

7-
use GuzzleHttp\Psr7\Uri as Psr7Uri;
87
use InvalidArgumentException;
98

109
use function dirname;
@@ -28,13 +27,13 @@ class Uri
2827
*/
2928
public static function mergeUrls(string $baseUri, string $uri): string
3029
{
31-
$base = new Psr7Uri($baseUri);
30+
$base = self::parseUrl($baseUri);
3231
$parts = parse_url($uri);
3332

3433
//If the relative URL does not parse, attempt to parse the entire URL.
3534
//PHP Known bug ( https://bugs.php.net/bug.php?id=70942 )
3635
if ($parts === false) {
37-
$parts = parse_url($base . $uri);
36+
$parts = parse_url($baseUri . $uri);
3837
}
3938

4039
if ($parts === false) {
@@ -47,14 +46,14 @@ public static function mergeUrls(string $baseUri, string $uri): string
4746
}
4847

4948
if (isset($parts['host'])) {
50-
$base = $base->withHost($parts['host']);
51-
$base = $base->withPath('');
52-
$base = $base->withQuery('');
53-
$base = $base->withFragment('');
49+
$base['host'] = $parts['host'];
50+
$base['path'] = '';
51+
$base['query'] = '';
52+
$base['fragment'] = '';
5453
}
5554
if (isset($parts['path'])) {
5655
$path = $parts['path'];
57-
$basePath = $base->getPath();
56+
$basePath = $base['path'] ?? '';
5857
if ((!str_starts_with($path, '/')) && !empty($path)) {
5958
if ($basePath !== '') {
6059
// if it ends with a slash, relative paths are below it
@@ -69,36 +68,38 @@ public static function mergeUrls(string $baseUri, string $uri): string
6968
$path = '/' . ltrim($path, '/');
7069
}
7170
}
72-
$base = $base->withPath($path);
73-
$base = $base->withQuery('');
74-
$base = $base->withFragment('');
71+
$base['path'] = $path;
72+
$base['query'] = '';
73+
$base['fragment'] = '';
7574
}
7675
if (isset($parts['query'])) {
77-
$base = $base->withQuery($parts['query']);
78-
$base = $base->withFragment('');
76+
$base['query'] = $parts['query'];
77+
$base['fragment'] = '';
7978
}
8079
if (isset($parts['fragment'])) {
81-
$base = $base->withFragment($parts['fragment']);
80+
$base['fragment'] = $parts['fragment'];
8281
}
8382

84-
return (string)$base;
83+
return self::phpUrlPartsToString($base);
8584
}
8685

8786
/**
8887
* Retrieve /path?query#fragment part of URL
8988
*/
9089
public static function retrieveUri(string $url): string
9190
{
92-
$uri = new Psr7Uri($url);
93-
return (string)(new Psr7Uri())
94-
->withPath($uri->getPath())
95-
->withQuery($uri->getQuery())
96-
->withFragment($uri->getFragment());
91+
$urlParts = self::parseUrl($url);
92+
93+
return self::phpUrlPartsToString([
94+
'path' => $urlParts['path'],
95+
'query' => $urlParts['query'] ?? '',
96+
'fragment' => $urlParts['fragment'] ?? '',
97+
]);
9798
}
9899

99100
public static function retrieveHost(string $url): string
100101
{
101-
$urlParts = parse_url($url);
102+
$urlParts = self::parseUrl($url);
102103
if (!isset($urlParts['host']) || !isset($urlParts['scheme'])) {
103104
throw new InvalidArgumentException("Wrong URL passes, host and scheme not set");
104105
}
@@ -111,13 +112,88 @@ public static function retrieveHost(string $url): string
111112

112113
public static function appendPath(string $url, string $path): string
113114
{
114-
$uri = new Psr7Uri($url);
115-
$cutUrl = (string)$uri->withQuery('')->withFragment('');
115+
$cutUrl = parse_url($url);
116+
unset(
117+
$cutUrl['query'],
118+
$cutUrl['fragment'],
119+
);
120+
$cutUrl = self::phpUrlPartsToString($cutUrl);
116121

117122
if ($path === '' || $path[0] === '#') {
118123
return $cutUrl . $path;
119124
}
120125

121126
return rtrim($cutUrl, '/') . '/' . ltrim($path, '/');
122127
}
128+
129+
/**
130+
* @return array{
131+
* scheme?: string,
132+
* host?: string,
133+
* port?: int,
134+
* user?: string,
135+
* pass?: string,
136+
* query?: string,
137+
* path?: string,
138+
* fragment?: string,
139+
* }
140+
*/
141+
public static function parseUrl(string $uri): array
142+
{
143+
$parts = parse_url($uri);
144+
145+
if ($parts === false) {
146+
throw new InvalidArgumentException("Invalid URI {$uri}");
147+
}
148+
149+
return $parts;
150+
}
151+
152+
/**
153+
* @param array{
154+
* scheme?: string,
155+
* host?: string,
156+
* port?: int,
157+
* user?: string,
158+
* pass?: string,
159+
* query?: string,
160+
* path?: string,
161+
* fragment?: string,
162+
* } $urlParts
163+
*/
164+
public static function phpUrlPartsToString(array $urlParts): string
165+
{
166+
$uri = '';
167+
$scheme = $urlParts['scheme'] ?? '';
168+
$host = $urlParts['host'] ?? '';
169+
$path = $urlParts['path'] ?? '';
170+
171+
if ($scheme !== '') {
172+
$uri .= $scheme . ':';
173+
}
174+
175+
if ($host !== '' || $scheme === 'file') {
176+
$uri .= '//' . $host;
177+
178+
if (($urlParts['port'] ?? '') !== '') {
179+
$uri .= ':' . $urlParts['port'];
180+
}
181+
}
182+
183+
if ($host !== '' && $path !== '' && $path[0] !== '/') {
184+
$path = '/' . $path;
185+
}
186+
187+
$uri .= $path;
188+
189+
if (($urlParts['query'] ?? '') !== '') {
190+
$uri .= '?' . $urlParts['query'];
191+
}
192+
193+
if (($urlParts['fragment'] ?? '') !== '') {
194+
$uri .= '#' . $urlParts['fragment'];
195+
}
196+
197+
return $uri;
198+
}
123199
}

tests/Util/UriTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Tests\Codeception\Util;
66

77
use Codeception\Util\Uri;
8+
use PHPUnit\Framework\Attributes\DataProvider;
89
use PHPUnit\Framework\TestCase;
910

1011
class UriTest extends TestCase
@@ -125,4 +126,61 @@ public function testMergeUrlsWhenBaseUriEndsWithSlashButUriPathHasNoLeadingSlash
125126
Uri::mergeUrls('https://codeception.com/', 'test')
126127
);
127128
}
129+
130+
#[DataProvider('phpUrlPartsProvider')]
131+
public function testPhpUrlPartsToString(array $parts, string $expected): void
132+
{
133+
$this->assertSame($expected, Uri::phpUrlPartsToString($parts));
134+
}
135+
136+
public static function phpUrlPartsProvider(): iterable
137+
{
138+
yield [
139+
[
140+
'path' => '/test',
141+
],
142+
'/test'
143+
];
144+
145+
yield [
146+
[
147+
'query' => 'test=a',
148+
],
149+
'?test=a'
150+
];
151+
152+
yield [
153+
[
154+
'scheme' => 'https',
155+
'host' => 'codeception.com',
156+
'path' => '/test',
157+
],
158+
'https://codeception.com/test'
159+
];
160+
161+
yield [
162+
[
163+
'scheme' => 'https',
164+
'host' => 'codeception.com',
165+
],
166+
'https://codeception.com'
167+
];
168+
169+
yield [
170+
[
171+
'scheme' => 'https',
172+
'host' => 'codeception.com',
173+
],
174+
'https://codeception.com'
175+
];
176+
177+
yield [
178+
[
179+
'scheme' => 'https',
180+
'host' => 'codeception.com',
181+
'port' => 8080,
182+
],
183+
'https://codeception.com:8080'
184+
];
185+
}
128186
}

0 commit comments

Comments
 (0)