* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\Uri; use InvalidArgumentException; use League\Uri\Exceptions\SyntaxError; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use Psr\Http\Message\UriInterface; use function serialize; use function unserialize; #[CoversClass(Http::class)] #[Group('http')] final class HttpTest extends TestCase { public function createUri(string $uri): UriInterface { return (new HttpFactory())->createUri($uri); } public function testDefaultConstructor(): void { self::assertSame('', (string) Http::new()); } public function testJson(): void { self::assertSame( '"http:\/\/example.com"', json_encode(Http::new('http://example.com')) ); } public function testInvalidPort(): void { self::expectException(InvalidArgumentException::class); Http::new('https://example.com:-1'); } public function testThrowInvalidArgumentExceptionOnIllegalCharacters(): void { self::expectException(InvalidArgumentException::class); Http::new('https://example.com')->withFragment("\0"); } public function testPortModification(): void { $uri = Http::new('http://login:pass@secure.example.com:443/test/query.php?kingkong=toto#doc3'); self::assertSame(443, $uri->getPort()); self::assertSame($uri, $uri->withPort(443)); self::assertNotEquals($uri, $uri->withPort(81)); self::assertSame( 'http://login:pass@secure.example.com/test/query.php?kingkong=toto#doc3', (string) $uri->withPort(null) ); } public function testUserInfoModification(): void { $uri = Http::new('http://login:pass@secure.example.com:443/test/query.php?kingkong=toto#doc3'); self::assertSame('login:pass', $uri->getUserInfo()); self::assertSame($uri, $uri->withUserInfo('login', 'pass')); self::assertNotEquals($uri, $uri->withUserInfo('login')); self::assertSame( 'http://secure.example.com:443/test/query.php?kingkong=toto#doc3', (string) $uri->withUserInfo('') ); } public function testCreateFromComponents(): void { $uri = '//0:0@0/0?0#0'; self::assertEquals( Http::fromComponents(parse_url($uri)), Http::new($uri) ); } public function testCreateFromBaseUri(): void { self::assertEquals( Http::new('http://0:0@0/0?0#0'), Http::parse('0?0#0', 'http://0:0@0/') ); } public function testCreateFromUri(): void { self::assertEquals( Http::new('http://0:0@0/0?0#0'), Http::new(Uri::new('http://0:0@0/0?0#0')) ); self::assertEquals( Http::new('http://0:0@0/0?0#0'), Http::new(Http::new('http://0:0@0/0?0#0')) ); } #[DataProvider('validUrlProvider')] public function testCreateFromString(string $expected, string $uri): void { self::assertSame($expected, (string) Http::new($uri)); } public static function validUrlProvider(): array { return [ 'with default port' => [ 'http://example.com/foo/bar?foo=bar#content', 'http://example.com:80/foo/bar?foo=bar#content', ], 'without scheme' => [ '//example.com', '//example.com', ], 'without scheme but with port' => [ '//example.com:80', '//example.com:80', ], 'with user info' => [ 'http://login:pass@example.com/', 'http://login:pass@example.com/', ], ]; } #[DataProvider('invalidUrlProvider')] public function testIsValid(string $uri): void { self::expectException(SyntaxError::class); Http::new($uri); } public static function invalidUrlProvider(): array { return [ ['http:example.com'], ['https:/example.com'], ['http://user@:80'], ['//user@:80'], ['http:///path'], ['http:path'], ]; } #[DataProvider('portProvider')] public function testValidPort(string $uri, ?int $port): void { self::assertSame($port, Http::new($uri)->getPort()); } public static function portProvider(): array { return [ ['http://www.example.com:443/', 443], ['http://www.example.com:80/', null], ['http://www.example.com', null], ['//www.example.com:80/', 80], ]; } #[TestWith(['data:go'])] #[TestWith(['to://to'])] public function testPathIsInvalid(string $path): void { self::expectException(SyntaxError::class); Http::new()->withPath($path); } #[DataProvider('invalidURI')] public function testCreateFromInvalidUrlKO(string $uri): void { self::expectException(SyntaxError::class); Http::new($uri); } public static function invalidURI(): array { return [ ['http://user@:80'], ['http://example.com:655356'], ['http://example.com:-1'], ['///path?query'], ]; } public function testModificationFailedWithEmptyAuthority(): void { $http = Http::new('http://example.com/path') ->withScheme('') ->withHost('') ->withPath('//toto'); self::assertSame('/.//toto', (string) $http); } public function testItStripMultipleLeadingSlashOnGetPath(): void { $uri = Http::new('https://example.com///miscillaneous.tld'); self::assertSame('https://example.com///miscillaneous.tld', (string) $uri); self::assertSame('/miscillaneous.tld', $uri->getPath()); $modifiedUri = $uri->withPath('///foobar'); self::assertSame('https://example.com///foobar', (string) $modifiedUri); self::assertSame('/foobar', $modifiedUri->getPath()); self::assertSame('//example.com///foobar', (string) $modifiedUri->withScheme('')); self::assertSame( '/.///foobar', (string) $modifiedUri ->withScheme('') ->withHost('') ); } public function testItPreservesMultipleLeadingSlashesOnMutation(): void { $uri = Http::new('https://www.example.com///google.com'); self::assertSame('https://www.example.com///google.com', (string) $uri); self::assertSame('/google.com', $uri->getPath()); $modifiedUri = $uri->withPath('/google.com'); self::assertSame('https://www.example.com/google.com', (string) $modifiedUri); self::assertSame('/google.com', $modifiedUri->getPath()); $modifiedUri2 = $uri->withPath('///google.com'); self::assertSame('https://www.example.com///google.com', (string) $modifiedUri2); self::assertSame('/google.com', $modifiedUri2->getPath()); } public function testICanBeInstantiateFromRFC6750(): void { $template = 'https://example.com/hotels/{hotel}/bookings/{booking}'; $params = ['booking' => '42', 'hotel' => 'Rest & Relax']; self::assertSame( '/hotels/Rest%20%26%20Relax/bookings/42', Http::fromTemplate($template, $params)->getPath() ); } #[Test] public function it_can_be_serialized_by_php(): void { $uri = Http::new('https://user:pass@example.com:81/path?query#fragment'); /** @var Http $newUri */ $newUri = unserialize(serialize($uri)); self::assertEquals($uri, $newUri); } }