diff --git a/src/Uri.php b/src/Uri.php index dc21e97..7ab71f7 100644 --- a/src/Uri.php +++ b/src/Uri.php @@ -27,6 +27,8 @@ * Import functions */ use function getservbyname; +use function ltrim; +use function strncmp; /** * Uniform Resource Identifier @@ -351,6 +353,25 @@ public function __toString() $path = $this->getPath(); if ($path !== '') { + // https://github.com/sunrise-php/uri/issues/31 + // https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 + // + // If a URI contains an authority component, + // then the path component must either be empty + // or begin with a slash ("/") character. + if ($authority !== '' && strncmp($path, '/', 1) !== 0) { + $path = '/' . $path; + } + + // https://github.com/sunrise-php/uri/issues/31 + // https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 + // + // If a URI does not contain an authority component, + // then the path cannot begin with two slash characters ("//"). + if ($authority === '' && strncmp($path, '//', 2) === 0) { + $path = '/' . ltrim($path, '/'); + } + $uri .= $path; } diff --git a/tests/UriTest.php b/tests/UriTest.php index 4d54ef7..f81fc9d 100644 --- a/tests/UriTest.php +++ b/tests/UriTest.php @@ -567,6 +567,21 @@ public function testToString() $this->assertSame(self::TEST_URI, (string) $uri); } + public function testToStringIssue31() + { + $uri = new Uri('//username@hostname'); + $uri = $uri->withPath('pathname'); + $this->assertSame('//username@hostname/pathname', $uri->__toString()); + + $uri = new Uri('scheme:'); + $uri = $uri->withPath('//pathname'); + $this->assertSame('scheme:/pathname', $uri->__toString()); + + $uri = new Uri('scheme:'); + $uri = $uri->withPath('///pathname'); + $this->assertSame('scheme:/pathname', $uri->__toString()); + } + // Normalizes... public function testNormalizeScheme()