Problem/Motivation

The EU Only option is incompatible with page cache. If page cache is enabled, even without a additional caching layer such a Varnish, a user (not) in a EU, could be served a page with(out) the pop-up. The display of the pop-up is set for the HTTP request that put the page in the cache, not the request for which the page is served because it is done in eu_cookie_compliance_page_build().

Proposed resolution

Instead of checking for the visitor country in eu_cookie_compliance_page_build(), provide a non-cacheable menu callback that return the visitor country, and check whether or not to display the pop-up from JavaScript only. The callback should support both the GeoIP and Smart IP modules.

The should be the default behavior of the module has soon as page caching is enabled (ie. the cache variable is true). If page cache is not enabled, the existing behavior could still be used (but switching to the JS based check shouldn't hurt).

Original report by @jrbeeman

As currently designed, this module requires that Drupal bootstrap for every page request, making technologies like Varnish difficult to use in conjunction with the cookie detection.

Solution: Provide a menu callback that returns country information that can then be used by the module JS to determine if the cookie warning should be displayed.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jrbeeman’s picture

Patch attached.

This patch adds a menu callback that returns JSON-formatted data about the country from which the user is visiting and a corresponding option in the module settings for which detection method to use. This feature requires the GeoIP module to be installed.

jrbeeman’s picture

Assigned: jrbeeman » Unassigned
Status: Active » Needs review
svenryen’s picture

There's a suggested fix for Varnish here: https://drupal.org/node/2190719

pbuyle’s picture

Title: Provide a JavaScript-based detection method » The EU Only option is incompatible with page cache
Category: Feature request » Bug report
Issue summary: View changes

The Varnish solution linked in in #3 is to allow Varnish to cache pages when the module is used. Because of the cookie-agreed set in JavaScript, and only consumed in JavaScript, a standard Varnish configuration will not cache the page. But the value of the cookie does not change the content of the page, so it could safely be ignored by Varnish (or other HTTP cache).

This issue is about serving the same cached page to all visitors, regardless of their country. Since Geo-localisation of the visitor is done on the server side, it result is cached. If the UE only setting s enabled (available when the GeoIP or the Smart IP module is enabled), the page could be generated for a user in the EU with the JavaScript code for the pop-up. Then the page will be cached, and when a not from the EU will get the page, the page with the pop-up will be served. Or a page without the pop-up could be cached, then served to a visitor from the EU.

Note that, because alteration of the page to add the pop-up is done in a eu_cookie_compliance_page_build(), I believe the issue to be present even when only the Drupal page cache is used.

pbuyle’s picture

Status: Needs review » Needs work
pbuyle’s picture

Issue summary: View changes
Finn Lewis’s picture

@svenryen: I'm not sure the suggested fix for Varnish at: https://drupal.org/node/2190719 will actually have the desired effect. I could be wrong, but it suggests passing the cookie-agreed cookie through, which (depending on the rest of your Varnish configuration) will usually result in Varnish not caching the page. In my tests that has certainly been the case, so I was interested in the patch above.

@jrbeeman: I liked the look of your patch, but couldn't get it to apply cleanly, so re-rolled against the latest 7.x-1.x-dev. I have tested this somewhat on a server and it seems to be working well, but I have yet to test with a greater variety of IPs from different countries. I also added a variable_get() to enable us to easier alter the array of country codes that we consider EU, (or actually care about), as this may change over time depending on the use case.

Patch attached, will report back when tested further.

@mongolito404
I think you are confirming that this is indeed an issue. Just to clarify my understanding, the patch in the original post and the re-roll attached aims to address this by using a separate callback to Drupal at /eu-cookie-compliance-check (which is not cached by Drupal and can be ignored by Varnish) such that the cached page can decide how to behave depending on the result of this.

svenryen’s picture

Thank you for the re-roll. I will see if I can get this functionality into the 2.x branch. If you can help @finn.lewis , do you have a Varnish environment where I can test my code? I don't have any Varnish set up for now.

Jody Lynn’s picture

This is the patch in 7 with an additional isset to prevent notices we were seeing on cache clear.

@@ -123,7 +123,7 @@ function eu_cookie_compliance_page_build(&$page) {
         'popup_link_new_window' => isset($popup_settings['popup_link_new_window']) ? $popup_settings['popup_link_new_window'] : 1,
         'popup_position' => empty($popup_settings['popup_position']) ? NULL : $popup_settings['popup_position'],
         'popup_language' => $language->language,
-        'popup_eu_only_js' => $popup_settings['eu_only_js'],
+        'popup_eu_only_js' => isset($popup_settings['eu_only_js']) ? $popup_settings['eu_only_js'] : 0,
         'domain' => variable_get('eu_cookie_compliance_domain', ''),
       );
Jody Lynn’s picture

That last patch was bad. New patch and I also removed the whitespace fixes as they were making the patch not apply to 7.x-1.14.

Leeteq’s picture

Priority: Normal » Major
Status: Needs work » Needs review
pbuyle’s picture

drupal_add_http_header('Cache-Control', 'private'); should prevent aching of the JSON by a reverse-proxy cache such a Varnish or CloudFront. Solving the issue mentionned in #4. However, it should be called before drupal_json_output(). The later may trigger a buffer flush and start the HTTP response, which will prevent any additional header to work.

l0ke’s picture

Moved drupal_add_http_header('Cache-Control', 'private'); before drupal_json_output() as noted here #2153799-12: The EU Only option is incompatible with page cache.

I've noticed that value of Drupal.settings.eu_cookie_compliance.domain in eu_cookie_compliance.js is getting cached because it's passed from cachable eu_cookie_compliance_page_build(), so it doesn't work correct.

Proposed solution is to use AJAX callback to get the domain value.

oppure’s picture

Hi thanks for the patch, can you clarify if the fix works only when selecting the javascript based EU only option? If so is it possible to make it work also with smart_ip module? geoip unfortunately can't use cloudflare as location source. Thanks.

clairedesbois@gmail.com’s picture

To do tests, I added code to recover the geoip_debug parameter in the URL to use a IP of my choice (I'm in Canada, the patch doesn't work with my true IP thus the cookie is directly setted).

svenryen’s picture

Assigned: Unassigned » svenryen
SocialNicheGuru’s picture

Status: Needs review » Needs work

did not apply cleanly to newest dev version.

patch -p1 < eu_cookie_compliance-js-check_2153799_15.patch
patching file eu_cookie_compliance.admin.inc
Hunk #1 succeeded at 245 with fuzz 1 (offset 190 lines).
patching file eu_cookie_compliance.module
Hunk #1 FAILED at 19.
Hunk #2 succeeded at 163 with fuzz 1 (offset 47 lines).
Hunk #3 succeeded at 246 (offset 62 lines).
1 out of 3 hunks FAILED -- saving rejects to file eu_cookie_compliance.module.rej
patching file js/eu_cookie_compliance.js
Hunk #2 succeeded at 99 (offset 11 lines).
>~/platforms/7/modules/all/eu_cookie_compliance$ more *e.rej
--- eu_cookie_compliance.module
+++ eu_cookie_compliance.module
@@ -19,6 +19,18 @@
'access arguments' => array('administer EU Cookie Compliance popup'),
'file' => 'eu_cookie_compliance.admin.inc',
);
+ $items['eu-cookie-compliance-domain'] = array(
+ 'title' => 'Return cookie domain',
+ 'page callback' => 'eu_cookie_compliance_domain_json',
+ 'access arguments' => array('display EU Cookie Compliance popup'),
+ );
+ if (module_exists('geoip')) {
+ $items['eu-cookie-compliance-check'] = array(
+ 'title' => 'Check if visit is in EU',
+ 'page callback' => 'eu_cookie_compliance_json',
+ 'access arguments' => array('display EU Cookie Compliance popup'),
+ );
+ }
return $items;
}

svenryen’s picture

Status: Needs work » Fixed

Thank you for the patch, I've added it to -dev. I improved it a little bit so that it would also show the "Thank you"-banner, and also support smart_ip.

  • svenryen committed 40c7558 on 7.x-1.x authored by Calystod
    Issue #2153799 by Jody Lynn, l0ke, Calystod, jrbeeman, finn.lewis,...
svenryen’s picture

Status: Fixed » Closed (fixed)