Skip to content

Commit 100e8f3

Browse files
committed
ext/uri: Preserve empty query and fragment in URL builders
Keep empty components distinct from null so serialization retains the trailing question mark or hashmark.
1 parent 3bec7e4 commit 100e8f3

3 files changed

Lines changed: 92 additions & 2 deletions

File tree

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
Test Uri\WhatWg\UrlBuilder::setFragment() - success - empty string
3+
--FILE--
4+
<?php
5+
6+
$builder = new Uri\WhatWg\UrlBuilder();
7+
$builder->setScheme("https");
8+
$builder->setHost("example.com");
9+
$builder->setFragment("foo");
10+
$builder->setFragment("");
11+
$url = $builder->build();
12+
13+
var_dump($url->toAsciiString());
14+
var_dump($url);
15+
var_dump($url->equals(new Uri\WhatWg\Url($url->toAsciiString())));
16+
17+
?>
18+
--EXPECTF--
19+
string(21) "https://example.com/#"
20+
object(Uri\WhatWg\Url)#%d (%d) {
21+
["scheme"]=>
22+
string(5) "https"
23+
["username"]=>
24+
NULL
25+
["password"]=>
26+
NULL
27+
["host"]=>
28+
string(11) "example.com"
29+
["port"]=>
30+
NULL
31+
["path"]=>
32+
string(1) "/"
33+
["query"]=>
34+
NULL
35+
["fragment"]=>
36+
string(0) ""
37+
}
38+
bool(true)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
Test Uri\WhatWg\UrlBuilder::setQuery() - success - empty string
3+
--FILE--
4+
<?php
5+
6+
$builder = new Uri\WhatWg\UrlBuilder();
7+
$builder->setScheme("https");
8+
$builder->setHost("example.com");
9+
$builder->setQuery("foo");
10+
$builder->setQuery("");
11+
$url = $builder->build();
12+
13+
var_dump($url->toAsciiString());
14+
var_dump($url);
15+
var_dump($url->equals(new Uri\WhatWg\Url($url->toAsciiString())));
16+
17+
?>
18+
--EXPECTF--
19+
string(21) "https://example.com/?"
20+
object(Uri\WhatWg\Url)#%d (%d) {
21+
["scheme"]=>
22+
string(5) "https"
23+
["username"]=>
24+
NULL
25+
["password"]=>
26+
NULL
27+
["host"]=>
28+
string(11) "example.com"
29+
["port"]=>
30+
NULL
31+
["path"]=>
32+
string(1) "/"
33+
["query"]=>
34+
string(0) ""
35+
["fragment"]=>
36+
NULL
37+
}
38+
bool(true)

ext/uri/uri_parser_whatwg.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,13 +1068,27 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh
10681068
goto failure;
10691069
}
10701070

1071-
result = php_uri_parser_whatwg_query_write(lexbor_url, query, NULL);
1071+
if (Z_TYPE_P(query) == IS_STRING && Z_STRLEN_P(query) == 0) {
1072+
/* The URL API setter treats an empty string as removal. The builder
1073+
* distinguishes an empty component from an absent one. */
1074+
lexbor_str_destroy(&lexbor_url->query, lexbor_url->mraw, false);
1075+
lexbor_str_init(&lexbor_url->query, lexbor_url->mraw, 1);
1076+
} else {
1077+
result = php_uri_parser_whatwg_query_write(lexbor_url, query, NULL);
1078+
}
10721079
php_uri_parser_whatwg_build_errors(&errors);
10731080
if (result == FAILURE) {
10741081
goto failure;
10751082
}
10761083

1077-
result = php_uri_parser_whatwg_fragment_write(lexbor_url, fragment, NULL);
1084+
if (Z_TYPE_P(fragment) == IS_STRING && Z_STRLEN_P(fragment) == 0) {
1085+
/* The URL API setter treats an empty string as removal. The builder
1086+
* distinguishes an empty component from an absent one. */
1087+
lexbor_str_destroy(&lexbor_url->fragment, lexbor_url->mraw, false);
1088+
lexbor_str_init(&lexbor_url->fragment, lexbor_url->mraw, 1);
1089+
} else {
1090+
result = php_uri_parser_whatwg_fragment_write(lexbor_url, fragment, NULL);
1091+
}
10781092
php_uri_parser_whatwg_build_errors(&errors);
10791093
if (result == FAILURE) {
10801094
goto failure;

0 commit comments

Comments
 (0)