Skip to content

Commit 729a95e

Browse files
committed
:octocat: move parseUrl() to QueryUtil::parseUrl()
1 parent 3f4fb02 commit 729a95e

File tree

4 files changed

+65
-62
lines changed

4 files changed

+65
-62
lines changed

src/QueryUtil.php

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010

1111
namespace chillerlan\HTTP\Utils;
1212

13-
use function array_merge, call_user_func_array, explode, implode, is_array, is_bool, is_iterable,
14-
is_numeric, is_string, rawurldecode, sort, str_replace, trim, uksort;
13+
use function array_map, array_merge, call_user_func_array, explode, implode, is_array, is_bool, is_iterable,
14+
is_numeric, is_string, parse_url, preg_match, preg_replace_callback, rawurldecode, sort, str_replace, trim, uksort,
15+
urlencode;
16+
1517
use const PHP_QUERY_RFC1738, PHP_QUERY_RFC3986, SORT_STRING;
1618

1719
/**
@@ -166,7 +168,7 @@ public static function build(array $params, int $encoding = null, string $delimi
166168
* Merges additional query parameters into an existing query string
167169
*/
168170
public static function merge(string $uri, array $query):string{
169-
$parsedquery = self::parse(parseUrl($uri)['query'] ?? '');
171+
$parsedquery = self::parse(self::parseUrl($uri)['query'] ?? '');
170172
$requestURI = explode('?', $uri)[0];
171173
$params = array_merge($parsedquery, $query);
172174

@@ -225,4 +227,39 @@ public static function parse(string $querystring, int $urlEncoding = null):array
225227
return $result;
226228
}
227229

230+
/**
231+
* UTF-8 aware \parse_url() replacement.
232+
*
233+
* The internal function produces broken output for non ASCII domain names
234+
* (IDN) when used with locales other than "C".
235+
*
236+
* On the other hand, cURL understands IDN correctly only when UTF-8 locale
237+
* is configured ("C.UTF-8", "en_US.UTF-8", etc.).
238+
*
239+
* @see https://bugs.php.net/bug.php?id=52923
240+
* @see https://www.php.net/manual/en/function.parse-url.php#114817
241+
* @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING
242+
*
243+
* @link https://github.com/guzzle/psr7/blob/c0dcda9f54d145bd4d062a6d15f54931a67732f9/src/Uri.php#L89-L130
244+
*/
245+
public static function parseUrl(string $url):?array{
246+
// If IPv6
247+
$prefix = '';
248+
/** @noinspection RegExpRedundantEscape */
249+
if(preg_match('%^(.*://\[[0-9:a-f]+\])(.*?)$%', $url, $matches)){
250+
/** @var array{0:string, 1:string, 2:string} $matches */
251+
$prefix = $matches[1];
252+
$url = $matches[2];
253+
}
254+
255+
$encodedUrl = preg_replace_callback('%[^:/@?&=#]+%usD', fn($matches) => urlencode($matches[0]), $url);
256+
$result = parse_url($prefix.$encodedUrl);
257+
258+
if($result === false){
259+
return null;
260+
}
261+
262+
return array_map('urldecode', $result);
263+
}
264+
228265
}

src/message_helpers.php

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -374,38 +374,3 @@ function uriWithQueryValue(UriInterface $uri, string $key, string $value = null)
374374

375375
return $uri->withQuery(implode('&', $result));
376376
}
377-
378-
/**
379-
* UTF-8 aware \parse_url() replacement.
380-
*
381-
* The internal function produces broken output for non ASCII domain names
382-
* (IDN) when used with locales other than "C".
383-
*
384-
* On the other hand, cURL understands IDN correctly only when UTF-8 locale
385-
* is configured ("C.UTF-8", "en_US.UTF-8", etc.).
386-
*
387-
* @see https://bugs.php.net/bug.php?id=52923
388-
* @see https://www.php.net/manual/en/function.parse-url.php#114817
389-
* @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING
390-
*
391-
* @link https://github.com/guzzle/psr7/blob/c0dcda9f54d145bd4d062a6d15f54931a67732f9/src/Uri.php#L89-L130
392-
*/
393-
function parseUrl(string $url):?array{
394-
// If IPv6
395-
$prefix = '';
396-
/** @noinspection RegExpRedundantEscape */
397-
if(preg_match('%^(.*://\[[0-9:a-f]+\])(.*?)$%', $url, $matches)){
398-
/** @var array{0:string, 1:string, 2:string} $matches */
399-
$prefix = $matches[1];
400-
$url = $matches[2];
401-
}
402-
403-
$encodedUrl = preg_replace_callback('%[^:/@?&=#]+%usD', fn($matches) => urlencode($matches[0]), $url);
404-
$result = parse_url($prefix.$encodedUrl);
405-
406-
if($result === false){
407-
return null;
408-
}
409-
410-
return array_map('urldecode', $result);
411-
}

tests/MessageHelpersTest.php

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
use function chillerlan\HTTP\Utils\{
1616
decompress_content, get_json, get_xml, getMimetypeFromExtension, getMimetypeFromFilename, message_to_string,
17-
parseUrl, r_rawurlencode, uriIsAbsolute, uriIsAbsolutePathReference, uriIsDefaultPort, uriIsNetworkPathReference,
17+
r_rawurlencode, uriIsAbsolute, uriIsAbsolutePathReference, uriIsDefaultPort, uriIsNetworkPathReference,
1818
uriIsRelativePathReference, uriWithoutQueryValue, uriWithQueryValue
1919
};
2020

@@ -262,29 +262,6 @@ public function testUriIsDefaultPort():void{
262262

263263
}
264264

265-
public function parseUrlProvider():array{
266-
return [
267-
['http://', null],
268-
['https://яндекAс.рф', [
269-
'scheme' => 'https',
270-
'host' => 'яндекAс.рф'
271-
]],
272-
['http://[2a00:f48:1008::212:183:10]:56?foo=bar', [
273-
'scheme' => 'http',
274-
'host' => '[2a00:f48:1008::212:183:10]',
275-
'port' => '56',
276-
'query' => 'foo=bar',
277-
]]
278-
];
279-
}
280-
281-
/**
282-
* @dataProvider parseUrlProvider
283-
*/
284-
public function testParseUrl($url, $expected):void{
285-
$this::assertSame($expected, parseUrl($url));
286-
}
287-
288265
public function testGetMimetype():void{
289266
$this::assertSame('application/json', getMimetypeFromExtension('json'));
290267
$this::assertSame('application/json', getMimetypeFromFilename('/path/to/some/file.json'));

tests/QueryUtilTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,28 @@ public function testBuildBooleans():void{
180180
public function testParseDoesTrimQuestionMark():void{
181181
$this::assertSame(QueryUtil::parse('?q=a'), ['q' => 'a']);
182182
}
183+
184+
public function parseUrlProvider():array{
185+
return [
186+
['http://', null],
187+
['https://яндекAс.рф', [
188+
'scheme' => 'https',
189+
'host' => 'яндекAс.рф'
190+
]],
191+
['http://[2a00:f48:1008::212:183:10]:56?foo=bar', [
192+
'scheme' => 'http',
193+
'host' => '[2a00:f48:1008::212:183:10]',
194+
'port' => '56',
195+
'query' => 'foo=bar',
196+
]]
197+
];
198+
}
199+
200+
/**
201+
* @dataProvider parseUrlProvider
202+
*/
203+
public function testParseUrl($url, $expected):void{
204+
$this::assertSame($expected, QueryUtil::parseUrl($url));
205+
}
206+
183207
}

0 commit comments

Comments
 (0)