Skip to content

Commit

Permalink
Changed cache variable to be standard on route - "cached" can be true…
Browse files Browse the repository at this point in the history
… or false

Removed the "create" cached response from static elements
Added content type for cached response and RouterResponse
Templates are cached if caching is on
Correct mimetype is returned on files for content type
Cache is instantiated even if cache is not on when route is annotated with @cache
FreshToken header is returned after valid authentication
@no-cache plus @cache annotations available for routes
Default security is set to user when @secure annotation does not contain a security group
Fix where security was bypassed when caching was on
@Content-Type annotation added to determine correct 403 response type
403 response type will respond with empty array when content-type is application/json or application/xml
Initialize now has a createCache method to instantiate the cache if required.
Headers are not returned when httpcode is 403 - security
Composer package updates
  • Loading branch information
andrevanzuydam committed Nov 29, 2023
1 parent 3423d63 commit d007fdb
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 183 deletions.
15 changes: 12 additions & 3 deletions Tina4/Initialize.php
Original file line number Diff line number Diff line change
Expand Up @@ -316,11 +316,13 @@ function autoLoadFolders($documentRoot, $location, $class)
}
}

//Initialize the Cache
global $cache;

//On a rerun need to check if we have already instantiated the cache
function createCache()
{
//Initialize the Cache
global $cache;

if (defined("TINA4_CACHE_ON") && TINA4_CACHE_ON === true) {
if (!file_exists("." . DIRECTORY_SEPARATOR . "cache" . DIRECTORY_SEPARATOR) && !mkdir("." . DIRECTORY_SEPARATOR . "cache" . DIRECTORY_SEPARATOR, 0777, true)) {
Debug::message("Could not create " . DIRECTORY_SEPARATOR . "cache");
}
Expand All @@ -338,6 +340,13 @@ function autoLoadFolders($documentRoot, $location, $class)
\Tina4\Debug::message("Could not initialize cache", TINA4_LOG_ERROR);
}
}

return $cache;
}


if (defined("TINA4_CACHE_ON") && TINA4_CACHE_ON === true) {
createCache();
} else {
$cache = null;
}
Expand Down
12 changes: 11 additions & 1 deletion Tina4/Routing/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,16 @@ public static function middleware(array $functionNames): void
public static function noCache(): void
{
global $arrRoutes;
$arrRoutes[sizeof($arrRoutes)-1]["noCache"] = true;
$arrRoutes[sizeof($arrRoutes)-1]["cached"] = false;
}

/**
* Cache route
* @return void
*/
public static function Cache(): void
{
global $arrRoutes;
$arrRoutes[sizeof($arrRoutes)-1]["cached"] = true;
}
}
158 changes: 117 additions & 41 deletions Tina4/Routing/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ final public function resolveRoute(?string $method, ?string $url, ?Config $confi
$fileName = realpath(TINA4_DOCUMENT_ROOT . DIRECTORY_SEPARATOR . "src" . DIRECTORY_SEPARATOR . "public" . $url); //The most obvious request
if (file_exists($fileName) && $routerResponse = $this->returnStatic($fileName)) {
Debug::message("$this->GUID GET - " . $fileName, TINA4_LOG_DEBUG);
$this->createCacheResponse($url, $routerResponse->httpCode, $routerResponse->content, $this->addCORS($routerResponse->headers), $fileName);

if (!empty($routerResponse->content)) {
return $routerResponse;
}
Expand All @@ -109,7 +107,16 @@ final public function resolveRoute(?string $method, ?string $url, ?Config $confi

//THIRD ROUTING
if ($routerResponse = $this->handleRoutes($method, $url, $customHeaders, $customRequest)) {
$this->createCacheResponse($url, $routerResponse->httpCode, $routerResponse->content, $this->addCORS($routerResponse->headers), "");
if ($routerResponse->cached) {
$this->createCacheResponse(
$url,
$routerResponse->httpCode,
$routerResponse->content,
$this->addCORS($routerResponse->headers),
"",
$routerResponse->contentType
);
}
return $routerResponse;
}

Expand All @@ -130,28 +137,15 @@ final public function resolveRoute(?string $method, ?string $url, ?Config $confi
}
}

$this->createCacheResponse($url, $parseFile->httpCode, $parseFile->content, $this->addCORS($parseFile->headers), $parseFile->fileName);
//Caching of templates
if (defined("TINA4_CACHE_ON") && TINA4_CACHE_ON) {
$this->createCacheResponse($url, $parseFile->httpCode, $parseFile->content, $this->addCORS($parseFile->headers), $parseFile->fileName, TEXT_HTML);
}

return new RouterResponse($parseFile->content, $parseFile->httpCode, $this->addCORS($parseFile->headers));
}

/**
* Get cache response
* @param $url
* @return array|null
* @throws \Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException
* @throws \Psr\Cache\InvalidArgumentException
*/
public function getCacheResponse($url): ?array
{
$key = "url_" . md5($url);

$response = (new Cache())->get($key);
if (defined("TINA4_DEBUG") && TINA4_DEBUG && $response !== null && (strpos($response["fileName"], ".twig") !== false || strpos($response["fileName"], "/public/") !== false)) {
return null;
}

return $response;
}

/**
* Handles an options request
Expand Down Expand Up @@ -205,7 +199,7 @@ public function returnStatic($fileName)
$content = file_get_contents($fileName);
}

return new RouterResponse($content, HTTP_OK, $headers);
return new RouterResponse($content, HTTP_OK, $headers, false, $mimeType);
}

/**
Expand Down Expand Up @@ -309,18 +303,46 @@ public function rangeDownload($file): RouterResponse
* @param $content
* @param $headers
* @param $fileName
* @param $contentType
* @return bool
* @throws PhpfastcacheInvalidArgumentException
* @throws InvalidArgumentException
* @throws PhpfastcacheInvalidArgumentException
*/
public function createCacheResponse($url, $httpCode, $content, $headers, $fileName): bool
public function createCacheResponse($url, $httpCode, $content, $headers, $fileName, $contentType): bool
{
global $cache;
if (empty($cache)) {
$cache = createCache();
}

$key = "url_" . md5($url);
if (defined("TINA4_DEBUG") && TINA4_DEBUG && (strpos($url, ".twig") !== false || strpos($url, "/public/") !== false)) {
return false;
}
return (new Cache())->set($key, ["url" => $url, "fileName" => $fileName, "httpCode" => $httpCode, "content" => $content, "headers" => $headers], 360);
return (new Cache())->set($key, ["url" => $url, "fileName" => $fileName, "httpCode" => $httpCode, "content" => $content, "headers" => $headers, "contentType" => $contentType], 360);
}

/**
* Get cache response
* @param $url
* @return array|null
* @throws \Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException
* @throws \Psr\Cache\InvalidArgumentException
*/
public function getCacheResponse($url): ?array
{
global $cache;
if (empty($cache)) {
$cache = createCache();
}
$key = "url_" . md5($url);

$response = (new Cache())->get($key);
if (defined("TINA4_DEBUG") && TINA4_DEBUG && $response !== null && (strpos($response["fileName"], ".twig") !== false || strpos($response["fileName"], "/public/") !== false)) {
return null;
}

return $response;
}


Expand Down Expand Up @@ -368,8 +390,16 @@ public function handleRoutes($method, $url, array $customHeaders=[], $customRequ
Debug::message("$this->GUID Looking in routes for {$method} - {$url}", TINA4_LOG_DEBUG);
global $arrRoutes;
$response = new Response();

if ($this->config->getAuthentication() === null) {
$auth = new Auth();
$this->config->setAuthentication($auth);
}

$headers = [];
$headers[] = "Tina4Debug: $this->GUID";
$headers[] = "FreshToken: ".$this->config->getAuthentication()->getToken(["payload" => $url]);

//iterate through the routes

foreach ($arrRoutes as $rid => $route) {
Expand All @@ -394,8 +424,37 @@ public function handleRoutes($method, $url, array $customHeaders=[], $customRequ
$route["middleware"] = explode(",", $annotations["middleware"][0]);
}

//Check for no-cache
if (isset($annotations["no-cache"])) {
$route["cached"] = false;
}

//Check for cache annotation
if (isset($annotations["cache"])) {
$route["cached"] = true;
}

//Determine the content type
if (isset($annotations["content-type"])) {
$route["content-type"] = $annotations["content-type"][0];
} else {
$route["content-type"] = TEXT_HTML;
}

if (!isset($route["cached"])) {
if (defined("TINA4_CACHE_ON") && TINA4_CACHE_ON ) {
$route["cached"] = true;
} else {
$route["cached"] = false;
}
}


if (isset($annotations["secure"]) || isset($annotations["security"])) {
$params[sizeof($params)-1]->security = isset($annotations["secure"]) ? explode(",", $annotations["secure"][0]) : explode(",", $annotations["security"][0]);
if (empty($params[sizeof($params)-1]->security[0])) {
$params[sizeof($params)-1]->security[0] = "user";
}
}

if (isset($route["middleware"])) {
Expand All @@ -419,12 +478,7 @@ public function handleRoutes($method, $url, array $customHeaders=[], $customRequ
}

//Look to see if we are a secure route
if (empty($result) && in_array("secure", $annotations, true) || (isset($requestHeaders["Authorization"]) && stripos($requestHeaders["Authorization"], "bearer ") !== false)) {
if ($this->config->getAuthentication() === null) {
$auth = new Auth();
$this->config->setAuthentication($auth);
}

if (empty($result) && isset($annotations["secure"]) || (isset($requestHeaders["Authorization"]) && stripos($requestHeaders["Authorization"], "bearer ") !== false)) {
if (isset($requestHeaders["Authorization"]) && $this->config->getAuthentication()->validToken(urldecode($requestHeaders["Authorization"]))) {
//call closure with & without params
$this->config->setAuthentication(null); //clear the auth
Expand All @@ -445,28 +499,34 @@ public function handleRoutes($method, $url, array $customHeaders=[], $customRequ
{
\Tina4\Debug::message("$this->GUID Matching secure ".$this->config->getAuthentication()->getPayLoad($_REQUEST["formToken"])["payload"]." ".$route["routePath"], TINA4_LOG_DEBUG);
$this->config->setAuthentication(null); //clear the auth

$result = $this->getRouteResult($route["class"], $route["function"], $params);
} else {
if ($route["method"] === TINA4_GET) {
return new RouterResponse("", HTTP_FORBIDDEN, $headers);
if ($route["content-type"] === APPLICATION_JSON || $route["content-type"] === APPLICATION_XML) {
return new RouterResponse([], HTTP_FORBIDDEN, $headers, false, $route["content-type"]);
} else {
return new RouterResponse("", HTTP_FORBIDDEN, $headers, false, $route["content-type"]);
}
}
}
}
}

if (!isset($route["noCache"])) {
else
if ($route["cached"]) {
$cacheResult = $this->getCacheResponse($url);
if ($cacheResult !== null && $url !== "/cache/clear" && $url !== "/migrate" && $url !== "/migrate/create") {
Debug::message("$this->GUID Got cached result for $url", TINA4_LOG_DEBUG);
return new RouterResponse(
$cacheResult["content"],
$cacheResult["httpCode"],
$cacheResult["headers"]
array_merge($cacheResult["headers"], $headers),
false,
$cacheResult["contentType"]
);
}
}


if ($result === null) {
if (isset($_REQUEST["formToken"]) && in_array($route["method"], [\TINA4_POST, \TINA4_PUT, \TINA4_PATCH, \TINA4_DELETE], true)) {
if ($this->config->getAuthentication() === null) {
Expand All @@ -477,6 +537,20 @@ public function handleRoutes($method, $url, array $customHeaders=[], $customRequ
if (!$this->config->getAuthentication()->validToken($_REQUEST["formToken"])) {
return new RouterResponse("", HTTP_FORBIDDEN, $headers);
} else {
if ($route["cached"]) {
$cacheResult = $this->getCacheResponse($url);
if ($cacheResult !== null && $url !== "/cache/clear" && $url !== "/migrate" && $url !== "/migrate/create") {
Debug::message("$this->GUID Got cached result for $url", TINA4_LOG_DEBUG);
return new RouterResponse(
$cacheResult["content"],
$cacheResult["httpCode"],
array_merge($cacheResult["headers"], $headers),
false,
$cacheResult["contentType"]
);
}
}

$this->config->setAuthentication(null); //clear the auth
$result = $this->getRouteResult($route["class"], $route["function"], $params);
}
Expand All @@ -487,7 +561,11 @@ public function handleRoutes($method, $url, array $customHeaders=[], $customRequ
if ($url === "/git/deploy" || $this->config->getAuthentication()->validToken(json_encode($_REQUEST))) {
$result = $this->getRouteResult($route["class"], $route["function"], $params);
} else {
return new RouterResponse("", HTTP_FORBIDDEN, $headers);
if ($route["content-type"] === APPLICATION_JSON || $route["content-type"] === APPLICATION_XML) {
return new RouterResponse([], HTTP_FORBIDDEN, $headers, false, $route["content-type"]);
} else {
return new RouterResponse("", HTTP_FORBIDDEN, $headers, false, $route["content-type"]);
}
}
}
else {
Expand All @@ -497,23 +575,21 @@ public function handleRoutes($method, $url, array $customHeaders=[], $customRequ

//check for an empty result
if ($result === null && !is_array($result) && !is_object($result)) {
return new RouterResponse("", HTTP_OK);
return new RouterResponse("", HTTP_OK, [], false, $route["content-type"]);
} elseif (!is_string($result)) {
$headers[] = $result["contentType"];
$content = $result["content"];
$httpCode = $result["httpCode"];

//Find X Headers and add to the $headers variable TINA4_RETURN_X_HEADERS=true which is default
if (defined("TINA4_RETURN_X_HEADERS") && TINA4_RETURN_X_HEADERS) {

$headers = $this->getXHeaders($headers);
}

if (!empty($result["customHeaders"]) && is_array($result["customHeaders"])) {
$headers = array_merge($headers, $result["customHeaders"]);
}

return new RouterResponse($content, $httpCode, $headers);
return new RouterResponse($content, $httpCode, $headers, $route["cached"], $result["contentType"]);
}

break;
Expand Down
6 changes: 5 additions & 1 deletion Tina4/Routing/RouterResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ class RouterResponse
public $content;
public $httpCode;
public $headers;
public $cached;
public $contentType;

public function __construct($content, ?int $httpCode = HTTP_NOT_FOUND, array $headers = [])
public function __construct($content, ?int $httpCode = HTTP_NOT_FOUND, array $headers = [], $cached=false, $contentType=TEXT_HTML)
{
$this->content = $content;
$this->httpCode = $httpCode;
$this->headers = $headers;
$this->cached = $cached;
$this->contentType = $contentType;
}
}
7 changes: 5 additions & 2 deletions Tina4/Tina4Php.php
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,13 @@ public function __toString(): string
$content = "";
if ($routerResponse !== null) {
if (!headers_sent()) {
foreach ($routerResponse->headers as $hid => $header) {
header($header);
if ($routerResponse->httpCode !== HTTP_FORBIDDEN) {
foreach ($routerResponse->headers as $hid => $header) {
header($header);
}
}
}
header("Content-Type: " . $routerResponse->contentType);
http_response_code($routerResponse->httpCode);
if ($routerResponse->content === "") {
//try give back a response based on the error code - first templates then public
Expand Down
Loading

0 comments on commit d007fdb

Please sign in to comment.