Use iframe/javascript to set session cookie. Long term goal is anonymous user & ajax shopping cart. Use tricks learned from stats to accomplish this.

Order of operation
html downloaded, iframe loaded, ajax cart loaded. The iframe needs to set a trigger to load the cart via ajax.

Alt:
use javascript to check for session cookie, if none found, go get one from server; once session is in place load cart via ajax.

CommentFileSizeAuthor
#12 boost-586210.patch8.29 KBmikeytown2
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

douglas.a.hatch’s picture

This would be a great feature! Subscribing.

animammal’s picture

This would be Ideal! I'd be very interested to see how this progresses. Unfortunatly I don't have the know how to help much but I can test.

asak’s picture

+1 for this one.

I'm invetigating caching options which support ubercart anon. carts - and this would be ideal!

threading_signals’s picture

Subscribing. Also, how does Boost affect admin boosted pages? Are anonymous or authenticated users able to view those pages, or does Drupal check the role of the user first? I am trying to determine this before using the exclude path settings, thank you.

mikeytown2’s picture

@vividgates
/admin never gets cached; if an anonymous user can't visit the page, it never gets cached; if the page returns anything other then a 200, as an anonymous user, it doesn't get cached. In short boost is fairly smart in this regard.

douglas.a.hatch’s picture

Mikey, is this feature still on the Boost roadmap? I've got another feature on my site, which I think would depend on this same session cookie. It's one of those boxes that calculates on the fly how much more a customer needs to purchase to get FREE shipping. Here's an example:

http://chunkybling-sandbox.com/interchangeable-watches/watch-bands/test-...

To make this work, I need to query the cart subtotal at page load. Do you know of a way to do this from within a Boosted page that wouldn't require the session cookie? Thanks!

torgosPizza’s picture

Subscribing.

This type of functionality is necessary in order to serve Boost-ed Ubercart product pages; since the uc_add_cart_item() function requires a cookie be set that contains the $_SESSION['uc_cart_id'] variable.

I'm investigating the possibility of a javascript function that triggers an AJAX callback that sets a cookie in PHP. This seems to be the only way to do this without downloading the Cookie plugin for jQuery, for example - although perhaps that could be made an option for Boost down the road to solve this issue.

Thoughts? (This is an important issue for us, as www.rifftrax.com is an e-commerce site that gets enough traffic that Boost is heavily used and needed. See #679422: hook_exit() causes Ubercart "Add to Cart" to fail)

EDIT to add, what about a new hook, something like hook_boost_cookie() that is a counterpart to hook_boost_preprocess()? (Either that or each module could implement its own boost_preprocess hook to add its own info.) This approach would allow each module to essentially add the name of a session var to an array and have boost set them all individually. So for Ubercart's uc_cart.module, something like:

function uc_cart_boost_cookie() {
  return array('uc_cart_id' => uc_cart_get_id());
}

which gets invoked when the page is created and cached. The resulting source code served by Apache would be as described above: an iframe/javascript/ajax combination that does the actual dirty work of setting all the cookies that were initialized. But this way, it would just be the one iFrame as opposed to on a per-module basis as they require it.

torgosPizza’s picture

Here's how I was able to implement it for Ubercart: http://drupal.org/node/679422#comment-2452874

It's essentially the way I would do it with a new Boost hook. Perhaps hook_boost_cookie() is wrong, since these are $_SESSION vars I'm talking about, but the idea is still the same... I'll work on a patch to Boost this weekend if I get some time.

mikeytown2’s picture

Going to check for session ID via javascript & if none found get SESS*** Cookie from server.

mikeytown2’s picture

This sucks... the session cookie is not readable from javascript due to httponly flag
http://en.wikipedia.org/wiki/HTTP_cookie#Cookie_theft
It's probably a good thing.

So it looks like no matter what I have to hit the server to make sure the session cookie is set. Here are some ideas
http://insanesecurity.wordpress.com/2007/08/01/httponly-vs-xmlhttprequest/ - More black-hat then I like.
Which leaves me with a custom URL that does a session bootstrap for each page request
http://api.drupal.org/api/function/_drupal_bootstrap/6
Looking at this, it looks like I can do this in an iframe/object

    include_once './includes/bootstrap.inc';
    drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
    echo "Session Check In";

I might want to skip DRUPAL_BOOTSTRAP_ACCESS and saving 1 query; but thats not critical ATM. This should probably be placed at the top of the page, right after the start of the body tag.

torgosPizza’s picture

Yeah, I think this idea is solid. I'd love to test it. Might also make sure you wrap it in a condition that looks for the cookie first (perhaps DRUPAL_UID or something? Maybe configurable...)

One thing I would consider is a setup similar to that of the "don't boost these URLs" textfield that would be used for "force a session on these pages." Because a) not everyone will need this functionality and b) those that *do* may only need it on a handful of pages. For our site, it's anything that has products on it, which we could summarize thusly:

/rifftrax*
/dvd*
/ondemand*
etc...

I'll read up more on your idea and will be glad to test any solutions you come up with.

mikeytown2’s picture

Status: Active » Needs review
FileSize
8.29 KB

