Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion flight/Engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -1020,8 +1020,10 @@ public function _etag(string $id, string $type = 'strong'): void
public function _lastModified(int $time): void
{
$this->response()->header('Last-Modified', gmdate('D, d M Y H:i:s \G\M\T', $time));
$request = $this->request();
$ifModifiedSince = $request->header('If-Modified-Since');

$hit = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $time;
$hit = isset($ifModifiedSince) && strtotime($ifModifiedSince) === $time;
$this->triggerEvent('flight.cache.checked', 'lastModified', $hit, 0.0);

if ($hit === true) {
Expand Down
88 changes: 51 additions & 37 deletions flight/net/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,27 +155,37 @@ class Request
public function __construct(array $config = [])
{
// Default properties
if (empty($config)) {
if (empty($config) === true) {
$scheme = $this->getScheme();
$url = $this->getVar('REQUEST_URI', '/');
if (strpos($url, '@') !== false) {
$url = str_replace('@', '%40', $url);
}
$base = $this->getVar('SCRIPT_NAME', '');
if (strpos($base, ' ') !== false || strpos($base, '\\') !== false) {
$base = str_replace(['\\', ' '], ['/', '%20'], $base);
}
$base = dirname($base);
$config = [
'url' => str_replace('@', '%40', self::getVar('REQUEST_URI', '/')),
'base' => str_replace(['\\', ' '], ['/', '%20'], \dirname(self::getVar('SCRIPT_NAME'))),
'method' => self::getMethod(),
'referrer' => self::getVar('HTTP_REFERER'),
'ip' => self::getVar('REMOTE_ADDR'),
'ajax' => self::getVar('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest',
'scheme' => self::getScheme(),
'user_agent' => self::getVar('HTTP_USER_AGENT'),
'type' => self::getVar('CONTENT_TYPE'),
'length' => intval(self::getVar('CONTENT_LENGTH', 0)),
'url' => $url,
'base' => $base,
'method' => $this->getMethod(),
'referrer' => $this->getVar('HTTP_REFERER'),
'ip' => $this->getVar('REMOTE_ADDR'),
'ajax' => $this->getVar('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest',
'scheme' => $scheme,
'user_agent' => $this->getVar('HTTP_USER_AGENT'),
'type' => $this->getVar('CONTENT_TYPE'),
'length' => intval($this->getVar('CONTENT_LENGTH', 0)),
'query' => new Collection($_GET),
'data' => new Collection($_POST),
'cookies' => new Collection($_COOKIE),
'files' => new Collection($_FILES),
'secure' => self::getScheme() === 'https',
'accept' => self::getVar('HTTP_ACCEPT'),
'proxy_ip' => self::getProxyIpAddress(),
'host' => self::getVar('HTTP_HOST'),
'servername' => self::getVar('SERVER_NAME', ''),
'secure' => $scheme === 'https',
'accept' => $this->getVar('HTTP_ACCEPT'),
'proxy_ip' => $this->getProxyIpAddress(),
'host' => $this->getVar('HTTP_HOST'),
'servername' => $this->getVar('SERVER_NAME', ''),
];
}

Expand All @@ -201,7 +211,7 @@ public function init(array $properties = []): self
// (such as installing on a subdirectory in a web server)
// @see testInitUrlSameAsBaseDirectory
if ($this->base !== '/' && $this->base !== '' && strpos($this->url, $this->base) === 0) {
$this->url = substr($this->url, \strlen($this->base));
$this->url = substr($this->url, strlen($this->base));
}

// Default url
Expand Down Expand Up @@ -249,11 +259,11 @@ public function getBody(): string
return $body;
}

$method = $this->method ?? self::getMethod();
$method = $this->method ?? $this->getMethod();

if ($method === 'POST' || $method === 'PUT' || $method === 'DELETE' || $method === 'PATCH') {
$body = file_get_contents($this->stream_path);
}
if (in_array($method, ['POST', 'PUT', 'DELETE', 'PATCH'], true) === true) {
$body = file_get_contents($this->stream_path);
}

$this->body = $body;

Expand All @@ -267,8 +277,8 @@ public static function getMethod(): string
{
$method = self::getVar('REQUEST_METHOD', 'GET');

if (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']) === true) {
$method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'];
if (self::getVar('HTTP_X_HTTP_METHOD_OVERRIDE') !== '') {
$method = self::getVar('HTTP_X_HTTP_METHOD_OVERRIDE');
} elseif (isset($_REQUEST['_method']) === true) {
$method = $_REQUEST['_method'];
}
Expand All @@ -295,8 +305,9 @@ public static function getProxyIpAddress(): string
$flags = \FILTER_FLAG_NO_PRIV_RANGE | \FILTER_FLAG_NO_RES_RANGE;

foreach ($forwarded as $key) {
if (\array_key_exists($key, $_SERVER) === true) {
sscanf($_SERVER[$key], '%[^,]', $ip);
$serverVar = self::getVar($key);
if ($serverVar !== '') {
sscanf($serverVar, '%[^,]', $ip);
if (filter_var($ip, \FILTER_VALIDATE_IP, $flags) !== false) {
return $ip;
}
Expand Down Expand Up @@ -403,14 +414,17 @@ public function getBaseUrl(): string
*/
public static function parseQuery(string $url): array
{
$params = [];

$args = parse_url($url);
if (isset($args['query']) === true) {
parse_str($args['query'], $params);
}

return $params;
$queryPos = strpos($url, '?');
if ($queryPos === false) {
return [];
}
$query = substr($url, $queryPos + 1);
if ($query === '') {
return [];
}
$params = [];
parse_str($query, $params);
return $params;
}

/**
Expand All @@ -421,13 +435,13 @@ public static function parseQuery(string $url): array
public static function getScheme(): string
{
if (
(isset($_SERVER['HTTPS']) === true && strtolower($_SERVER['HTTPS']) === 'on')
(strtolower(self::getVar('HTTPS')) === 'on')
||
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) === true && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
(self::getVar('HTTP_X_FORWARDED_PROTO') === 'https')
||
(isset($_SERVER['HTTP_FRONT_END_HTTPS']) === true && $_SERVER['HTTP_FRONT_END_HTTPS'] === 'on')
(self::getVar('HTTP_FRONT_END_HTTPS') === 'on')
||
(isset($_SERVER['REQUEST_SCHEME']) === true && $_SERVER['REQUEST_SCHEME'] === 'https')
(self::getVar('REQUEST_SCHEME') === 'https')
) {
return 'https';
}
Expand Down
3 changes: 2 additions & 1 deletion flight/net/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,11 @@ public function sendHeaders(): self
);
// @codeCoverageIgnoreEnd
} else {
$serverProtocol = Request::getVar('SERVER_PROTOCOL') ?: 'HTTP/1.1';
$this->setRealHeader(
sprintf(
'%s %d %s',
$_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1',
$serverProtocol,
$this->status,
self::$codes[$this->status]
),
Expand Down
21 changes: 21 additions & 0 deletions tests/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -356,4 +356,25 @@ public function testGetMultiFileUpload(): void
$this->assertEquals('/tmp/php456', $files[1]->getTempName());
$this->assertEquals(0, $files[1]->getError());
}

public function testUrlWithAtSymbol(): void
{
$_SERVER['REQUEST_URI'] = '/user@domain';
$_SERVER['SCRIPT_NAME'] = '/index.php';
$request = new Request();
$this->assertEquals('/user%40domain', $request->url);
}

public function testBaseWithSpaceAndBackslash(): void
{
$_SERVER['SCRIPT_NAME'] = '\\dir name\\base folder\\index.php';
$request = new Request();
$this->assertEquals('/dir%20name/base%20folder', $request->base);
}

public function testParseQueryWithEmptyQueryString(): void
{
$result = Request::parseQuery('/foo?');
$this->assertEquals([], $result);
}
}