Skip to content

Commit

Permalink
Improve internal codebase (#138)
Browse files Browse the repository at this point in the history
* Improve internal codebase
* Deprecate usage of PSR-7 in API
* Adding IPv6 Converter and usage in uri-interfaces and uri-components
  • Loading branch information
nyamsprod authored Jun 26, 2024
1 parent 6bfb02d commit 2b3649c
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 23 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ All Notable changes to `League\Uri\Components` will be documented in this file

- `UrlSearchParams::uniqueKeyCount`
- `Modifier::getIdnUriString`
- `Modifier::hostToIpv6Compressed`
- `Modifier::hostToIpv6Expanded`

### Fixed

- None
- Adding `SensitiveParameter` attribute in the `UserInfo` and the `Authority` class.
- Remove Usage of PSR-7 `UriInterface` in `UrlSearchParams` class

### Deprecated

- None
- Usage of PSR-7 `UriFactoryInterface` is deprecated in `Modifier` class

### Removed

Expand Down
19 changes: 10 additions & 9 deletions Components/Authority.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use League\Uri\Exceptions\SyntaxError;
use League\Uri\UriString;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use SensitiveParameter;
use Stringable;

final class Authority extends Component implements AuthorityInterface
Expand All @@ -32,7 +33,7 @@ final class Authority extends Component implements AuthorityInterface
public function __construct(
Stringable|string|null $host,
Stringable|string|int|null $port = null,
Stringable|string|null $userInfo = null
#[SensitiveParameter] Stringable|string|null $userInfo = null
) {
$this->host = !$host instanceof HostInterface ? Host::new($host) : $host;
$this->port = !$port instanceof PortInterface ? Port::new($port) : $port;
Expand All @@ -45,7 +46,7 @@ public function __construct(
/**
* @throws SyntaxError If the component contains invalid HostInterface part.
*/
public static function new(Stringable|string|null $value = null): self
public static function new(#[SensitiveParameter] Stringable|string|null $value = null): self
{
$components = UriString::parseAuthority(self::filterComponent($value));

Expand All @@ -62,7 +63,7 @@ public static function new(Stringable|string|null $value = null): self
/**
* Create a new instance from a URI object.
*/
public static function fromUri(Stringable|string $uri): self
public static function fromUri(#[SensitiveParameter] Stringable|string $uri): self
{
$uri = self::filterUri($uri);
$authority = $uri->getAuthority();
Expand All @@ -87,7 +88,7 @@ public static function fromUri(Stringable|string $uri): self
* port? : ?int
* } $components
*/
public static function fromComponents(array $components): self
public static function fromComponents(#[SensitiveParameter] array $components): self
{
$components += ['user' => null, 'pass' => null, 'host' => null, 'port' => null];

Expand All @@ -104,7 +105,7 @@ public function value(): ?string
}

private static function getAuthorityValue(
UserInfoInterface $userInfo,
#[SensitiveParameter] UserInfoInterface $userInfo,
HostInterface $host,
PortInterface $port
): ?string {
Expand Down Expand Up @@ -180,7 +181,7 @@ public function withPort(Stringable|string|int|null $port): AuthorityInterface
};
}

public function withUserInfo(Stringable|string|null $user, Stringable|string|null $password = null): AuthorityInterface
public function withUserInfo(Stringable|string|null $user, #[SensitiveParameter] Stringable|string|null $password = null): AuthorityInterface
{
$userInfo = new UserInfo($user, $password);

Expand All @@ -200,7 +201,7 @@ public function withUserInfo(Stringable|string|null $user, Stringable|string|nul
*
* Create a new instance from a URI object.
*/
public static function createFromUri(UriInterface|Psr7UriInterface $uri): self
public static function createFromUri(#[SensitiveParameter] UriInterface|Psr7UriInterface $uri): self
{
return self::fromUri($uri);
}
Expand All @@ -215,7 +216,7 @@ public static function createFromUri(UriInterface|Psr7UriInterface $uri): self
*
* Returns a new instance from a string or a stringable object.
*/
public static function createFromString(Stringable|string $authority): self
public static function createFromString(#[SensitiveParameter] Stringable|string $authority): self
{
return self::new($authority);
}
Expand Down Expand Up @@ -255,7 +256,7 @@ public static function createFromNull(): self
* port? : ?int
* } $components
*/
public static function createFromComponents(array $components): self
public static function createFromComponents(#[SensitiveParameter] array $components): self
{
return self::fromComponents($components);
}
Expand Down
1 change: 1 addition & 0 deletions Components/Host.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use League\Uri\Idna\Converter as IdnConverter;
use League\Uri\IPv4\Converter as IPv4Converter;
use League\Uri\IPv4Normalizer;
use League\Uri\IPv6\Converter;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use Stringable;

Expand Down
2 changes: 0 additions & 2 deletions Components/URLSearchParams.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
use League\Uri\KeyValuePair\Converter;
use League\Uri\QueryString;
use League\Uri\Uri;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use Stringable;

use function array_is_list;
Expand Down Expand Up @@ -202,7 +201,6 @@ public static function fromAssociative(object|array $associative): self
public static function fromUri(Stringable|string $uri): self
{
$query = match (true) {
$uri instanceof Psr7UriInterface,
$uri instanceof UriInterface => $uri->getQuery(),
default => Uri::new($uri)->getQuery(),
};
Expand Down
35 changes: 25 additions & 10 deletions Components/UserInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function __construct(
/**
* Create a new instance from a URI object.
*/
public static function fromUri(Stringable|string $uri): self
public static function fromUri(#[SensitiveParameter] Stringable|string $uri): self
{
$uri = self::filterUri($uri);
$component = $uri->getUserInfo();
Expand All @@ -64,7 +64,7 @@ public static function fromUri(Stringable|string $uri): self
/**
* Create a new instance from an Authority object.
*/
public static function fromAuthority(Stringable|string|null $authority): self
public static function fromAuthority(#[SensitiveParameter] Stringable|string|null $authority): self
{
return match (true) {
$authority instanceof AuthorityInterface => self::new($authority->getUserInfo()),
Expand All @@ -80,7 +80,7 @@ public static function fromAuthority(Stringable|string|null $authority): self
*
* @param array{user? : ?string, pass? : ?string} $components
*/
public static function fromComponents(array $components): self
public static function fromComponents(#[SensitiveParameter] array $components): self
{
$components += ['user' => null, 'pass' => null];

Expand All @@ -93,7 +93,7 @@ public static function fromComponents(array $components): self
/**
* Creates a new instance from an encoded string.
*/
public static function new(Stringable|string|null $value = null): self
public static function new(#[SensitiveParameter] Stringable|string|null $value = null): self
{
if ($value instanceof UriComponentInterface) {
$value = $value->value();
Expand All @@ -113,9 +113,8 @@ public static function new(Stringable|string|null $value = null): self
public function value(): ?string
{
return match (true) {
null === $this->username => null,
null === $this->password => Encoder::encodeUser($this->username),
default => Encoder::encodeUser($this->username).':'.Encoder::encodePassword($this->password),
null === $this->password => $this->getUsername(),
default => $this->getUsername().':'.$this->getPassword(),
};
}

Expand All @@ -134,6 +133,22 @@ public function getPass(): ?string
return $this->password;
}

public function getUsername(): ?string
{
return match ($this->username) {
null => null,
default => Encoder::encodeUser($this->username)
};
}

public function getPassword(): ?string
{
return match ($this->password) {
null => null,
default => Encoder::encodePassword($this->password)
};
}

/**
* @return array{user: ?string, pass: ?string}
*/
Expand Down Expand Up @@ -176,7 +191,7 @@ public function withPass(#[SensitiveParameter] Stringable|string|null $password)
*
* Create a new instance from a URI object.
*/
public static function createFromUri(Psr7UriInterface|UriInterface $uri): self
public static function createFromUri(#[SensitiveParameter] Psr7UriInterface|UriInterface $uri): self
{
return self::fromUri($uri);
}
Expand All @@ -191,7 +206,7 @@ public static function createFromUri(Psr7UriInterface|UriInterface $uri): self
*
* Create a new instance from an Authority object.
*/
public static function createFromAuthority(AuthorityInterface|Stringable|string $authority): self
public static function createFromAuthority(#[SensitiveParameter] AuthorityInterface|Stringable|string $authority): self
{
return self::fromAuthority($authority);
}
Expand All @@ -206,7 +221,7 @@ public static function createFromAuthority(AuthorityInterface|Stringable|string
*
* Creates a new instance from an encoded string.
*/
public static function createFromString(Stringable|string $userInfo): self
public static function createFromString(#[SensitiveParameter] Stringable|string $userInfo): self
{
return self::new($userInfo);
}
Expand Down
21 changes: 21 additions & 0 deletions Modifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use League\Uri\Exceptions\SyntaxError;
use League\Uri\Idna\Converter as IdnConverter;
use League\Uri\IPv4\Converter as IPv4Converter;
use League\Uri\IPv6\Converter;
use League\Uri\KeyValuePair\Converter as KeyValuePairConverter;
use Psr\Http\Message\UriFactoryInterface;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
Expand All @@ -43,6 +44,12 @@ final public function __construct(protected readonly Psr7UriInterface|UriInterfa
{
}

/**
* @param Stringable|string $uri
* @param UriFactoryInterface|null $uriFactory Deprecated, will be removed in the next major release
*
* @return static
*/
public static function from(Stringable|string $uri, ?UriFactoryInterface $uriFactory = null): static
{
return new static(match (true) {
Expand Down Expand Up @@ -445,6 +452,20 @@ public function hostToHexadecimal(): static
};
}

public function hostToIpv6Compressed(): static
{
return new static($this->uri->withHost(
Converter::compress($this->uri->getHost())
));
}

public function hostToIpv6Expanded(): static
{
return new static($this->uri->withHost(
Converter::expand($this->uri->getHost())
));
}

/**
* Prepend a label or a host to the current URI host.
*
Expand Down
39 changes: 39 additions & 0 deletions ModifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -859,4 +859,43 @@ public static function idnUriProvider(): iterable
'input' => "http://bébé.be:80?q=toto le héros",
];
}

#[DataProvider('ipv6NormalizationUriProvider')]
public function testItCanExpandOrCompressTheHost(
string $inputUri,
string $compressedUri,
string $expandedUri,
): void {
$uri = Modifier::from(Http::new($inputUri));

self::assertSame($compressedUri, $uri->hostToIpv6Compressed()->getUriString());
self::assertSame($expandedUri, $uri->hostToIpv6Expanded()->getUriString());
}

public static function ipv6NormalizationUriProvider(): iterable
{
yield 'no change happen with a non IP host' => [
'inputUri' => 'https://example.com/foo/bar',
'compressedUri' => 'https://example.com/foo/bar',
'expandedUri' => 'https://example.com/foo/bar',
];

yield 'no change happen with a IPv4 host' => [
'inputUri' => 'https://127.0.0.1/foo/bar',
'compressedUri' => 'https://127.0.0.1/foo/bar',
'expandedUri' => 'https://127.0.0.1/foo/bar',
];

yield 'IPv6 gets expanded if needed' => [
'inputUri' => 'https://[fe80::a%25en1]/foo/bar',
'compressedUri' => 'https://[fe80::a%25en1]/foo/bar',
'expandedUri' => 'https://[fe80:0000:0000:0000:0000:0000:0000:000a%25en1]/foo/bar',
];

yield 'IPv6 gets compressed if needed' => [
'inputUri' => 'https://[0000:0000:0000:0000:0000:0000:0000:0001]/foo/bar',
'compressedUri' => 'https://[::1]/foo/bar',
'expandedUri' => 'https://[0000:0000:0000:0000:0000:0000:0000:0001]/foo/bar',
];
}
}

0 comments on commit 2b3649c

Please sign in to comment.