Here's the first stab at it, cookie only gets set if the page is from the boost cache. Also due to the httponly flag being set for the session cookie, I send a cookie called boost-session-ready with the unix time as the value. I also set the session variable like so, to force the session cookie.

$_SESSION['boost_give_user_session'] = mt_rand();

Configuration on what pages get the iframe/object is done at the bottom of the "Boost advanced settings" section.

geerlingguy’s picture

+1 / subscribe. Can't test right now, though.

chriscalip’s picture

Patch is up and running on a live site www.drifire.com

drupal boost, ajax_regions, breadcrumb_blocks

Some IE error's in the boost_html_object_load return html string

Original html code

<div style="width:1px; height:1px; border:0px; position:absolute; top:-1000px; z-index:10;">
  <!--[if IE]>
    <object classid="clsid:25336920-03F9-11CF-8FD0-00AA00686F13" data="some.html"></object>
    <object classid="clsid:25336920-03F9-11CF-8FD0-00AA00686F13" type="text/html" data="' . $dest . '" style="width:1px; height:1px; border:0px; position:absolute; top:-1000px; z-index:10;"></object>
  <![endif]-->
  <!--[if !IE]> 
    <-->
    <object data="' . $dest . '" style="width:1px; height:1px; border:0px; position:absolute; top:-1000px; z-index:10;"></object>
    </object>
</div>

Updated Working Code:

<div style="width:1px; height:1px; border:0px; position:absolute; top:-1000px; z-index:10;">
  <!--[if IE]>
    <object classid="clsid:25336920-03F9-11CF-8FD0-00AA00686F13" data="some.html"></object>
    <object classid="clsid:25336920-03F9-11CF-8FD0-00AA00686F13" type="text/html" data="' . $dest . '" style="width:1px; height:1px; border:0px; position:absolute; top:-1000px; z-index:10;"></object>
  <![endif]-->
  <!--[if !IE]> 
    <object data="' . $dest . '" style="width:1px; height:1px; border:0px; position:absolute; top:-1000px; z-index:10;"></object>
  <![endif]-->
</div>
mikeytown2’s picture

Back when I wrote this patch ajaxify regions wasn't a good option; now it is. Looking at your site; the cookie is currently getting set by ajaxify regions. And after some debugging with iframes/objects I would prefer using ajax to set the cookie.

Anyway I don't see "boost-set-session-cookie.php" getting hit in the net panel via firebug.

If you end up caching the ajaxify regions then something else needs to be done

AlexisWilke’s picture

Just thinking, at the top of my head...

Wouldn't all those cases be resolved by catching the POST?

I think there is a problem with the CAPTCHA because of the session duration. Although we can just remove the DELETE of the session and thus never had a CAPTCHA out of date...

db_query('DELETE FROM {captcha_sessions} WHERE timestamp < %d', time() - 60*60*24);

But that does not automatically resolve the cache problem for all forms. What I'm thinking is that forms can be cached for a long time as long as their are not POSTed. Once POSTed, they should be deleted from the cache. I'm not too sure, but I thought I saw something of the sort in Boost already. Am I wrong? If so, I think we should try to determine why it fails in some situations? In case of the CAPTCHA, that DELETE is the main problem... if the CAPTCHA deletes the session before the page cache in Boost is deleted, then the page is not working for anonymous users anymore. Maybe we could make use of the form_id information to have CAPTCHA request boost to delete the cache whenever it deletes a session. That way, the problem would be solved.

Thank you.
Alexis Wilke

torgosPizza’s picture

Alexis, I think you posted to the wrong Issue thread.

AlexisWilke’s picture

torgosPizza,

I guess that the CAPTCHA session is not a $_SESSION, indeed... it's just in the form. So that would be a different problem. Hmmm...

Well, at least I'm subscribed to this issue. 8-)

Alexis

torgosPizza’s picture

Alexis, I'm not sure if you're having the same problem this Issue talks about, unless I'm missing something. We are trying to get session cookies SET (not deleted) so that things such as Ubercart will work. Since Ubercart requires that a session cookie (or at least, a $_SESSION) be set, Boost won't do this by default - which is actually a good thing because you don't want your site to set sessions as this will destroy any reverse-proxy caching you might have enabled.

So basically the thought is to use Ajax (or Ahah) to set a Session Cookie asynchronously so that things like Ubercart will work, without breaking Boost or other caching.

Fabianx’s picture

I've used a different approach on one site:

Exclude cart, cart/* from Boost.

Have all producs POST to /cart.

Then on the cart/ page set a little cookie with the number of products via JS.

On the normal pages, have Cart and replace it in JS with "Cart (1)" or whatever.

Works like a charm.

JS Cookies really is the way to go if you have

* small data set

and need really high performance.

An iframe often is not an option as the load on the server is almost the same as if the page was not boosted.

What however could work:

Add: boost_variable.php

- Just bootstrap to stage database (and authorize SESSION of course).

- boost_variable.php is giving back a JSON array of variable set data for this SESSION.

- Data is set via cache_set / cache_get to make full use of memcache, etc.

- Custom hooks can then set data on the server for certain events (product added to cart, etc.)

- Or for certain sections

Works also great with core cache and cache clear all (as data is cached, no stale data is served).

Best Wishes,

Fabian

ioanmar’s picture

subscribe