diff --git a/composer.json b/composer.json index e64c99a9..86351d58 100644 --- a/composer.json +++ b/composer.json @@ -60,7 +60,6 @@ "src/functions/marshal_headers_from_sapi.php", "src/functions/marshal_method_from_sapi.php", "src/functions/marshal_protocol_version_from_sapi.php", - "src/functions/marshal_uri_from_sapi.php", "src/functions/normalize_server.php", "src/functions/normalize_uploaded_files.php", "src/functions/parse_cookie_header.php" diff --git a/docs/book/v3/api.md b/docs/book/v3/api.md index e255b3f3..f49ef106 100644 --- a/docs/book/v3/api.md +++ b/docs/book/v3/api.md @@ -153,9 +153,6 @@ and even the `Cookie` header. These include: when under Apache) - `Laminas\Diactoros\marshalProtocolVersionFromSapi(array $server) : string` - `Laminas\Diactoros\marshalMethodFromSapi(array $server) : string`. -- `Laminas\Diactoros\marshalUriFromSapi(array $server, array $headers) : Uri`. - Please note: **this function is deprecated as of version 2.11.1**, and no longer used in `ServerRequestFactory::fromGlobals()`. - Use `ServerRequestFactory::fromGlobals()` instead. - `Laminas\Diactoros\marshalHeadersFromSapi(array $server) : array` - `Laminas\Diactoros\parseCookieHeader(string $header) : array` - `Laminas\Diactoros\createUploadedFile(array $spec) : UploadedFile` (creates the diff --git a/docs/book/v3/migration.md b/docs/book/v3/migration.md index f54c3077..047f6004 100644 --- a/docs/book/v3/migration.md +++ b/docs/book/v3/migration.md @@ -12,3 +12,9 @@ With the update in PHP 8.0 to usage of opaque resource types for all GD resource As such, we have removed the feature entirely. If you need to stream an image, the recommendation is to use the functionality in the GD extension to write the image to a temporary file (e.g., `php://temp`), and then to pass that to `Laminas\Diactoros\Stream`. + +### marshalUriFromSapi function + +The `Laminas\Diactoros\marshalUriFromSapi()` function was deprecated starting in version 2.11.0, and now removed. +The functionality that was present in it was moved to `Laminas\Diactoros\UriFactory::createFromSapi()`. +If you were using the function previously, use this static method instead. diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 90d56ad1..97aaecc5 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -305,52 +305,6 @@ - - - $default - $host - $https - - - static function ($host) { - static function (string $name, array $headers, $default = null) { - - - - $host - $host - $host - $host - $port - $requestUri - - - - $headers[$header] - $host - - - $host - $iisUrlRewritten - $origPathInfo - $unencodedUrl - - - array - string - - - - - - $defaults - $origPathInfo - $unencodedUrl - - - - - diff --git a/psalm.xml.dist b/psalm.xml.dist index 9b1e8dbe..28ed3276 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -22,12 +22,6 @@ - - - - - - @@ -44,12 +38,6 @@ - - - - - - diff --git a/src/functions/marshal_uri_from_sapi.php b/src/functions/marshal_uri_from_sapi.php deleted file mode 100644 index 186d6d9a..00000000 --- a/src/functions/marshal_uri_from_sapi.php +++ /dev/null @@ -1,233 +0,0 @@ -withScheme($scheme); - - // Set the host - [$host, $port] = $marshalHostAndPort($headers, $server); - if (! empty($host)) { - $uri = $uri->withHost($host); - if (! empty($port)) { - $uri = $uri->withPort($port); - } - } - - // URI path - $path = $marshalRequestPath($server); - - // Strip query string - $path = explode('?', $path, 2)[0]; - - // URI query - $query = ''; - if (isset($server['QUERY_STRING'])) { - $query = ltrim($server['QUERY_STRING'], '?'); - } - - // URI fragment - $fragment = ''; - if (str_contains($path, '#')) { - $parts = explode('#', $path, 2); - assert(count($parts) >= 2); - [$path, $fragment] = $parts; - } - - return $uri - ->withPath($path) - ->withFragment($fragment) - ->withQuery($query); -} diff --git a/test/ServerRequestFactoryTest.php b/test/ServerRequestFactoryTest.php index 2bdddfe5..83259cb8 100644 --- a/test/ServerRequestFactoryTest.php +++ b/test/ServerRequestFactoryTest.php @@ -9,21 +9,15 @@ use Laminas\Diactoros\ServerRequestFilter\DoNotFilter; use Laminas\Diactoros\ServerRequestFilter\FilterServerRequestInterface; use Laminas\Diactoros\UploadedFile; -use Laminas\Diactoros\Uri; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; use UnexpectedValueException; -use function array_shift; use function Laminas\Diactoros\marshalHeadersFromSapi; use function Laminas\Diactoros\marshalProtocolVersionFromSapi; -use function Laminas\Diactoros\marshalUriFromSapi; use function Laminas\Diactoros\normalizeServer; use function Laminas\Diactoros\normalizeUploadedFiles; -use function sprintf; -use function str_contains; use function str_replace; -use function strtolower; final class ServerRequestFactoryTest extends TestCase { @@ -95,296 +89,6 @@ public function testMarshalsVariablesPrefixedByApacheFromServerArray(): void $this->assertEquals($expected, marshalHeadersFromSapi($server)); } - public function testMarshalRequestUriUsesIISUnencodedUrlValueIfPresentAndUrlWasRewritten(): void - { - $server = [ - 'IIS_WasUrlRewritten' => '1', - 'UNENCODED_URL' => '/foo/bar', - ]; - - $uri = marshalUriFromSapi($server, []); - - $this->assertSame($server['UNENCODED_URL'], $uri->getPath()); - } - - public function testMarshalRequestUriStripsSchemeHostAndPortInformationWhenPresent(): void - { - $server = [ - 'REQUEST_URI' => 'http://example.com:8000/foo/bar', - ]; - - $uri = marshalUriFromSapi($server, []); - - $this->assertSame('/foo/bar', $uri->getPath()); - } - - public function testMarshalRequestUriUsesOrigPathInfoIfPresent(): void - { - $server = [ - 'ORIG_PATH_INFO' => '/foo/bar', - ]; - - $uri = marshalUriFromSapi($server, []); - - $this->assertSame('/foo/bar', $uri->getPath()); - } - - public function testMarshalRequestUriFallsBackToRoot(): void - { - $server = []; - - $uri = marshalUriFromSapi($server, []); - - $this->assertSame('/', $uri->getPath()); - } - - public function testMarshalHostAndPortUsesHostHeaderWhenPresent(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('http://example.com/')); - $request = $request->withMethod('GET'); - $request = $request->withHeader('Host', 'example.com'); - - $uri = marshalUriFromSapi([], $request->getHeaders()); - - $this->assertSame('example.com', $uri->getHost()); - $this->assertNull($uri->getPort()); - } - - public function testMarshalHostAndPortWillDetectPortInHostHeaderWhenPresent(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('http://example.com:8000/')); - $request = $request->withMethod('GET'); - $request = $request->withHeader('Host', 'example.com:8000'); - - $uri = marshalUriFromSapi([], $request->getHeaders()); - - $this->assertSame('example.com', $uri->getHost()); - $this->assertSame(8000, $uri->getPort()); - } - - public function testMarshalHostAndPortReturnsEmptyValuesIfNoHostHeaderAndNoServerName(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri()); - - $uri = marshalUriFromSapi([], $request->getHeaders()); - - $this->assertSame('', $uri->getHost()); - $this->assertNull($uri->getPort()); - } - - public function testMarshalHostAndPortReturnsServerNameForHostWhenPresent(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('http://example.com/')); - - $server = [ - 'SERVER_NAME' => 'example.com', - ]; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertSame('example.com', $uri->getHost()); - $this->assertNull($uri->getPort()); - } - - public function testMarshalHostAndPortReturnsServerPortForPortWhenPresentWithServerName(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri()); - - $server = [ - 'SERVER_NAME' => 'example.com', - 'SERVER_PORT' => 8000, - ]; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertSame('example.com', $uri->getHost()); - $this->assertSame(8000, $uri->getPort()); - } - - public function testMarshalHostAndPortReturnsServerNameForHostIfServerAddrPresentButHostIsNotIpv6Address(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('http://example.com/')); - - $server = [ - 'SERVER_ADDR' => '127.0.0.1', - 'SERVER_NAME' => 'example.com', - ]; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertSame('example.com', $uri->getHost()); - } - - public function testMarshalHostAndPortReturnsServerAddrForHostIfPresentAndHostIsIpv6Address(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri()); - - $server = [ - 'SERVER_ADDR' => 'FE80::0202:B3FF:FE1E:8329', - 'SERVER_NAME' => '[FE80::0202:B3FF:FE1E:8329]', - 'SERVER_PORT' => 8000, - ]; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertSame(strtolower('[FE80::0202:B3FF:FE1E:8329]'), $uri->getHost()); - $this->assertSame(8000, $uri->getPort()); - } - - public function testMarshalHostAndPortWillDetectPortInIpv6StyleHost(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri()); - - $server = [ - 'SERVER_ADDR' => 'FE80::0202:B3FF:FE1E:8329', - 'SERVER_NAME' => '[FE80::0202:B3FF:FE1E:8329:80]', - ]; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertSame(strtolower('[FE80::0202:B3FF:FE1E:8329]'), $uri->getHost()); - $this->assertNull($uri->getPort()); - } - - /** @return non-empty-array */ - public function httpsParamProvider(): array - { - return [ - 'lowercase' => ['https'], - 'uppercase' => ['HTTPS'], - ]; - } - - /** - * @dataProvider httpsParamProvider - * @param non-empty-string $param - */ - public function testMarshalUriDetectsHttpsSchemeFromServerValue(string $param): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('http://example.com/')); - $request = $request->withHeader('Host', 'example.com'); - - $server = [ - $param => 'on', - ]; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertInstanceOf(Uri::class, $uri); - $this->assertSame('https', $uri->getScheme()); - } - - /** @return iterable */ - public function httpsDisableParamProvider(): iterable - { - foreach ($this->httpsParamProvider() as $key => $data) { - $param = array_shift($data); - foreach (['lowercase-off', 'uppercase-off'] as $type) { - $key = sprintf('%s-%s', $key, $type); - $value = str_contains($type, 'lowercase') ? 'off' : 'OFF'; - yield $key => [$param, $value]; - } - } - } - - /** - * @dataProvider httpsDisableParamProvider - * @param non-empty-string $param - * @param 'off'|'OFF' $value - */ - public function testMarshalUriUsesHttpSchemeIfHttpsServerValueEqualsOff(string $param, string $value): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('http://example.com/')); - $request = $request->withHeader('Host', 'example.com'); - - $server = [ - $param => $value, - ]; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertInstanceOf(Uri::class, $uri); - $this->assertSame('http', $uri->getScheme()); - } - - /** - * @dataProvider httpsParamProvider - * @param non-empty-string $xForwardedProto - */ - public function testMarshalUriDetectsHttpsSchemeFromXForwardedProtoValue(string $xForwardedProto): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('http://example.com/')); - $request = $request->withHeader('Host', 'example.com'); - $request = $request->withHeader('X-Forwarded-Proto', $xForwardedProto); - - $server = []; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertInstanceOf(Uri::class, $uri); - $this->assertSame('https', $uri->getScheme()); - } - - public function testMarshalUriStripsQueryStringFromRequestUri(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('http://example.com/')); - $request = $request->withHeader('Host', 'example.com'); - - $server = [ - 'REQUEST_URI' => '/foo/bar?foo=bar', - ]; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertInstanceOf(Uri::class, $uri); - $this->assertSame('/foo/bar', $uri->getPath()); - } - - public function testMarshalUriInjectsQueryStringFromServer(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('http://example.com/')); - $request = $request->withHeader('Host', 'example.com'); - - $server = [ - 'REQUEST_URI' => '/foo/bar?foo=bar', - 'QUERY_STRING' => 'bar=baz', - ]; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertInstanceOf(Uri::class, $uri); - $this->assertSame('bar=baz', $uri->getQuery()); - } - - public function testMarshalUriInjectsFragmentFromServer(): void - { - $request = new ServerRequest(); - $request = $request->withUri(new Uri('http://example.com/')); - $request = $request->withHeader('Host', 'example.com'); - - $server = [ - 'REQUEST_URI' => '/foo/bar#foo', - ]; - - $uri = marshalUriFromSapi($server, $request->getHeaders()); - - $this->assertInstanceOf(Uri::class, $uri); - $this->assertSame('foo', $uri->getFragment()); - } - public function testCanCreateServerRequestViaFromGlobalsMethod(): void { $server = [ @@ -603,19 +307,6 @@ public function marshalProtocolVersionProvider(): array ]; } - public function testMarshalRequestUriPrefersRequestUriServerParamWhenXOriginalUrlButNoXRewriteUrlPresent(): void - { - $headers = [ - 'X-Original-URL' => '/hijack-attempt', - ]; - $server = [ - 'REQUEST_URI' => 'https://example.com/requested/path', - ]; - - $uri = marshalUriFromSapi($server, $headers); - $this->assertSame('/requested/path', $uri->getPath()); - } - public function testServerRequestFactoryHasAWritableEmptyBody(): void { $factory = new ServerRequestFactory(); diff --git a/test/UriFactoryTest.php b/test/UriFactoryTest.php index 786686e1..1701ca74 100644 --- a/test/UriFactoryTest.php +++ b/test/UriFactoryTest.php @@ -253,4 +253,17 @@ public function testMarshalUriInjectsFragmentFromServer(): void $this->assertInstanceOf(Uri::class, $uri); $this->assertSame('foo', $uri->getFragment()); } + + public function testMarshalRequestUriPrefersRequestUriServerParamWhenXOriginalUrlButNoXRewriteUrlPresent(): void + { + $headers = [ + 'X-Original-URL' => '/hijack-attempt', + ]; + $server = [ + 'REQUEST_URI' => 'https://example.com/requested/path', + ]; + + $uri = UriFactory::createFromSapi($server, $headers); + $this->assertSame('/requested/path', $uri->getPath()); + } } diff --git a/test/functions/MarshalUriFromSapiTest.php b/test/functions/MarshalUriFromSapiTest.php deleted file mode 100644 index c78d459a..00000000 --- a/test/functions/MarshalUriFromSapiTest.php +++ /dev/null @@ -1,108 +0,0 @@ - $httpsValue, - 'SERVER_NAME' => 'localhost', - 'SERVER_PORT' => '80', - 'SERVER_ADDR' => '172.22.0.4', - 'REMOTE_PORT' => '36852', - 'REMOTE_ADDR' => '172.22.0.1', - 'SERVER_SOFTWARE' => 'nginx/1.11.8', - 'GATEWAY_INTERFACE' => 'CGI/1.1', - 'SERVER_PROTOCOL' => 'HTTP/1.1', - 'DOCUMENT_ROOT' => '/var/www/public', - 'DOCUMENT_URI' => '/index.php', - 'REQUEST_URI' => '/api/messagebox-schema', - 'PATH_TRANSLATED' => '/var/www/public', - 'PATH_INFO' => '', - 'SCRIPT_NAME' => '/index.php', - 'CONTENT_LENGTH' => '', - 'CONTENT_TYPE' => '', - 'REQUEST_METHOD' => 'GET', - 'QUERY_STRING' => '', - 'SCRIPT_FILENAME' => '/var/www/public/index.php', - 'FCGI_ROLE' => 'RESPONDER', - 'PHP_SELF' => '/index.php', - ]; - - $headers = [ - 'HTTP_COOKIE' => '', - 'HTTP_ACCEPT_LANGUAGE' => 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7', - 'HTTP_ACCEPT_ENCODING' => 'gzip, deflate, br', - 'HTTP_REFERER' => 'http://localhost:8080/index.html', - 'HTTP_USER_AGENT' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)', - 'HTTP_ACCEPT' => 'application/json,*/*', - 'HTTP_CONNECTION' => 'keep-alive', - 'HTTP_HOST' => 'localhost:8080', - ]; - - $url = marshalUriFromSapi($server, $headers); - - self::assertSame($expectedScheme, $url->getScheme()); - } - - /** @return array */ - public function returnsUrlWithCorrectHttpSchemeFromArraysProvider(): array - { - return [ - 'on-lowercase' => ['on', 'https'], - 'on-uppercase' => ['ON', 'https'], - 'off-lowercase' => ['off', 'http'], - 'off-mixed-case' => ['oFf', 'http'], - 'neither-on-nor-off' => ['foo', 'http'], - 'empty' => ['', 'http'], - ]; - } - - /** - * @dataProvider returnsUrlWithCorrectSchemeAndHostFromArrays - */ - public function testReturnsUrlWithCorrectSchemeAndHostFromArrays( - string $expectedScheme, - string $expectedHost, - array $server, - array $headers - ): void { - $uri = marshalUriFromSapi($server, $headers); - self::assertSame($expectedScheme, $uri->getScheme()); - self::assertSame($expectedHost, $uri->getHost()); - } - - /** @return array, array}> */ - public function returnsUrlWithCorrectSchemeAndHostFromArrays(): array - { - return [ - 'x-forwarded-proto' => [ - 'https', - 'localhost', - [ - 'SERVER_NAME' => 'localhost', - ], - ['X-Forwarded-Proto' => 'https'], - ], - 'x-forwarded-host' => [ - 'http', - 'example.org', - [ - 'SERVER_NAME' => 'localhost', - ], - ['X-Forwarded-Host' => 'example.org', 'Host' => 'localhost'], - ], - ]; - } -}