'php', 'cookiePath' => $uri->webroot, ]; $session = Session::create($sessionConfig); /** @psalm-suppress NoInterfaceProperties */ $request = new ServerRequest([ 'environment' => $server, 'uri' => $uri, 'files' => $files ?: $_FILES, 'cookies' => $cookies ?: $_COOKIE, 'query' => $query ?: $_GET, 'post' => $body ?: $_POST, 'webroot' => $uri->webroot, 'base' => $uri->base, 'session' => $session, 'mergeFilesAsObjects' => Configure::read('App.uploadedFilesAsObjects', true), ]); return $request; } /** * Create a new server request. * * Note that server-params are taken precisely as given - no parsing/processing * of the given values is performed, and, in particular, no attempt is made to * determine the HTTP method or URI, which must be provided explicitly. * * @param string $method The HTTP method associated with the request. * @param \Psr\Http\Message\UriInterface|string $uri The URI associated with the request. If * the value is a string, the factory MUST create a UriInterface * instance based on it. * @param array $serverParams Array of SAPI parameters with which to seed * the generated request instance. * * @return \Psr\Http\Message\ServerRequestInterface */ public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface { $serverParams['REQUEST_METHOD'] = $method; $options = ['environment' => $serverParams]; if ($uri instanceof UriInterface) { $options['uri'] = $uri; } else { $options['url'] = $uri; } return new ServerRequest($options); } /** * Create a new Uri instance from the provided server data. * * @param array $server Array of server data to build the Uri from. * $_SERVER will be added into the $server parameter. * @return \Psr\Http\Message\UriInterface New instance. */ public static function createUri(array $server = []): UriInterface { $server += $_SERVER; $server = normalizeServer($server); $headers = marshalHeadersFromSapi($server); return static::marshalUriFromSapi($server, $headers); } /** * Build a UriInterface object. * * Add in some CakePHP specific logic/properties that help * preserve backwards compatibility. * * @param array $server The server parameters. * @param array $headers The normalized headers * @return \Psr\Http\Message\UriInterface a constructed Uri */ protected static function marshalUriFromSapi(array $server, array $headers): UriInterface { $uri = marshalUriFromSapi($server, $headers); [$base, $webroot] = static::getBase($uri, $server); // Look in PATH_INFO first, as this is the exact value we need prepared // by PHP. $pathInfo = Hash::get($server, 'PATH_INFO'); if ($pathInfo) { $uri = $uri->withPath($pathInfo); } else { $uri = static::updatePath($base, $uri); } if (!$uri->getHost()) { $uri = $uri->withHost('localhost'); } // Splat on some extra attributes to save // some method calls. /** @psalm-suppress NoInterfaceProperties */ $uri->base = $base; /** @psalm-suppress NoInterfaceProperties */ $uri->webroot = $webroot; return $uri; } /** * Updates the request URI to remove the base directory. * * @param string $base The base path to remove. * @param \Psr\Http\Message\UriInterface $uri The uri to update. * @return \Psr\Http\Message\UriInterface The modified Uri instance. */ protected static function updatePath(string $base, UriInterface $uri): UriInterface { $path = $uri->getPath(); if (strlen($base) > 0 && strpos($path, $base) === 0) { $path = substr($path, strlen($base)); } if ($path === '/index.php' && $uri->getQuery()) { $path = $uri->getQuery(); } if (empty($path) || $path === '/' || $path === '//' || $path === '/index.php') { $path = '/'; } $endsWithIndex = '/' . (Configure::read('App.webroot') ?: 'webroot') . '/index.php'; $endsWithLength = strlen($endsWithIndex); if (strlen($path) >= $endsWithLength && substr($path, -$endsWithLength) === $endsWithIndex ) { $path = '/'; } return $uri->withPath($path); } /** * Calculate the base directory and webroot directory. * * @param \Psr\Http\Message\UriInterface $uri The Uri instance. * @param array $server The SERVER data to use. * @return array An array containing the [baseDir, webroot] */ protected static function getBase(UriInterface $uri, array $server): array { $config = (array)Configure::read('App') + [ 'base' => null, 'webroot' => null, 'baseUrl' => null, ]; $base = $config['base']; $baseUrl = $config['baseUrl']; $webroot = $config['webroot']; if ($base !== false && $base !== null) { return [$base, $base . '/']; } if (!$baseUrl) { $base = dirname(Hash::get($server, 'PHP_SELF')); // Clean up additional / which cause following code to fail.. $base = preg_replace('#/+#', '/', $base); $indexPos = strpos($base, '/' . $webroot . '/index.php'); if ($indexPos !== false) { $base = substr($base, 0, $indexPos) . '/' . $webroot; } if ($webroot === basename($base)) { $base = dirname($base); } if ($base === DIRECTORY_SEPARATOR || $base === '.') { $base = ''; } $base = implode('/', array_map('rawurlencode', explode('/', $base))); return [$base, $base . '/']; } $file = '/' . basename($baseUrl); $base = dirname($baseUrl); if ($base === DIRECTORY_SEPARATOR || $base === '.') { $base = ''; } $webrootDir = $base . '/'; $docRoot = Hash::get($server, 'DOCUMENT_ROOT'); $docRootContainsWebroot = strpos($docRoot, $webroot); if (!empty($base) || !$docRootContainsWebroot) { if (strpos($webrootDir, '/' . $webroot . '/') === false) { $webrootDir .= $webroot . '/'; } } return [$base . $file, $webrootDir]; } }