Pages with protected content cannot be cached

Hi dear community,

I’ve recently upgraded a website containing more than 1500 pages from Kirby 3.5.0 (PHP 7.4) to 3.7.5 (PHP 8.1). Since then, the overall navigation has slowed down because pages are not being cached anymore.

The following code in my header snippet seems to be the cause:

<?php if ( $kirby->user() ):
  <a href="url('my-account)">My account</a>
<?php endif ?>

I read a lot here and on Github about the security reason why cacheability detection has evolved, but after trying different nonworking hacks, I still wonder:

How to properly cache a page with some protected content for visitors?

I’m not sure if my question is really clear, so I’ve taken a screen capture to better explain my issue.

  1. Users can log in by filling a form displayed in a modal, accessible on every page in the website header.
  2. Once logged in, the content of this same modal is replaced by some links. It could be a simple link to their account, or to a page with protected content to read and download (as in the capture above). Those links are wrapped in a code similar to what I’ve typed in my initial post (checking if Kirby user).
  3. And, sadly, because of this simple user check, the pages of my website cannot be cached for visitors…

In the past, I used this in my config:

'cache' => [
  'pages' => [
    'active' => true,
    'ignore' => function() {
      return kirby()->user() !== null;
    }
  ]
],

…but it’s not working anymore since latest Kirby versions. So I’m now looking for alternatives, if there are new proper ways to check for active sessions and display protected content without breaking the cache functionality (which I really need as like I said, it used to hyperboost the page loadings).

Thank you very much for your time, if someone can guide me :pray:

Since I wasn’t really up to date I confirmed with the team and caching should works for users who are not logged in without any further config setting, i.e you can remove your config check for a logged in user.

Hi Sonja!

In my config.php, to activate cache for all pages, I currently have this:

'cache' => [
  'pages' => [
    'active' => true
  ]
],

Cache is working fine (at this step). In the header response I have:

  • For visitors: Cache-Control: max-age=0
  • For logged in users: Cache-Control: no-store, private

But in any template or snippet, if I want to make some content visible for logged in users only, once I use let’s says this:

<?php if ( $kirby->user() ):
  "Hello dear member"
<?php endif ?>

… the header response for visitors become Cache-Control: no-store, private.

I tried many things to make cache work, like I explained previously, even some hacks like the one shared here by @sebastiangreger. The issue has even been reproduced today by @sylvainjule using the latest Starterkit (3.7.5), as described in this Github post
So I’m not the only one struggling with cache when pages contain user checks to display protected content :exploding_head:

HOWEVER, I just noticed that in the .htaccess file (the one inlcuded in the Starterkit and Plainkit), if I remove the following line, caching seems to work as expected for visitors:

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

I said “seems to work” because I don’t know if it’s not breaking or going to break something in the way Kirby uses authorization… Maybe @lukasbestle, @bnomei or even @bastianallgeier could share their input? (Sorry guys for pinging, hope you won’t by angry :sweat_smile:)

Again, thanks all for your time and effort helping solve this issue :smiling_face:

@lukasbestle will look into it asap.

1 Like

Discussion continues in the GitHub issue to keep everything in one place:

Thank you @tacotac for the pointer that HTTP_AUTHORIZATION makes a difference here, it lead me to a possible solution in the core.

Thank you @lukasbestle! I’m so glad if my finding could help you solve this. Finally cache is working using your solution :dancer: