Hi,

I've installed authcache following the steps described here: Tutorial: Commerce Kickstart 2 and Authcache 2.

I've also followed this and removed tokens for commerce_cart_add_to_cart_form_*, and restricted this only to unprivileged authenticated users.

Everything seems to work fine for anonymous users, but caching for authenticated users on pages with forms (add to cart forms with ajax) don't work. If the add to cart form token is not removed, there's no caching. If it is removed, the page is cached but add to cart works only for the initial user (the user that generated the page cache). I.e, if user_A accessed a certain page and then user_B, user_A will be able to add to the cart but user_B won't.

Any idea what might cause this?

Thanks,
Dana

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

znerol’s picture

Thanks for the report. Did you also install and configure the Cache Object API module? Since beta3 this is required to make Ajax forms work for authenticated users.

I realize that the documentation is lacking in this regard.

gdana’s picture

Not before posting this but after working with the authcache debugger at some point a message about cache object appeared so yes, I installed it and it looks like it solved the issue (need to test it a little more to be sure).

You really should add this step to the documentation, this is such a great module... :)

Another small question: if add to cart is an Ajax form, am I right that there's no need to add it to the list of forms of which tokens should be removed as it is cached any way?

Thanks again,
Dana

znerol’s picture

Form Tokens are used to prevent CSRF attacks. As of version beta4 it is not necessary anymore to remove the form token from the add to cart form, due to #2352239: Use base form id for tokens in order to minimize ajax requests on repeated forms (e.g. commerce add-to-cart).

Form Build IDs are used to reference form cache entries and are required for Ajax forms.

So those two things are in fact very different.

gdana’s picture

Hello again,

OK, I think I understand the difference between tokens and build ids.

However, I'm still encountering serious problems with the add to cart forms. The problem now is different and there is a very strange behaviour when adding to cart by an authenticated user: again, assuming there are two users, user_A and user_B. if user_A created the cached page, and user_B adds to his cart from the same page, the first time user_B adds to his cart, it doesn't perform correctly and the product is added to the cart of user_A. After that, adding to the cart performs as expected for that specific add to cart form (i.e., adding the same product a second time works).

This is the message in the debug window:
Status
Cache Status: "HIT"
Speedup: "104,787% increase"
Page Render Time: "9712.52 ms"
Cache Render Time: "9.26 ms"
Page Age: "51 seconds"
Settings
Cache Class: "DrupalDatabaseCache"
Cache CID: "6a905a2/sunday"
Debug Users: [""]
Cache User: "258"
Cache Backends: "authcache_builtin"
Active Backend: "authcache_builtin"
Authcache Key: "6a905a2"
Key props: {"base_root":"example.com","roles":[2],"ajax":true}
P13n Clients: "Ajax"
Active P13n Clients: "Ajax"

Do you know what could possibly be the problem now?

Thanks a lot, again.
Dana

znerol’s picture

I tried to reproduce this with my Commerce Kickstart + Authcache sandbox to no avail. (Use ./scripts/build.sh /path/to/destination/directory to build the distribution).

Please check the following things on your setup:

  • Which exact version of Drupal do you run? Do you use a distribution?
  • Do you see JavaScript errors when that happens?
gdana’s picture

It's 7.36, and no, there are no JavaScript errors when this happens. When adding a product for the first time if the page was cached by another user, the Ajax responds and displays a message that the product was added (and it was, just not to the right user...). After the first addition, it works. So strange.

Regarding reporoducing the problem - I'm sorry, I should have pointed out that It's not Commerce Kickstart. It's a Drupal Commerce website that's been working properly for almost 2 years, except for the fact that certain pages are extremely slow (views with many products and add to cart forms), which is why we are trying to implement Authcache.

Obviously, this is not tested on the live site. We've installed the latest Drupal distribution (7.36) and imported the entire site, and then followed the steps in the tutorial (with a few small additions):

  1. Installed the modules: Authcache, Authcache Ajax, Authcache Builtin Storage Backend, Authcache Comment (and User), Authcache Form, Authcache Personazilation API, Authcache Views. Also installed Authcache Block, Authcache User Cookie and Cache Object API.
  2. Added this to settings.php:
    # Include the Cache Object API Wrapper as a cache backend
    $conf['cache_backends'][] = 'sites/all/modules/cacheobject/cacheobject.inc';
    
    # Set the cache class for the form cache to 
    $conf['cache_class_cache_form'] = 'CacheObjectAPIWrapper';
    
    # Optionally set the underlying cache class
    $conf['cacheobject_class_cache_form'] = 'DrupalDatabaseCache';
    $conf['cache_backends'][] = 'sites/all/modules/authcache/authcache.cache.inc';
    $conf['cache_backends'][] = 'sites/all/modules/authcache/modules/authcache_builtin/authcache_builtin
    .cache.inc';
    
    
  3. Enabled authcache for anonymous and authenticated users.
  4. Enabled authcache to the shopping cart view.
  5. Enabled authcache to the shopping cart view block.
  6. Removed form tokens from: search_form, search_block_form, search_api_page_search_form (but not commerce add to cart, following your previous explanation).

I really don't know what to think, it worked so well after adding the Cache Object module but then stopped, after some (seemingly) unrelated changes made to the site and the server. Is there some kind of logging I could add that would clarify things a little?

Thanks, your help is very much appreciated.

znerol’s picture

