From 3de0d91b109adf34e029fd4f1e8ee688963fdbdf Mon Sep 17 00:00:00 2001 From: ignace nyamagana butera Date: Mon, 30 Dec 2024 21:59:23 +0100 Subject: [PATCH] Adding Modifier::whatWgHost --- components/CHANGELOG.md | 1 + components/Modifier.php | 26 ++++++++++++++++++++++++++ components/ModifierTest.php | 12 ++++++++++++ docs/components/7.0/modifiers.md | 14 ++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/components/CHANGELOG.md b/components/CHANGELOG.md index 9f9d0923..33e8bdb9 100644 --- a/components/CHANGELOG.md +++ b/components/CHANGELOG.md @@ -10,6 +10,7 @@ All Notable changes to `League\Uri\Components` will be documented in this file - `URLSearchParams::when` conditional method to ease component building logic. - `Modifier::prependQueryParameters` returns a modifier with prepend query paramters - `Modifier::when` conditional method to ease component building logic. +- `Modifier::whatWgHost` returns the host as normalized by the WHATWG algorithm - `Modifier::with*` method from the underlying `Uri` object are proxy to improve DX. - `Query::decoded` the string representation of the component decoded. - `URLSearchParams::decoded` the string representation of the component decoded. diff --git a/components/Modifier.php b/components/Modifier.php index 3578fd8c..4e85eb12 100644 --- a/components/Modifier.php +++ b/components/Modifier.php @@ -26,6 +26,7 @@ use League\Uri\Contracts\PathInterface; use League\Uri\Contracts\UriAccess; use League\Uri\Contracts\UriInterface; +use League\Uri\Exceptions\MissingFeature; use League\Uri\Exceptions\SyntaxError; use League\Uri\Idna\Converter as IdnaConverter; use League\Uri\IPv4\Converter as IPv4Converter; @@ -36,6 +37,7 @@ use Stringable; use function array_map; +use function filter_var; use function get_object_vars; use function is_bool; use function ltrim; @@ -44,6 +46,9 @@ use function str_ends_with; use function str_starts_with; +use const FILTER_FLAG_IPV4; +use const FILTER_VALIDATE_IP; + /** * @method static withScheme(Stringable|string|null $scheme) returns a new instance with the specified scheme. * @method static withUserInfo(Stringable|string|null $user, Stringable|string|null $password = null) returns a new instance with the specified user info. @@ -597,6 +602,27 @@ public function replaceLabel(int $offset, Stringable|string|null $label): static )); } + public function whatWgHost(): static + { + $host = $this->uri->getHost(); + try { + $converted = IPv4Converter::fromEnvironment()->toDecimal($host); + } catch (MissingFeature) { + $converted = null; + } + + if (false === filter_var($converted, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + $converted = IPv6Converter::compress($host); + } + + return match (true) { + null !== $converted => new static($this->uri->withHost($converted)), + '' === $host, + $this->uri instanceof UriInterface => $this, + default => new static($this->uri->withHost((string) Uri::fromComponents(['host' => $host])->getHost())), + }; + } + /********************************* * Path modifier methods *********************************/ diff --git a/components/ModifierTest.php b/components/ModifierTest.php index b2eb581e..fb8e8f03 100644 --- a/components/ModifierTest.php +++ b/components/ModifierTest.php @@ -883,4 +883,16 @@ public function it_will_remove_empty_pairs_fix_issue_133(): void self::assertNull($removeEmptyPairs('https://a.b/c?=d')); self::assertNull($removeEmptyPairs('https://a.b/c?=')); } + + #[Test] + public function it_will_convert_uri_host_following_whatwg_rules(): void + { + self::assertSame( + '192.168.2.13', + Modifier::from(Http::new('https://0:0@0xc0a8020d/0?0#0')) + ->whatWgHost() + ->getUri() + ->getHost() + ); + } } diff --git a/docs/components/7.0/modifiers.md b/docs/components/7.0/modifiers.md index 01854e79..a0daa673 100644 --- a/docs/components/7.0/modifiers.md +++ b/docs/components/7.0/modifiers.md @@ -145,6 +145,7 @@ echo Modifier::from('http://bébé.be')
  • replaceLabel
  • removeLabels
  • sliceLabels
  • +
  • whatWgHost
  • @@ -604,6 +605,19 @@ echo Modifier::from($uri)->sliceLabels(1, 1)->getUriString();

    This modifier supports negative offset

    +### Modifier::whatWgHost + +Returns the host as formatted following WHATWG host formatting + +

    available since version 7.6.0

    + +~~~php +$uri = "https://0:0@0:0"; +echo Modifier::from($uri)->whatWgHost()->getUriString(); +//display "https://0:0@0.0.0.0:0" +~~~ + +In case of IPv4 and/or IPv6 some extra normalization are applied. ## Path modifiers