diff --git a/CHANGELOG.md b/CHANGELOG.md index b73dd9e1..d6d17af1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ All Notable changes to `League\Uri` will be documented in this file ### Added -- None +- `UriInfo::isCrossOrigin` method ### Fixed diff --git a/composer.json b/composer.json index 2059a5f4..4d361cec 100644 --- a/composer.json +++ b/composer.json @@ -76,7 +76,7 @@ "phpcs": "php-cs-fixer fix -v --diff --dry-run --allow-risky=yes --ansi", "phpcs:fix": "php-cs-fixer fix -vvv --allow-risky=yes --ansi", "phpstan": "phpstan analyse -l max -c phpstan.neon src --ansi --memory-limit=256M", - "phpunit": "phpunit --coverage-text", + "phpunit": "XDEBUG_MODE=coverage phpunit --coverage-text", "test": [ "@phpunit", "@phpstan", diff --git a/docs/uri/6.0/info.md b/docs/uri/6.0/info.md index e5c7f5b2..34116ef5 100644 --- a/docs/uri/6.0/info.md +++ b/docs/uri/6.0/info.md @@ -78,7 +78,7 @@ UriInfo::getOrigin(Http::createFromString('file:///usr/bin/php')); //returns nul UriInfo::getOrigin(Uri::createFromString('data:text/plain,Bonjour%20le%20monde%21')); //returns null ~~~ -
+ Because the origin property does not exists in the RFC3986 specification this additional steps is implemented: @@ -92,3 +92,25 @@ use League\Uri\UriInfo; UriInfo::getOrigin(Http::createFromString('/path/to/endpoint')); //returns null ~~~ + +## UriInfo::isCrossOrigin + +This public static method tells whether the given URI object represents different origins. +According to [RFC9110](https://www.rfc-editor.org/rfc/rfc9110#section-4.3.1) The "origin" for a given URI is the triple of scheme, host, and port +after normalizing the scheme and host to lowercase and normalizing the port to remove any leading +zeros. + +~~~php + 21, 'http' => 80, 'https' => 443, 'ws' => 80, 'wss' => 443]; /** * @codeCoverageIgnore @@ -88,9 +88,7 @@ private static function normalize($uri) $pairs = null === $query ? [] : explode('&', $query); sort($pairs, SORT_REGULAR); - $replace = static function (array $matches): string { - return rawurldecode($matches[0]); - }; + $replace = static fn (array $matches): string => rawurldecode($matches[0]); $retval = preg_replace_callback(self::REGEXP_ENCODED_CHARS, $replace, [$path, implode('&', $pairs), $fragment]); if (null !== $retval) { @@ -195,12 +193,23 @@ public static function getOrigin($uri): ?string $scheme = $uri->getScheme(); } - if (in_array($scheme, self::WHATWG_SPECIAL_SCHEMES, true)) { - $null = self::emptyComponentValue($uri); - - return (string) $uri->withFragment($null)->withQuery($null)->withPath('')->withUserInfo($null, null); + if (null === $scheme || !array_key_exists($scheme, self::WHATWG_SPECIAL_SCHEMES)) { + return null; } - return null; + $null = self::emptyComponentValue($uri); + + return (string) $uri->withFragment($null)->withQuery($null)->withPath('')->withUserInfo($null); + } + + /** + * @param Psr7UriInterface|UriInterface $uri + * @param Psr7UriInterface|UriInterface $base_uri + */ + public static function isCrossOrigin($uri, $base_uri): bool + { + return null === ($uriString = self::getOrigin($uri)) + || null === ($baseUriString = self::getOrigin($base_uri)) + || $uriString !== $baseUriString; } } diff --git a/src/UriInfoTest.php b/src/UriInfoTest.php index 5b990643..68d40e80 100644 --- a/src/UriInfoTest.php +++ b/src/UriInfoTest.php @@ -215,4 +215,35 @@ public function getOriginProvider(): array ], ]; } + + /** + * @dataProvider getCrossOriginExamples + */ + public function testIsCrossOrigin(string $original, string $modified, bool $expected): void + { + self::assertSame($expected, UriInfo::isCrossOrigin(Uri::createFromString($original), Http::createFromString($modified))); + } + + /** + * @return array