diff --git a/controller/Controller.class.php b/controller/Controller.class.php index 97a9d126..55f0468f 100644 --- a/controller/Controller.class.php +++ b/controller/Controller.class.php @@ -173,7 +173,7 @@ class Controller return static::redirect('/' . strtolower($slug), 301); } if (View::exists('page/' . $slug)) { - Response::enableHttpCache(); + Response::enablePublicImmutableCache(); return ['page/' . $slug, []]; } else { return NavActions::execute404(); diff --git a/controller/Session.class.php b/controller/Session.class.php index 51ec4d65..1fdbeb81 100644 --- a/controller/Session.class.php +++ b/controller/Session.class.php @@ -16,11 +16,18 @@ class Session { ini_set('session.cookie_secure', IS_PRODUCTION); // send cookie over ssl only ini_set('session.cookie_httponly', true); // no js access to cookies + session_start(); + /* + * session_start automatically adds headers because lolphp, let's remove them and handle it ourselves + */ + header_remove('cache-control'); + header_remove('pragma'); + header_remove('expires'); if (!static::get('secure_and_httponly_set')) { - session_regenerate_id(); // ensure that old cookies get new settings + session_regenerate_id(); // ensure that old cookies get new settings } static::set('secure_and_httponly_set', true); diff --git a/controller/action/AcquisitionActions.class.php b/controller/action/AcquisitionActions.class.php index 8575995d..2a0875f4 100644 --- a/controller/action/AcquisitionActions.class.php +++ b/controller/action/AcquisitionActions.class.php @@ -36,16 +36,19 @@ class AcquisitionActions extends Actions public static function executeVerify(string $token) { + Response::disableHttpCache(); return ['acquisition/verify', ['token' => $token]]; } public static function executeAutoVerify() { + Response::disableHttpCache(); return ['acquisition/auto-verify']; } public static function executeYoutubeToken() { + Response::disableHttpCache(); $channelName = Request::encodeStringFromUser($_POST['desired_lbry_channel_name']); $immediateSync = (boolean)$_POST['immediate_sync']; @@ -65,6 +68,7 @@ class AcquisitionActions extends Actions public static function executeYoutubeStatus(string $token) { + Response::disableHttpCache(); $data = LBRY::statusYoutube($token); if (!$data['success']) { diff --git a/controller/action/ContentActions.class.php b/controller/action/ContentActions.class.php index fe1f6d3a..ca2e90e1 100644 --- a/controller/action/ContentActions.class.php +++ b/controller/action/ContentActions.class.php @@ -28,27 +28,27 @@ class ContentActions extends Actions public static function executeHome(): array { - Response::enableHttpCache(); + Response::enablePublicImmutableCache(); return ['page/home']; } // public static function executeOrg(): array { - Response::enableHttpCache(); + Response::enablePublicImmutableCache(); return ['page/org']; } public static function executeTv(): array { - Response::enableHttpCache(); + Response::enablePublicImmutableCache(); return ['page/tv']; } // public static function executeNews(string $slug = null): array { - Response::enableHttpCache(); + Response::enablePublicImmutableCache(); if (!$slug || $slug == static::SLUG_RSS) { $posts = array_filter( @@ -90,7 +90,7 @@ class ContentActions extends Actions public static function executeFaq(string $slug = null): array { - Response::enableHttpCache(); + Response::enablePublicImmutableCache(); if (!$slug) { $allPosts = Post::find(static::VIEW_FOLDER_FAQ, Post::SORT_ORD_ASC); @@ -139,7 +139,7 @@ class ContentActions extends Actions public static function executeCreditReports(string $year = null, string $month = null): array { - Response::enableHttpCache(); + Response::enablePublicImmutableCache(); $posts = Post::find(static::VIEW_FOLDER_CREDIT_REPORTS); @@ -150,7 +150,7 @@ class ContentActions extends Actions public static function executeCreditReport(string $year = null, string $quarter = null): array { - Response::enableHttpCache(); + Response::enablePublicImmutableCache(); try { $post = Post::load(static::SLUG_CREDIT_REPORTS . '/' . $year . '-Q' . $quarter); @@ -172,7 +172,7 @@ class ContentActions extends Actions public static function executeBounty(string $slug = null): array { - Response::enableHttpCache(); + Response::enablePublicImmutableCache(); @@ -276,7 +276,7 @@ class ContentActions extends Actions // // $zip->close(); // -// Response::enableHttpCache(); +// Response::enablePublicImmutableCache(); // Response::setDownloadHttpHeaders($zipFileName, 'application/zip', filesize($zipPath)); // // return ['internal/zip', [ @@ -320,7 +320,7 @@ class ContentActions extends Actions } public static function executePostCategoryFilter(string $category) { - Response::enableHttpCache(); + Response::enablePublicImmutableCache(); $filter_post = []; diff --git a/controller/action/MailActions.class.php b/controller/action/MailActions.class.php index 90cebe42..7fb87aa5 100644 --- a/controller/action/MailActions.class.php +++ b/controller/action/MailActions.class.php @@ -51,6 +51,7 @@ class MailActions extends Actions public static function executeUnsubscribe(string $email) { + Response::disableHttpCache(); $decodedEmail = Encoding::base64DecodeUrlsafe(urldecode($email)); if (!$decodedEmail) { return ['mail/unsubscribe', ['error' => 'Invalid unsubscribe link']]; @@ -62,6 +63,7 @@ class MailActions extends Actions public static function editEmailSettings(string $token) { + Response::disableHttpCache(); list($status, $headers, $response) = LBRY::emailStatus($token); if ($status == 403) { //Catch 403 to return elegant error message. diff --git a/controller/action/i18nActions.class.php b/controller/action/i18nActions.class.php index cc20ae3a..4da4ddfd 100644 --- a/controller/action/i18nActions.class.php +++ b/controller/action/i18nActions.class.php @@ -32,7 +32,7 @@ class i18nActions extends Actions $json = Transifex::getTranslationResourceFile($project, $resource, $language); Response::setHeader(Response::HEADER_CROSS_ORIGIN, "*"); - Response::setHeader(Response::HEADER_ETAG, md5(json_encode($json))); + Response::enablePublicMutableCache(md5(json_encode($json))); return View::renderJson($json); } diff --git a/view/Response.class.php b/view/Response.class.php index 479fbbdb..54ba3b5e 100644 --- a/view/Response.class.php +++ b/view/Response.class.php @@ -6,7 +6,6 @@ class Response const HEADER_LOCATION = 'Location'; const HEADER_CACHE_CONTROL = 'Cache-Control'; - const HEADER_LAST_MODIFIED = 'Last-Modified'; const HEADER_ETAG = 'Etag'; const HEADER_CONTENT_TYPE = 'Content-Type'; @@ -26,7 +25,9 @@ class Response ], 'css' => ['/css/all.css'] ]; - protected static $headers = []; + protected static $headers = [ + 'Cache-Control' => 'private, no-cache' + ]; protected static $headersSent = false; protected static $content = ''; protected static $contentSent = false; @@ -192,30 +193,23 @@ class Response ])); } - public static function enableHttpCache(int $seconds = 300) + //public immutable cache = hard-caching (no server checks) until time limit passes + public static function enablePublicImmutableCache(int $seconds = 300) { - static::addCacheControlHeader('max-age', $seconds); - static::setHeader('Pragma', 'public'); + static::setHeader(static::HEADER_CACHE_CONTROL, 'public, max-age=' . $seconds); } - public static function addCacheControlHeader(string $name, $value = null) + //public mutable cache = soft-caching (requires at least one round trip for headers) as long as etag identifier matches + public static function enablePublicMutableCache(string $etag) { - $cacheControl = static::getHeader(static::HEADER_CACHE_CONTROL); - $currentHeaders = []; - if ($cacheControl) { - foreach (preg_split('/\s*,\s*/', $cacheControl) as $tmp) { - $tmp = explode('=', $tmp); - $currentHeaders[$tmp[0]] = $tmp[1] ?? null; - } - } - $currentHeaders[strtr(strtolower($name), '_', '-')] = $value; + static::setHeader(static::HEADER_CACHE_CONTROL, 'public, no-cache'); + static::setHeader(static::HEADER_ETAG, $etag); + } - $headers = []; - foreach ($currentHeaders as $key => $currentVal) { - $headers[] = $key . ($currentVal !== null ? '=' . $currentVal : ''); - } - - static::setHeader(static::HEADER_CACHE_CONTROL, implode(', ', $headers)); + //always reload and re-execute this resource, disable any local or intermediary caching + public static function disableHttpCache() + { + static::setHeader(static::HEADER_CACHE_CONTROL, 'private, no-cache, no-store'); } public static function setHeader($name, $value)