Problem/Motivation
Caching is disabled if an Ajax enabled form (constructed with the Webform module) is on the page. This is due to the webform module storing the user id of the currently logged in user in a value element (see webform_client_form()).
Steps to reproduce
Preconditions: Authcache including Authcache Debug installed and properly configured. Webform and Webform Ajax installed and enabled.
- Add a new Webform.
- Add any input field.
- In Form settinsg enable Ajax mode.
Verify that the following message is reported by the debug widget if an authcache enabled user (or anonymaus) accesses the form:
Value element contained in the cacheable form webform_client_form_X. Please enable a suitable Authcache integration module for that form or file a support
Proposed resolution
Write an integration module similar to Authcache Commerce capable of stripping the user-id value from the webform from within a form_alter and restoring it from within a validation callback prior to form submission. Then mark $form['details']['uid'] as cacheable. Also mark $form['details']['nid'] cacheable (no additional code is required in this case because the nid does not depend on the currently logged in user).
Remaining tasks
User interface changes
API changes
Original report
How do you set up caching for anonymous users? I can't get it to work.
This is my configuration for caching:
<?php
/* Redis configuration */
$conf['redis_client_interface'] = 'PhpRedis'; // Can be "Predis".
$conf['redis_client_host'] = '****'; // Your Redis instance hostname
$conf['redis_client_port'] = ****;
$conf['lock_inc'] = 'sites/all/modules/redis/redis.lock.inc';
$conf['path_inc'] = 'sites/all/modules/redis/redis.path.inc';
$conf['cache_backends'][] = 'sites/all/modules/redis/redis.autoload.inc';
$conf['cache_default_class'] = 'Redis_Cache';
$conf['redis_client_password'] = '****';
/* Cacheobject configuration */
$conf['cache_backends'][] = 'sites/all/modules/cacheobject/cacheobject.inc';
$conf['cache_class_cache_form'] = 'CacheObjectAPIWrapper';
$conf['cacheobject_class_cache_form'] = 'DrupalDatabaseCache';
/* Authcache configuration */
$conf['cache_class_cache_authcache_key'] = 'Redis_Cache';
$conf['page_compression'] = 1;
$conf['page_cache_maximum_age'] = 600;
/* The following needs to be disabled for Varnish */
# $conf['authcache_builtin_cache_without_database'] = TRUE;
# $conf['cache_backends'][] = 'sites/all/modules/authcache/authcache.cache.inc';
# $conf['cache_backends'][] = 'sites/all/modules/authcache/modules/authcache_bu$
/* Varnish configuration */
$conf['cache_backends'][] = 'sites/all/modules/varnish/varnish.cache.inc';
$conf['cache_class_cache_page'] = 'VarnishCache';
$conf['page_cache_invoke_hooks'] = FALSE;
$conf['omit_vary_cookie'] = TRUE;
?>| Comment | File | Size | Author |
|---|---|---|---|
| #20 | authcache-element-value-debug-2460953.patch | 1.15 KB | firewaller |
| #19 | authcache_webform_ajax.zip | 6.43 KB | jalike |
Comments
Comment #1
znerol commentedAre you trying to use varnish for caching? Is authcache working for authenticated users and not for anonymous users? Or is it not working at all? Did you follow a specific guide / blog post in order to reach the point you are stuck right now? If yes, then please post links pointing to that resources.
Comment #2
znerol commentedComment #3
stevendeleus commentedHi, thank you for helping me out. For integration with Redis I used https://www.drupal.org/node/2160133 . The connection with Redis is working and recognized by authcache. For integration of authcache form, I followed the readme of the cacheobject module. I disabled everything Varnish related and the problem persists.
I really can't get basic setup working. Drupal cache always misses. As far as I can tell the problem is with authcache for which page cache has to be disabled. The only reason I need authcache is for forms, to clear the unnecessary tokens that cause page caching to be disabled for sure.
What I think is happening, is that the check for page caching caused by form tokens happens before authcache clears them.
Comment #4
stevendeleus commentedThe culprit is the webform_ajax module. I think it alters the form after authcache removes the token, causing the token to be renewed.
Comment #5
stevendeleus commentedChanging the order of the modules doesn't help or I'm doing it wrong.
Comment #6
stevendeleus commentedFYI:
Comment #7
znerol commentedI guess that may be a similar problem like #2389809: Content load by authcache, and pager with ajax loading content. In that case it would be enough to force the
$form_state['values']['webform_ajax_wrapper_id']to a constant value from within a custom module.Comment #8
znerol commentedOh, stupid me. 7.x-2.0-beta5 does not cache any form which as a value element in it by default. However, the value element here does not contain any user-specific data and can safely be cached. It can be marked as cacheable from within a custom form alter callback like so:
Comment #9
stevendeleus commentedHi, that doesn't help. I tried authcache_element_set_cacheable on webform_ajax_wrapper_id, but the form is not cached. Could I do something more generic to force the cache?
Comment #10
stevendeleus commentedI get this message from authcache_ensure_element_cacheable:
Value element contained in the cacheable form webform_client_form_8. Please enable a suitable Authcache integration module for that form or file a support request.
When I print the element I get:
Comment #11
stevendeleus commentedI found two more elements that needed to be made cacheable, but the problem still persists.
Comment #12
stevendeleus commentedI found the last issue. The form needs to be passed by reference:
Comment #13
stevendeleus commentedComment #14
znerol commentedOh sure! Sorry about that. Is #12 your complete implementation?
Comment #15
stevendeleus commentedNo, this is:
Comment #16
znerol commentedI'm sorry but that is very likely not safe and could lead to weird issues like the commerce cart one fixed in beta5. Take a look at the new Authcache Commerce module to get an idea on how to restore the actual user id from within a validation callback.
Comment #17
znerol commentedAdd a proper issue summary and convert this to a feature request. Patches greatly appreciated.
Comment #18
znerol commentedComment #19
jalike commentedSee proposed solution attached.
Comment #20
firewaller commentedI had some trouble debugging the value elements to get this working, so I passed the element key into the warning message to figure out where to look.
Comment #26
angel.angelio commentedIs authcache_element_set_cacheable() documented anywhere? I saw the same 'error'
And the doctype was not intuitive. I used it because I found this issue.
In my case the error was created from a custom form
Comment #27
znerol commentedDeveloper documentation is truly lacking. The only additional hint you get from the enclosing group heading:
Authcache tries to detect if it is save to cache the rendered markup + state of a form. Regrettably many forms assume that pages are never cached for authenticated users and therefore add some personalized bits here and there to some form elements. Some things are easy to spot when test driving the site manually, e.g. default values (name and email of the user prepopulated in the contact form). Other things are nearly impossible to detect, among them personalized form values (i.e., elements with
type => '#value'). That did lead to weird behavior in the past (#2307555: Comments intermittently misattributed and #2475503: Ajax add to cart works only for initial user).For this reason Authcache flat out refuses to cache a form if there is a value form element on the page unless some contrib/custom code did inspect the element and marked it as cacheable (using
authcache_element_set_cacheable()).Some value form elements do not contain any personalized content, but many do. If you use
authcache_element_set_cacheable()on a value element which contains personalized content, but do not add additional steps which cope with that situation, then you will likely run into issues like those linked above.Comment #28
angel.angelio commentedThanks for the amazing explanation.