There was a similar issue some time ago with the comments form: #2307555: Comments intermittently misattributed.

Could you describe a bit how you add-to-cart form is configured? Are there any additional modules involved which might alter/extend that form? Do you use custom line items?

gdana’s picture

Hi,

Yes, there are a few modules altering and extending.

The first is Commerce Cart Ajax, and the other is this code (custom module copied from here):


function ajax_cart_form_alter(&$form, &$form_state, $form_id) {
  // Add ajax property to Add to Cart button
  if (strstr($form_id, 'commerce_cart_add_to_cart_form')) {
    $form['submit'] = array(
      '#value' => t('Add to Cart'),
			'#weight' => 50,
      '#type' => 'submit',
      '#ajax' => array(
        'callback' => 'ajax_cart_form',
        'wrapper' => 'block-commerce-cart-cart',
        'effect' => 'fade',
        'progress' => array('type' => 'throbber', 'message' => ''),
      ),
    );
    $form['#submit'][] = 'ajax_cart_form_rebuild_submit';
  }
}

function ajax_cart_form_rebuild_submit($form, &$form_state){
  $form_state['rebuild'] = TRUE;
}

function ajax_cart_form($form, &$form_state){
  global $user;
  $order_id = commerce_cart_order_id($user->uid);
  $cart =  commerce_embed_view('commerce_cart_block', 'default', array($order_id));
  $commands = array();

  $commands[] = ajax_command_replace('#block-commerce-cart-cart .view-commerce-cart-block', $cart);
  $commands[] = ajax_command_replace('#block-commerce-cart-cart .cart-empty-block', $cart);
  $commands[] = ajax_command_after('.'.$form['#attributes']['class'][1],theme('status_messages'));
  return array('#type' => 'ajax', '#commands' => $commands);
}

Other than that, we're not using custom line items (assuming you mean this).

Thanks,
Dana

gdana’s picture

One more thing: correct me if I'm wrong but if I recall the code correctly when this did work, and if I understand your explanation about the form token using the form build id, shouldn't the form html include a token with the build id?

This is the current code:

<form class="commerce-add-to-cart commerce-cart-add-to-cart-form-12904" action="/products/90237" method="post" id="commerce-cart-add-to-cart-form-12904" accept-charset="UTF-8"><div><input type="hidden" name="product_id" value="12904" />
<input type="hidden" name="form_build_id" value="form-BIPQKAMmbxugkl99lK0Y96T6WsT3thh9RWUlamdMb_w" />
<span  class="authcache-ajax-frag" data-authcache-ajax-src="/sites/all/modules/authcache/modules/authcache_p13n/frontcontroller/authcache.php?a=commerce_cart_add_to_cart_form&amp;r=frag/form-token&amp;o[q]="></span><input type="hidden" name="form_id" value="commerce_cart_add_to_cart_form_12904" />
<div class="display-price"><div id="edit-display-price" class="form-item form-type-item">
...
<input type="submit" id="edit-submit" name="op" value="Add to cart" class="form-submit" /></div></form>
znerol’s picture

I think this is actually a bug, in fact I believe it is very similar to the one I've linked in #7. It looks like commerce cart does the same thing like the comment module, i.e. store a reference to the user in a value field (see commerce_cart_add_to_cart_form()). That gets serialized into the form state on Ajax enabled forms (i.e. form caching is on). That cached form / form state combination will then be duplicated and reused for other users, but the uid will remain the same.

znerol’s picture

FileSize
777 bytes

Attached is a module which I've extracted from Authcache Comment and adapted to the commerce cart case.

I'll follow up with a proper patch + test cases as soon as time permits.

gdana’s picture

Hey,

Great, the first few tests I've done look good and it seems the module solves the issue. Obviously will have to test it a lot more.

Thanks a lot for this and for your fantastic support and very quick responses.

Have a nice weekend...
Dana

  • znerol committed a7bc1f6 on 7.x-1.x
    Issue #2475503 by znerol, gdana: Ajax add to cart works only for initial...
znerol’s picture

Committed an initial skeleton of the new module. This is in order to make the test-bot pull in the new dependencies (commerce). This commit does not yet contain the necessary fix.

  • znerol committed 7c4b7ce on 7.x-1.x
    Revert "Issue #2475503 by znerol, gdana: Ajax add to cart works only for...
znerol’s picture

Version: 7.x-2.0-beta4 » 7.x-2.x-dev
Category: Support request » Bug report
Priority: Normal » Critical
Status: Active » Needs review
FileSize
1.85 KB

The module as a patch. Still needs tests, but they are currently blocked on #2481289: Prevent that cache/Ajax enabled forms with value elements are cached by default.

znerol’s picture

znerol’s picture

Fix test. We need a cardinality > 1 in order to trigger attributes (Ajax) on the add-to-cart form.

The last submitted patch, 18: ajax_add_to_cart_works-2475503-18-TEST-ONLY.patch, failed testing.

  • znerol committed e200422 on 7.x-2.x
    Issue #2475503 by znerol, gdana: Ajax add to cart works only for initial...
znerol’s picture

Many thanks @gdana for taking the time to report this issue.

znerol’s picture

Status: Needs review » Fixed
gdana’s picture

Can you please explain the exact procedure because the patching fails when installing the initial module (in #11) and then applying the patch.

Thanks,
Dana

znerol’s picture

The fix is included in the latest dev version. Please use that for testing purposes. I'm preparing to release another beta next week.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.