Problem/Motivation
We are caching a page in varnish under the same cid for authenticated and anonymous users. This page contains an (AJAX) add to cart form which creates the following issue:
1. Let's start with an empty varnish cache and empty {cache_form}.
2. As uid0 go to the page. The add to cart form gets cached in {cache_form} without a #cache_form
attribute (see form_set_cache()
) and therefore without a #authcache_immutable
attribute (see authcache_form_cacheobject_presave()
). The page html gets cached in varnish, the form_build_id in it.
3. As uid0 I reload the page. I get the page with the form_build_id. When I change product attributes, the AJAX fires. authcache_form_cacheobject_load()
runs but since there's no #authcache_immutable
set, it does not change the form. The form works as it should.
4. Now I log in and go to the same page. Logged in users are still cached by varnish so I get the html (with the same form_build_id as uid0) from varnish.
5. I try to change product attributes. AJAX fires, form_get_cache()
fetches the form from the cache and just like with the uid0 case, authcache_form_cacheobject_load()
does not do anything with it. So there's no #cache_token
on the form, which will break fetching $form_state in form_get_cache()
. I get an empty AJAX response.
Note that this only happens if the page gets cached in varnish for an uid0 request. If a logged in user triggers varnish caching, uid0 can still use the add to cart form since drupal_get_token()
in authcache_form_cacheobject_load()
and drupal_valid_token()
in form_get_cache()
works for uid0 users.
Proposed resolution
Always set $object->data['#authcache_immutable'] = TRUE;
in authcache_form_cacheobject_presave()
(even for forms without #cache_token
).
Comment | File | Size | Author |
---|---|---|---|
#18 | interdiff.txt | 2.14 KB | znerol |
#18 | 2813885-18.diff | 4.4 KB | znerol |
#14 | interdiff.txt | 718 bytes | znerol |
#14 | 2813885-12.diff | 5.06 KB | znerol |
#10 | 2813885-9.patch | 5.06 KB | znerol |
Comments
Comment #2
czigor CreditAttribution: czigor commentedFirst go, without updating related comments.
Comment #3
czigor CreditAttribution: czigor commentedComment #4
czigor CreditAttribution: czigor commentedComment #5
czigor CreditAttribution: czigor commentedTested this and works. Added a comment.
Comment #6
czigor CreditAttribution: czigor commentedComment #7
czigor CreditAttribution: czigor commentedComment #8
czigor CreditAttribution: czigor commentedComment #9
znerol CreditAttribution: znerol commentedThis looks like a follow-up on #2702423: Commerce Add to Cart Form ajax and ESI / Varnish fails.
Comment #10
znerol CreditAttribution: znerol commentedI think you are right. What if we move the whole immutability-flag-business into one place (
authcache_form_form_alter
)? It might help people to better understand what is actually going on.Comment #14
znerol CreditAttribution: znerol commentedComment #16
czigor CreditAttribution: czigor commentedThis has come one level up. Shouldn't this be still inside the authcache_page_is_cacheable() condition?
Otherwise moving the logic to the form_alter() makes sense to me.
Comment #17
znerol CreditAttribution: znerol commentedThere is a check for
authcache_page_is_cacheable()
inside_authcache_form_after_build()
anyway. So I figured we might just drop that condition here.Comment #18
znerol CreditAttribution: znerol commentedMaybe it really does not make much sense to modify that logic. But maybe move the immutable flag stuff (form cache issues) such that the form token stuff (CSRF issues) is close together.
Comment #19
czigor CreditAttribution: czigor commentedLooks good to me!
Comment #20
das-peter CreditAttribution: das-peter at Cando commentedLooks good to me. On my site everything seems to work just fine with the patch.
And I like it that it consolidates things.
Only nitpick I found is in an untouched part:
assaciated -> associated
So I'd say let's get this in :)
Comment #22
znerol CreditAttribution: znerol commentedThanks taking the time to report, test and fix this issue.