Upgrade Your Drupal Skills
We trained 1,000+ Drupal Developers over the last decade.
See Advanced Courses NAH, I know EnoughSimple Apache configuration file for mobile device detection
From time to time I get questions about caching strategies and mobile devices. Definitely when you want to create different responses in the back end based on the device AND you have strong caching strategies, things get very tricky.
An example scenario in Drupal (but can relate to any CMS) is where you boost performance by storing the generated pages as static files (see Boost).
These solutions rely heavily on Apache in a way that Apache delivers the static files in case these files exist. Otherwise it passes the request to the CMS.
In order to provide a way to server different responses to mobile devices I created following Apache script:
# Detect if a "device" query parameter is set in the request. # If so, the value for that attribute forces the requesting device type. # If the parameter is available, set a cookie to remember for which device pages have to be generated in subsequent requests. # Assume three categories: # - mobile-high (high end mobile devices) # - mobile-low (low end mobile devices) # - desktop (desktop browser) RewriteCond %{QUERY_STRING} ^.*device=(mobile-high|mobile-low|desktop).*$ RewriteRule .* - [CO=device:%1:.yourdomain.tld:1000:/,E=device:%1,S=2] # now skip 2 RewriteRules till after the user agent detection # If there is no "device" attribute, search for a cookie. # If the cookie is available add ?device=<device-type> to the request RewriteCond %{HTTP_COOKIE} ^.*device=(.*)$ RewriteRule (.*) $1?device=%1 [E=device:%1,S=2,QSA] #now skip till after the user agent detection # If no cookie or device attribute are present, check the user agent by simple user agent string matching (android and iphone only here) RewriteCond %{HTTP_USER_AGENT} ^.*(iphone|android).*$ [NC] RewriteRule (.*) $1?device=mobile-high [E=device:mobile-high,QSA,S=1] # Detect the user agent for lower end phones (nokia, older blackberries, ...) RewriteCond %{HTTP_USER_AGENT} ^.*(nokia|BlackBerry).*$ [NC] RewriteRule (.*) $1?device=mobile-low [E=device:mobile-low,QSA]
This scripts makes sure that every request has an extra "device" query parameter that defines the requesting device (desktop/mobile-high/mobile-low). This information can be used by the back end or any caching mechanisms!
I also added a %{ENV:device} variable so that within the Apache script more logic can be placed based on the device.
Applying to the Boost module
The above snippet works together with Boost by replacing %{server_name} by %{ENV:device}/%{server_name} in the Boost apache configuration.
### BOOST START ### AddDefaultCharset utf-8 <FilesMatch "(\.html|\.html\.gz)$"> <IfModule mod_headers.c> Header set Expires "Sun, 19 Nov 1978 05:00:00 GMT" Header set Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0" </IfModule> </FilesMatch> <IfModule mod_mime.c> AddCharset utf-8 .html AddCharset utf-8 .css AddCharset utf-8 .js AddEncoding gzip .gz </IfModule> <FilesMatch "(\.html|\.html\.gz)$"> ForceType text/html </FilesMatch> <FilesMatch "(\.js|\.js\.gz)$"> ForceType text/javascript </FilesMatch> <FilesMatch "(\.css|\.css\.gz)$"> ForceType text/css </FilesMatch> # Gzip Cookie Test RewriteRule boost-gzip-cookie-test\.html cache/perm/boost-gzip-cookie-test\.html\.gz [L,T=text/html] # GZIP - Cached css & js files RewriteCond %{HTTP_COOKIE} !(boost-gzip) RewriteCond %{HTTP:Accept-encoding} !gzip RewriteRule .* - [S=2] RewriteCond %{DOCUMENT_ROOT}/cache/perm/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_\.css\.gz -s RewriteRule .* cache/perm/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_\.css\.gz [L,QSA,T=text/css] RewriteCond %{DOCUMENT_ROOT}/cache/perm/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_\.js\.gz -s RewriteRule .* cache/perm/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_\.js\.gz [L,QSA,T=text/javascript] # NORMAL - Cached css & js files RewriteCond %{DOCUMENT_ROOT}/cache/perm/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_\.css -s RewriteRule .* cache/perm/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_\.css [L,QSA,T=text/css] RewriteCond %{DOCUMENT_ROOT}/cache/perm/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_\.js -s RewriteRule .* cache/perm/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_\.js [L,QSA,T=text/javascript] # Caching for anonymous users # Skip boost IF not get request OR uri has wrong dir OR cookie is set OR request came from this server OR https request RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [OR] RewriteCond %{REQUEST_URI} (^/(admin|cache|misc|modules|sites|system|openid|themes|node/add))|(/(comment/reply|edit|user|user/(login|password|register))$) [OR] RewriteCond %{HTTP_COOKIE} DRUPAL_UID [OR] RewriteCond %{HTTP:Pragma} no-cache [OR] RewriteCond %{HTTP:Cache-Control} no-cache [OR] RewriteCond %{HTTPS} on RewriteRule .* - [S=3] # GZIP RewriteCond %{HTTP_COOKIE} !(boost-gzip) RewriteCond %{HTTP:Accept-encoding} !gzip RewriteRule .* - [S=1] RewriteCond %{DOCUMENT_ROOT}/cache/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_%{QUERY_STRING}\.html\.gz -s RewriteRule .* cache/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_%{QUERY_STRING}\.html\.gz [L,T=text/html] # NORMAL RewriteCond %{DOCUMENT_ROOT}/cache/normal/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_%{QUERY_STRING}\.html -s RewriteRule .* cache/normal/%{ENV:device}/%{SERVER_NAME}%{REQUEST_URI}_%{QUERY_STRING}\.html [L,T=text/html] ### BOOST END ###
In your settings.php you should do the following:
/** * Theme array for the mobile categories. The key equals the device category * supported by the site. * Changing this array configures the mobile theme for a certain device group */ $mobile_themes = array('mobile-low' => 'bluemarine', 'mobile-high' => 'pushbutton'); /** * Check if the device argument is one of the valid devices (this is just an extra check) */ if(isset($_GET['device']) && array_key_exists($_GET['device'], $mobile_themes)){ $boost_device = $_GET['device']; $conf['theme_default'] = $mobile_themes[$_GET['device']]; // set the theme } else { $boost_device = 'desktop'; } // We configure the Boost folders to support multiple devices. // This corresponds to the %{ENV:device}/%{SERVER_NAME} string in the apache script $conf['boost_normal_dir'] = 'normal/' . $boost_device ; $conf['boost_gzip_dir'] = 'normal/' . $boost_device; $conf['boost_perm_normal_dir'] = 'perm/' . $boost_device; $conf['boost_perm_gz_dir'] = 'perm/' . $boost_device; /** * End configuration for boost */
Hope this gives some inspiration!
About Drupal Sun
Drupal Sun is an Evolving Web project. It allows you to:
- Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
- Facet based on tags, author, or feed
- Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
- View the entire article text inline, or in the context of the site where it was created
See the blog post at Evolving Web