How to - Fastcgi_cache & Desktop with Mobile versions - Purging with GET Requests

For how I figured this out, skip to after the instructions:

I have not seen an answer to the various versions of this question, ie: when using jetpack, wptouch, etc, so I hope this will help those who are facing this issue.

I am running a site using --wp --wpfc, It has wptouchpro. Previous attempts have cause either mobile or desktop versions to be shown to both device types after the first one accesses the page.

This is a refined version as stated on:

WARNING: This method edits core easy engine files which WILL be REPLACED on an update !!

How to - Quick & Easy:

nginx.conf - Add:

map $http_user_agent $mobile_request
 default                  fullversion;

 "~*ipad"    fullversion;

 "~*android.*mobile"   mobileversion;
 "~*iphone"    mobileversion;
 "~*ipod.*mobile"   mobileversion;
 "~*BlackBerry*Mobile Safari"  mobileversion;
 "~*BB*Mobile Safari"   mobileversion;
 "~*Opera.*Mini/7"   mobileversion;
 "~*IEMobile/10.*Touch"   mobileversion;
 "~*IEMobile/11.*Touch"   mobileversion;
 "~*IEMobile/7.0"   mobileversion;
 "~*IEMobile/9.0"   mobileversion;
 "~*Firefox.*Mobile"   mobileversion;
 "~*webOS"    mobileversion;


# FastCGI cache settings
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:50m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri$mobile_request";
fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503;
fastcgi_cache_valid 200 301 302 404 1h;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_param SERVER_NAME $http_host;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_keep_conn on;


set $skip_cache 0;
set $var_desktop "fullversion";
set $var_mobile "mobileversion";
# POST requests and URL with a query string should always go to php
if ($request_method = POST) {
  set $skip_cache 1;
if ($query_string != "") {
  set $skip_cache 1;
# Don't cache URL containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*.php|index.php|/feed/|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {
  set $skip_cache 1;
# Don't use the cache for logged in users or recent commenter
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
  set $skip_cache 1;
# Use cached or actual file if they exists, Otherwise pass request to WordPress
location / {
  try_files $uri $uri/ /index.php?$args;
location ~ ^/wp-content/cache/minify/(.+\.(css|js))$ {
  try_files $uri /wp-content/plugins/w3-total-cache/pub/minify.php?file=$1;
location ~ \.php$ {
  try_files $uri =404;
  include fastcgi_params;
  fastcgi_pass php;
  fastcgi_cache_bypass $skip_cache;
  fastcgi_no_cache $skip_cache;
  fastcgi_cache WORDPRESS;
if ($http_cookie ~ 'wptouch-pro-view=desktop') {
 set $mobile_request fullversion;
location ~ /purge(/.*) {
   access_log   off ;  log_not_found    off;
   fastcgi_cache_purge WORDPRESS $scheme$request_method$host$1$var_desktop;
location ~ /mpurge(/.*) {
   access_log   off ;  log_not_found    off;
   fastcgi_cache_purge WORDPRESS $scheme$request_method$host$1$var_mobile;


Look for function purgeUrl - default - replace with:

$_url_purge_base = $parse[ 'scheme' ] . '://' . $parse[ 'host' ] . '/purge' . $parse[ 'path' ];
					$_url_purge = $_url_purge_base;
					$_url_purge_base_m = $parse[ 'scheme' ] . '://' . $parse[ 'host' ] . '/mpurge' . $parse[ 'path' ];
					$_url_purge_m = $_url_purge_base_m;

					if ( isset( $parse[ 'query' ] ) && $parse[ 'query' ] != '' ) {
						$_url_purge .= '?' . $parse[ 'query' ];
						$_url_purge_m .= '?' . $parse[ 'query' ];

					$this->_do_remote_get( $_url_purge );
					$this->_do_remote_get_m( $_url_purge_m );

					if ( $feed ) {
						$feed_url = rtrim( $_url_purge_base, '/' ) . '/feed/';
						$feed_url_m = rtrim( $_url_purge_base_m, '/' ) . '/feed/';
						$this->_do_remote_get( $feed_url );
						$this->_do_remote_get_m( $feed_url_m );
						$this->_do_remote_get( $feed_url . 'atom/' );
						$this->_do_remote_get_m( $feed_url_m . 'atom/' );
						$this->_do_remote_get( $feed_url . 'rdf/' );
						$this->_do_remote_get_m( $feed_url_m . 'rdf/' );

Add new function after function _do_Remote_get:

private function _do_remote_get_m( $url ) {

			$user_args = array(
			'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1'

			$response = wp_remote_get( $url ,$user_args);

			if ( is_wp_error( $response ) ) {
				$_errors_str = implode( " - ", $response->get_error_messages() );
				$this->log( "Error while purging URL. " . $_errors_str, "ERROR" );
			} else {
				if ( $response[ 'response' ][ 'code' ] ) {
					switch ( $response[ 'response' ][ 'code' ] ) {
						case 200:
							$this->log( "- - " . $url . " *** PURGED ***" );
						case 404:
							$this->log( "- - " . $url . " is currently not cached" );
							$this->log( "- - " . $url . " not found (" . $response[ 'response' ][ 'code' ] . ")", "WARNING" );


Following those instructions, I got the server to create 2x versions of the page cached correctly. Using the key constructor ($scheme$request_method$host$request_uri$mobile_request) I used an online md5 generator to find the cache files and everything was working 100%.

Mobile requests were created using the inspector in chrome, set to an iPhone 6s.

I then modified the nginx helper plugin to do 2x calls, one to /purge, and the other to /mpurge. The main issue I faced was that the desktop version was getting purged, but the mobile version was not.

After several hours of diagnostics I perchance accessed the /mpurge url from the inspector in Mobile mode, and it cleared the mobile version !!

My hypothesis is that somehow, even though I can access the /mpurge from the server or desktop page request, you will always get 404 not found if the user agent is not one of those it detects as a mobile agent.

To fix this issue, I created a second function _do_remote_get_m which adds a user-agent arg to the wp_remote_get option. And then EVERYTHING started working correctly.

I am going to duplicate this to my production server, and fix any issues. Thought I would get this out there so long.

Enjoy !!

1 Like

hi @StormWalkerEc how is this customization going for you? Any problems? ( I am tedious to apply this changes to my production server unless i am sure )

All working … obviously you need to test it your side, but the changes are quick and easy. Increases the main site speed from 6.5s load time to 4.5s …

you apply this again after every EE update yes, since this isn’t applied to standard config files i guess.

Correct, you only need to edit the wpfc.conf file after an update


I need a soluction more easy. Do you have?

The issue is that core files need to be edited. One can probably make a script to do this, but, that’s not where my skills are …

Also, they are busy re-creating the engine for V4 using wp-cli … so will have to see how that goes. I am personally not using EE anymore as I have switched to docker, and EE does not play well in that environment …

1 Like