@@ -514,29 +514,37 @@ private static function resolveUrl(array $url, ?array $base, array $queryDefault
514
514
*/
515
515
private static function parseUrl (string $ url , array $ query = [], array $ allowedSchemes = ['http ' => 80 , 'https ' => 443 ]): array
516
516
{
517
- if (false === $ parts = parse_url ($ url )) {
518
- if ('/ ' !== ($ url [0 ] ?? '' ) || false === $ parts = parse_url ($ url .'# ' )) {
519
- throw new InvalidArgumentException (sprintf ('Malformed URL "%s". ' , $ url ));
520
- }
521
- unset($ parts ['fragment ' ]);
517
+ $ tail = '' ;
518
+
519
+ if (false === $ parts = parse_url (\strlen ($ url ) !== strcspn ($ url , '?# ' ) ? $ url : $ url .$ tail = '# ' )) {
520
+ throw new InvalidArgumentException (sprintf ('Malformed URL "%s". ' , $ url ));
522
521
}
523
522
524
523
if ($ query ) {
525
524
$ parts ['query ' ] = self ::mergeQueryString ($ parts ['query ' ] ?? null , $ query , true );
526
525
}
527
526
527
+ $ scheme = $ parts ['scheme ' ] ?? null ;
528
+ $ host = $ parts ['host ' ] ?? null ;
529
+
530
+ if (!$ scheme && $ host && !str_starts_with ($ url , '// ' )) {
531
+ $ parts = parse_url (':/ ' .$ url .$ tail );
532
+ $ parts ['path ' ] = substr ($ parts ['path ' ], 2 );
533
+ $ scheme = $ host = null ;
534
+ }
535
+
528
536
$ port = $ parts ['port ' ] ?? 0 ;
529
537
530
- if (null !== $ scheme = $ parts [ ' scheme ' ] ?? null ) {
538
+ if (null !== $ scheme ) {
531
539
if (!isset ($ allowedSchemes [$ scheme = strtolower ($ scheme )])) {
532
- throw new InvalidArgumentException (sprintf ('Unsupported scheme in "%s". ' , $ url ));
540
+ throw new InvalidArgumentException (sprintf ('Unsupported scheme in "%s": "%s" expected . ' , $ url, implode ( ' " or " ' , array_keys ( $ allowedSchemes )) ));
533
541
}
534
542
535
543
$ port = $ allowedSchemes [$ scheme ] === $ port ? 0 : $ port ;
536
544
$ scheme .= ': ' ;
537
545
}
538
546
539
- if (null !== $ host = $ parts [ ' host ' ] ?? null ) {
547
+ if (null !== $ host ) {
540
548
if (!\defined ('INTL_IDNA_VARIANT_UTS46 ' ) && preg_match ('/[\x80-\xFF]/ ' , $ host )) {
541
549
throw new InvalidArgumentException (sprintf ('Unsupported IDN "%s", try enabling the "intl" PHP extension or running "composer require symfony/polyfill-intl-idn". ' , $ host ));
542
550
}
@@ -564,7 +572,7 @@ private static function parseUrl(string $url, array $query = [], array $allowedS
564
572
'authority ' => null !== $ host ? '// ' .(isset ($ parts ['user ' ]) ? $ parts ['user ' ].(isset ($ parts ['pass ' ]) ? ': ' .$ parts ['pass ' ] : '' ).'@ ' : '' ).$ host : null ,
565
573
'path ' => isset ($ parts ['path ' ][0 ]) ? $ parts ['path ' ] : null ,
566
574
'query ' => isset ($ parts ['query ' ]) ? '? ' .$ parts ['query ' ] : null ,
567
- 'fragment ' => isset ($ parts ['fragment ' ]) ? '# ' .$ parts ['fragment ' ] : null ,
575
+ 'fragment ' => isset ($ parts ['fragment ' ]) && ! $ tail ? '# ' .$ parts ['fragment ' ] : null ,
568
576
];
569
577
}
570
578
0 commit comments