fix: truncate URI Template prefix modifier by character, not byte
Operator::inject() applied the ":N" prefix modifier with the byte-oriented substr(), splitting multibyte UTF-8 characters in half and producing invalid percent-encoded output (e.g. the euro sign truncated to its first byte only). RFC 6570 Section 2.4.1 defines the prefix length as a count of characters, so use mb_substr() with an explicit UTF-8 encoding instead. ext-mbstring is already a hard dependency of this package.
This commit is contained in:
1 parent
2c92ab421c
commit
c0b6c4bc5f
2 files changed
+18
-2
No files matched your search
@@ -261,6 +261,20 @@ final class UriTemplateTest extends TestCase
|
||||
self::assertSame($expectedUri, $uriTemplate->expandToUrlOrFail($variables)->toAsciiString());
|
||||
}
|
||||
|
||||
public function testPrefixModifierTruncatesByCharacterNotByte(): void
|
||||
{
|
||||
// RFC 6570 Section 2.4.1: the prefix length counts characters, not octets, so a
|
||||
// multibyte character must never be split. The euro sign and the musical G-clef
|
||||
// are 3 and 4 bytes in UTF-8, respectively, but each is a single character.
|
||||
$uriTemplate = new UriTemplate('{?currency:1}{clef:1}');
|
||||
$variables = [
|
||||
'currency' => "\u{20AC}uro",
|
||||
'clef' => "\u{1D11E}stave",
|
||||
];
|
||||
|
||||
self::assertSame('?currency=%E2%82%AC%F0%9D%84%9E', $uriTemplate->expand($variables)->toString());
|
||||
}
|
||||
|
||||
public function testDisallowNestedArrayExpansion(): void
|
||||
{
|
||||
$template = 'http://example.com{?query,data*,foo*}';
|
||||
|
||||
Reference in new issue
Block a user