2

Setup - We have Varnish in front of three drupal backend server. Varnish is serving as a cache and load balancer. Load balancer is using round robin director. It also does the device detection together with a drupal module (https://www.drupal.org/project/mobile_switch_varnish) to switch between the desktop and mobile theme.

device- detection code (vcl) is below -

sub vcl_recv {
  call identify_device;
}

sub identify_device {
    unset req.http.X-UA-Device;
    set req.http.X-UA-Device = "pc";

    # Handle that a cookie may override the detection alltogether.
    if (req.http.Cookie ~ "(?i)X-UA-Device-force") {
        /* ;?? means zero or one ;, non-greedy to match the first. */
        set req.http.X-UA-Device = regsub(req.http.Cookie, "(?i).*X-UA-Device-force=([^;]+);??.*", "\1");
        /* Clean up our mess in the cookie header */
        set req.http.Cookie = regsuball(req.http.Cookie, "(^|; ) *X-UA-Device-force=[^;]+;? *", "\1");
        /* If the cookie header is now empty, or just whitespace, unset it. */
        if (req.http.Cookie ~ "^ *$") { unset req.http.Cookie; }
    } else {
        if (req.http.User-Agent ~ "\(compatible; Googlebot-Mobile/2.1; \+http://www.google.com/bot.html\)" ||
            (req.http.User-Agent ~ "iPhone" && req.http.User-Agent ~ "\(compatible; Googlebot/2.1; \+http://www.google.com/bot.html")) {
            set req.http.X-UA-Device = "mobile-smart"; }
        elsif (req.http.User-Agent ~ "(?i)ipad")        
                    { set req.http.X-UA-Device = "mobile-tablet"; }
        elsif (req.http.User-Agent ~ "(?i)ip(hone|od)") 
                    { set req.http.X-UA-Device = "mobile-smart"; }
        /* how do we differ between an android phone and an android tablet?
           http://stackoverflow.com/questions/5341637/how-do-detect-android-tablets-in-general-useragent */
        elsif (req.http.User-Agent ~ "(?i)android.*(mobile|mini)") 
                    { set req.http.X-UA-Device = "mobile-smart"; }
        // android 3/honeycomb was just about tablet-only, and any phones will probably handle a bigger page layout.
        elsif (req.http.User-Agent ~ "(?i)android 3")              
                    { set req.http.X-UA-Device = "mobile-tablet"; }
        /* Opera Mobile */
        elsif (req.http.User-Agent ~ "Opera Mobi")                  
                    { set req.http.X-UA-Device = "mobile-smart"; }
        // May very well give false positives towards android tablets. Suggestions welcome.
        elsif (req.http.User-Agent ~ "(?i)android")         
                    { set req.http.X-UA-Device = "mobile-tablet"; }
        elsif (req.http.User-Agent ~ "PlayBook; U; RIM Tablet")         
                    { set req.http.X-UA-Device = "mobile-tablet"; }
        elsif (req.http.User-Agent ~ "hp-tablet.*TouchPad")         
                    { set req.http.X-UA-Device = "mobile-tablet"; }
        elsif (req.http.User-Agent ~ "Kindle/3")        
                    { set req.http.X-UA-Device = "mobile-tablet"; }
        elsif (req.http.User-Agent ~ "Touch.+Tablet PC")           
                    { set req.http.X-UA-Device = "mobile-tablet"; }
        elsif (req.http.User-Agent ~ "Mobile.+Firefox")     
                    { set req.http.X-UA-Device = "mobile-other"; }
        elsif (req.http.User-Agent ~ "^HTC" ||
            req.http.User-Agent ~ "Fennec" ||
            req.http.User-Agent ~ "IEMobile" ||
            req.http.User-Agent ~ "BlackBerry" ||
            req.http.User-Agent ~ "BB10.*Mobile" ||
            req.http.User-Agent ~ "GT-.*Build/GINGERBREAD" ||
            req.http.User-Agent ~ "SymbianOS.*AppleWebKit") 
                    {
            set req.http.X-UA-Device = "mobile-smart";
                    }
        elsif (req.http.User-Agent ~ "(?i)symbian" ||
            req.http.User-Agent ~ "(?i)^sonyericsson" ||
            req.http.User-Agent ~ "(?i)^nokia" ||
            req.http.User-Agent ~ "(?i)^samsung" ||
            req.http.User-Agent ~ "(?i)^lg" ||
            req.http.User-Agent ~ "(?i)bada" ||
            req.http.User-Agent ~ "(?i)blazer" ||
            req.http.User-Agent ~ "(?i)cellphone" ||
            req.http.User-Agent ~ "(?i)iemobile" ||
            req.http.User-Agent ~ "(?i)midp-2.0" ||
            req.http.User-Agent ~ "(?i)u990" ||
            req.http.User-Agent ~ "(?i)netfront" ||
            req.http.User-Agent ~ "(?i)opera mini" ||
            req.http.User-Agent ~ "(?i)palm" ||
            req.http.User-Agent ~ "(?i)nintendo wii" ||
            req.http.User-Agent ~ "(?i)playstation portable" ||
            req.http.User-Agent ~ "(?i)portalmmm" ||
            req.http.User-Agent ~ "(?i)proxinet" ||
            req.http.User-Agent ~ "(?i)sonyericsson" ||
            req.http.User-Agent ~ "(?i)symbian" ||
            req.http.User-Agent ~ "(?i)windows\ ?ce" ||
            req.http.User-Agent ~ "(?i)winwap" ||
            req.http.User-Agent ~ "(?i)eudoraweb" ||
            req.http.User-Agent ~ "(?i)htc" ||
            req.http.User-Agent ~ "(?i)240x320" ||
            req.http.User-Agent ~ "(?i)avantgo") 
                    {
            set req.http.X-UA-Device = "mobile-other";
                    }
    }
}


sub vcl_hash {
    #Default Hash
    hash_data(req.url);
   if (req.http.host) {
        hash_data(req.http.host);
    } else {
        hash_data(server.ip);
    }

    #hash based on device type
    if (req.http.X-UA-Device ~ "^mobile") {
        hash_data(req.http.host+req.http.X-UA-Device);
    }

    //return (hash);
}

**PHP code (written in module) which switch the theme is below -** 

/**
 * Implements hook_custom_theme()
*/
function yt_switchtheme_custom_theme(){
  // Detect if this is a mobile device.

  if (isset($_SERVER['HTTP_X_UA_DEVICE']) && strstr($_SERVER['HTTP_X_UA_DEVICE'], 'mobile')) {

    // Bail if this is an admin page and we don't respect admin pages.
    if (path_is_admin(current_path()) && !variable_get('mobile_switch_varnish_use_on_admin_pages', FALSE)) {
      return;
    }
    // Fetch the device type from the server variable.
     $device_type = substr($_SERVER['HTTP_X_UA_DEVICE'], 7);
    // If the mobile theme for device is empty (unlikely) or set to 'default' then return the default mobile theme.
    if (!variable_get('mobile_switch_varnish_theme_' . $device_type, 'default') || variable_get('mobile_switch_varnish_theme_' . $device_type, 'default') == 'default') {
      return variable_get('mobile_switch_varnish_theme_default', 'mobile_jquery');
    }
    // Else it's been set specifically; use this theme setting instead.
    else {
      return variable_get('mobile_switch_varnish_theme_' . $device_type, 'default');
    }
  }
}

Now problem is usually it serves desktop theme and mobile theme right on desktop and mobile device respectively but sometime it serve the mobile theme on desktop and vice-versa.

How can I stop it from happening?

-1

I have the same problem, I'm going to try using this: https://www.drupal.org/project/mobile_switch_varnish hope it works...

  • Have you tried this solution yet? If so, can you report if/how it soves this problem? – mpdonadio Aug 31 '15 at 21:18
  • We are already using above module for switching the theme based on http header 'HTTP_X_UA_DEVICE' which is set by device-detection.vcl file. But the problem is not solved. Some time it shows mobile theme on desktop and vice-versa. So i am looking on theory behind it. What cause this issue.? – ashish kushwah Sep 1 '15 at 4:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.