This is somewhat of a duplicate issue from the flag module #1468984: Flags deactivates page cache in combination with session_api module.

From what I can tell, basic interaction with the session_api module renders pages uncachable.

function session_api_get_sid($create = TRUE) {
  ...
  if ($create) {
    // Must initialize sessions for anonymous users.
    session_api_start_session();
  }
  ...

It calls session_api_start_session():

function session_api_start_session() {
  $_SESSION['session_api_session'] = '';
  drupal_session_start();
}

Which drops data into the session.
But, the in the core's session.inc file, a page becomes uncachable the moment anything is added to session:

function drupal_session_initialize() {
  ... 
  if (!empty($_COOKIE[session_name()]) || ($is_https && variable_get('https', FALSE) && !empty($_COOKIE[substr(session_name(), 1)]))) {
    ... 
    // This is where we get buggered
    if (!empty($user->uid) || !empty($_SESSION)) {
      drupal_page_is_cacheable(FALSE);
    }
  ... 

I'm not sure if this is a bug, a feature, or a won't fix type of issue. Was the session api module meant to disable page caching? I was under the impression it might be possible to keep session data in the database, then drop the sid into a cookie, bypassing the session altogether.

Drupal: 7.12
Flag: 7.x-2.0-beta6
Session_api: 7.x-1.0-beta3

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

lance.gliser’s picture

quicksketch checked in the issue against Flag. He's labeling this a session_api issue.

jhedstrom’s picture

Unless I'm missing something, setting $create = FALSE will resolve the issue. If a site needs more control of when sessions are created, that's what the parameter is for. Perhaps flag can make that configurable? I'm also open to how session api itself might resolve this issue, but I don't have any ideas offhand.

lance.gliser’s picture

Status: Active » Postponed

I tested out your suggestion, and I do retain page caches, while keeping flag cookies. From 20 minutes testing, does seem to resolve it. Let's put this on hold, and go back over to flag and see what others find.

quicksketch’s picture

Category: support » bug
Status: Postponed » Active

I've confirmed that Session API is the root of the problem in #1468984: Flags deactivates page cache in combination with session_api module. Session API's use of the $_SESSION variable completely eliminates the purpose of this module. If we wanted to start a normal PHP session, you wouldn't have any purpose for Session API since a session ID is generated already once you put something in $_SESSION. The added effect of using $_SESSION is that the page cache is disabled.

What Flag module expects from Session API is that it will generate a numeric session ID without starting a normal PHP session.

quicksketch’s picture

Note that this problem is only apparent in Flag when using a non-global flag. Since Flag doesn't need a Session ID for global flags. It's simple enough to just enable the "bookmarks" flag that comes with the module for anonymous users to reproduce the problem.

quicksketch’s picture

Status: Active » Needs review
FileSize
1.53 KB

This might do the trick. It should populate the $_COOKIE variable so that Session API can do its check.

loparr’s picture

Hello,
I applied this patch to dev version 7x1x dev. I had to set cookie time less because after clearing the cache in drupal, tha changes were visible after cookie expiration.
Hovewer, this is working so far with anonymous users and cache enabled.
Thank you.

Olarin’s picture

Status: Needs review » Reviewed & tested by the community

Patch in #6 seems to be clean and sensible and works as expected for me with latest releases of Flag and Session API.

Jarviss’s picture

hachreak’s picture

It's possible to port this patch also for 6.x-1.x module version?

Best,
hachreak

Exploratus’s picture

I am guessing this hasnt been commmited, I am hving issues with pages with user specific flags rendering no cache.

Drupa1ish’s picture

Big thanks @quicksketch! #6 works also with https://drupal.org/project/drupalchat

Exploratus’s picture

seems to work for me to.

quicksketch’s picture

Thanks for all the confirmations guys! I feel like this patch may need explanation as to how it works in order to be accepted by the maintainer.

+function session_api_init() {
+  // Set a cookie via JavaScript to check if anonymous users support cookies.
+  if (user_is_anonymous()) {
+    drupal_add_js("document.cookie = 'session_api_available=1; path=/';", array('type' => 'inline'));
+  }
 }

What this code is doing is setting a cookie via JavaScript. Why JavaScript instead of just setting a value in $_SESSION, $_COOKIE or setcookie()? Because if you set a value using any of those methods it requires sending a Set-Cookie HTTP Header to the client from Drupal. Using this header will disable all caching, because the user's browser is the intended recipient of the header.

So by using JavaScript instead, we can serve the exact same page to all anonymous users. The cookie will be set by JavaScript once the page has been loaded, and subsequent requests sent by the user will set the value in the $_COOKIE variable.

Drupa1ish’s picture

+1

adammalone’s picture

Are we able to get some movement on this jhedstrom?

a.ross’s picture

Version: 7.x-1.0-beta3 » 7.x-1.x-dev
Status: Reviewed & tested by the community » Needs work
+++ b/session_api.module
@@ -8,20 +8,20 @@
+  // Set a cookie via JavaScript to check if anonymous users support cookies.

Perhaps you can include your explanation for using Javascript to set a cookie here.

+++ b/session_api.module
@@ -8,20 +8,20 @@
+    drupal_add_js("document.cookie = 'session_api_available=1; path=/';", array('type' => 'inline'));

Is the path correct when Drupal is installed in a subfolder?

Also, this patch needs to be rerolled against -dev and it causes a test failure.

a.ross’s picture

Status: Needs work » Needs review
FileSize
1.26 KB

Re-roll

Status: Needs review » Needs work

The last submitted patch, session_api_nophpsession-1492622-18.patch, failed testing.

a.ross’s picture

This should do it. I'm just not exactly sure what "fooling session_api_get_sid()" was supposed to do.

a.ross’s picture

Status: Needs work » Needs review
a.ross’s picture

Status: Needs review » Needs work
+++ b/tests/session_api_test.module
@@ -24,6 +23,9 @@ function session_api_test_menu() {
+  // Make sure Session API thinks the client supports cookies.
+  $_COOKIE = array('session_api_test' => 'test');
+

The problem here is that cURL doesn't support JavaScript, so the cookie won't actually be set client-side and re-used for the next request. This should be done more elegantly.

Also this exposes an issue with this solution: clients that have JavaScript disabled won't be compatible with Session API. While that may be rare, it would be better to make the cookie initialization method configurable.

a.ross’s picture

Title: Session API Prevents Page Cache » Option to initiate Session API with JS
Category: bug » feature

This should be an option as mentioned. I'm just wondering if it would also make sense to allow for "lazy-initializing" the session with JS, as currently happens with the Set-Cookie header.

Pros of using JS in the way proposed:

  • Keeps pages for anonymous users cachable
  • Starting the session after the first page load would reduce the chance of the bad UX where Session API is unavailable at first.

Cons:

  • Doesn't degrade gracefully as it requires JS to work
a.ross’s picture

Issue summary: View changes

Altered formatting for issue's queue link.

Jibus’s picture

In my opinion, making session api works with anonymous users cachable would be great. I guess that most Drupal site use cachable page in order to earn performance. So it's would be a very good feature.

For people who disable JS, i guess session api won't be the first problem, but all "jQuery package" that almost all developpers use in their website.

It would be conveniant to have the cookie initialization method configurable (#22) with two options :

- Set the cookie through Javascript (works with anonymous user on cachable page)
- Set the cookie through the server

drupalz001’s picture

Issue summary: View changes

Before applied the patch, i have the similar issue which is when the 'bookmark flag' is flagged by an anonymous user, all the pages(fresh pages, havent been saved by boost module) i visited after it will not be saved by the boost.

After applied the patch, all the pages will be saved by the boost. But i have a problem here, the page with flagged(bookmarked) status is always showing 'bookmarked' for all the anonymous users who visited the cached page, even another anonymous user unflagged it.

I've no idea how to update the flag status alone, any ideas?