From 814e341a0b41307bc556b2ce23c48f6145e2a339 Mon Sep 17 00:00:00 2001 From: ignace nyamagana butera Date: Fri, 27 Dec 2024 23:19:36 +0100 Subject: [PATCH] Simplify URI codebase --- docs/interfaces/7.0/uri-parser-builder.md | 60 ++++++++--------------- interfaces/CHANGELOG.md | 3 +- interfaces/UriString.php | 37 +++++++++----- interfaces/UriStringTest.php | 2 +- uri/Uri.php | 4 +- 5 files changed, 51 insertions(+), 55 deletions(-) diff --git a/docs/interfaces/7.0/uri-parser-builder.md b/docs/interfaces/7.0/uri-parser-builder.md index af691ef0..28025d88 100644 --- a/docs/interfaces/7.0/uri-parser-builder.md +++ b/docs/interfaces/7.0/uri-parser-builder.md @@ -15,9 +15,11 @@ The class act as a drop-in replacement for PHP's `parse_url` feature. ## URI parsing ~~~php -UriString::resolve(string $uri, ?string $baseUri = null): array UriString::parse(string $uri): array +UriString::normalize(string $uri): string UriString::parseAuthority(string $autority): array +UriString::normalizeAuthority(string $autority): string +UriString::resolve(string $uri, ?string $baseUri = null): string ~~~ The parser is: @@ -74,17 +76,31 @@ a base URI which must be absolute, the URI will then be resolved using the base ```php $components = UriString::resolve('"/foo", "https://example.com"); +//returns "https://example.com/foo" +``` + +It is possible to normalize a URI against the RFC3986 rules using the `UriString::normalize` method. +The method expects a string and will return the same array as `UriString::parse` but each component will +have been normalized. + +```php +use League\Uri\UriString; + +$parsed = UriString::parse("https://EXAMPLE.COM/foo/../bar"); //returns the following array //array( -// 'scheme' => 'https', +// 'scheme' => 'http', // 'user' => null, // 'pass' => null, -// 'host' => 'example.com'', +// 'host' => 'EXAMPLE.COM', // 'port' => null, -// 'path' => '/foo', +// 'path' => '/foo/../bar', // 'query' => null, // 'fragment' => null, //); + +$normalized = UriString::normalize("https://EXAMPLE.COM/foo/../bar"); +//returns "https://example.com/bar" ``` ## URI Building @@ -119,39 +135,3 @@ echo UriString::build($components); //displays http://hello:world@foo.com?@bar.c The `build` method provides similar functionality to the `http_build_url()` function from v1.x of the [`pecl_http`](https://pecl.php.net/package/pecl_http) PECL extension.

The class also exposes a UriString::buildAuthority you can use to build an authority from its hash representation.

- -## URI Normalization - -It is possible to normalize a URI against the RFC3986 rules using the `UriString::normalize` method. -The method expects a string and will return the same array as `UriString::parse` but each component will -have been normalized. - -```php -use League\Uri\UriString; - -$parsed = UriString::parse("https://EXAMPLE.COM/foo/../bar"); -//returns the following array -//array( -// 'scheme' => 'http', -// 'user' => null, -// 'pass' => null, -// 'host' => 'EXAMPLE.COM', -// 'port' => null, -// 'path' => '/foo/../bar', -// 'query' => null, -// 'fragment' => null, -//); - -$normalized = UriString::normalize("https://EXAMPLE.COM/foo/../bar"); -//returns the following array -//array( -// 'scheme' => 'http', -// 'user' => null, -// 'pass' => null, -// 'host' => 'example.com', -// 'port' => null, -// 'path' => '/bar', -// 'query' => null, -// 'fragment' => null, -//); -``` diff --git a/interfaces/CHANGELOG.md b/interfaces/CHANGELOG.md index 0953748f..4c405f6d 100644 --- a/interfaces/CHANGELOG.md +++ b/interfaces/CHANGELOG.md @@ -17,7 +17,8 @@ All Notable changes to `League\Uri\Interfaces` will be documented in this file - `League\Uri\IPv6\Converter::isIpv6` - `UriString::resolve` - `UriString::removeDotSegments` -- `UriString::normalize` +- `UriString::parseAndNormalize` +- `UriString::parseAuthorityAndNormalize` ### Fixed diff --git a/interfaces/UriString.php b/interfaces/UriString.php index 9b047faa..59cb8571 100644 --- a/interfaces/UriString.php +++ b/interfaces/UriString.php @@ -33,6 +33,7 @@ use function rawurldecode; use function sprintf; use function strpos; +use function strtolower; use function substr; use const FILTER_FLAG_IPV6; @@ -275,10 +276,8 @@ public static function buildAuthority(array $components): ?string * Parses and normalizes the URI following RFC3986 destructive and non-destructive constraints. * * @throws SyntaxError if the URI is not parsable - * - * @return ComponentMap */ - public static function normalize(Stringable|string $uri): array + public static function normalize(Stringable|string $uri): string { $components = UriString::parse($uri); if (null !== $components['scheme']) { @@ -299,13 +298,31 @@ public static function normalize(Stringable|string $uri): array $path = '/'; } - $components['path'] = (string) $path; + $components['path'] = $path; $components['query'] = Encoder::decodeUnreservedCharacters($components['query']); $components['fragment'] = Encoder::decodeUnreservedCharacters($components['fragment']); $components['user'] = Encoder::decodeUnreservedCharacters($components['user']); $components['pass'] = Encoder::decodeUnreservedCharacters($components['pass']); - return $components; + return self::build($components); + } + + /** + * Parses and normalizes the URI following RFC3986 destructive and non-destructive constraints. + * + * @throws SyntaxError if the URI is not parsable + */ + public static function normalizeAuthority(Stringable|string $authority): string + { + $components = UriString::parseAuthority($authority); + if (null !== $components['host']) { + $components['host'] = IdnaConverter::toUnicode((string)IPv6Converter::compress($components['host']))->domain(); + } + + $components['user'] = Encoder::decodeUnreservedCharacters($components['user']); + $components['pass'] = Encoder::decodeUnreservedCharacters($components['pass']); + + return (string) self::buildAuthority($components); } /** @@ -320,10 +337,8 @@ public static function normalize(Stringable|string $uri): array * @see https://www.rfc-editor.org/rfc/rfc3986.html#section-5 * * @throws SyntaxError if the BaseUri is not absolute or in absence of a BaseUri if the uri is not absolute - * - * @return ComponentMap */ - public static function resolve(Stringable|string $uri, Stringable|string|null $baseUri = null): array + public static function resolve(Stringable|string $uri, Stringable|string|null $baseUri = null): string { $uri = self::parse($uri); $baseUri = null !== $baseUri ? self::parse($baseUri) : $uri; @@ -334,14 +349,14 @@ public static function resolve(Stringable|string $uri, Stringable|string|null $b if (null !== $uri['scheme'] && '' !== $uri['scheme']) { $uri['path'] = self::removeDotSegments($uri['path']); - return $uri; + return UriString::build($uri); } if (null !== self::buildAuthority($uri)) { $uri['scheme'] = $baseUri['scheme']; $uri['path'] = self::removeDotSegments($uri['path']); - return $uri; + return UriString::build($uri); } [$path, $query] = self::resolvePathAndQuery($uri, $baseUri); @@ -354,7 +369,7 @@ public static function resolve(Stringable|string $uri, Stringable|string|null $b $baseUri['query'] = $query; $baseUri['fragment'] = $uri['fragment']; - return $baseUri; + return UriString::build($baseUri); } /** diff --git a/interfaces/UriStringTest.php b/interfaces/UriStringTest.php index 1825d537..3d0ec46a 100644 --- a/interfaces/UriStringTest.php +++ b/interfaces/UriStringTest.php @@ -980,7 +980,7 @@ public static function buildUriProvider(): array #[DataProvider('resolveProvider')] public function testCreateResolve(string $baseUri, string $uri, string $expected): void { - self::assertSame($expected, UriString::build(UriString::resolve($uri, $baseUri))); + self::assertSame($expected, UriString::resolve($uri, $baseUri)); } public static function resolveProvider(): array diff --git a/uri/Uri.php b/uri/Uri.php index 9ccb65fc..4a4cc9cb 100644 --- a/uri/Uri.php +++ b/uri/Uri.php @@ -1670,7 +1670,7 @@ public function equals(UriInterface|Stringable|string $uri, bool $excludeFragmen */ public function normalize(): UriInterface { - return self::fromComponents(UriString::normalize($this->toString())); + return self::new(UriString::normalize($this->toString())); } /** @@ -1686,7 +1686,7 @@ public function normalize(): UriInterface */ public function resolve(Stringable|string $uri): UriInterface { - return self::fromComponents(UriString::resolve($uri, $this->toString())); + return self::new(UriString::resolve($uri, $this->toString())); } /**