After updating a site, it may be required to expire all pages. Should be done with care on sites with heavy traffic, but it would be great if we can do with a drush command or button in the admin.

I am using the following code for this (Varnish 3.x):

if (req.request == "PURGE" || req.request == "PURGEALL") {
  if (!client.ip ~ purge) {
    // Return error code 405 (Forbidden) when not
    error 405 "Not allowed.";
  }
   if (req.request == "PURGE") {
    // Purge all objects from cache that match the incoming url and host
    ban("req.url == " + req.url + " && req.http.host == \"" + req.htt$
  }
  else {
    // Purge all objects from cache that match the incoming host
    ban("req.url ~ ^/ && req.http.host == " + req.http.host);
  }
  // Return a http error code 200 (Ok)
  error 200 "Purged";
}

Comments

SqyD’s picture

Hi maurits!

This feature request was expected and will be in a future release. Please see my comment on a similar feature request http://drupal.org/node/1299484#comment-5099470

SqyD’s picture

Version: 6.x-1.x-dev » 7.x-2.x-dev
sokrplare’s picture

Issue summary: View changes

The VCL excerpt was helpful, so just for future folks who come across this, we used similar VCL logic and then implemented the call to PURGEALL in a custom module. That module already integrated with the Cache Expiration (expire) module to give us a backend form where we could expire specific URLs if needed, but this extended it to purge the whole domain. If you don't have the expire module you'd probably want to use different link paths.

/**
 * Implementation of hook_menu().
 */
function domain_purge_menu() {
  $items['admin/config/system/expire/full-domain'] = array(
    'title'            => 'Expire Domain',
    'description'      => 'Expire all URLs at this domain from the cache.',
    'page callback'    => 'drupal_get_form',
    'page arguments'   => array('domain_purge_admin_settings_full_domain_form'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
  );

  return $items;
}

/**
 * Form to allow admins to expire the entire domain from Varnish.
 */
function domain_purge_admin_settings_full_domain_form($form, &$form_state) {
	$form = array(); // no values or anything need to be passed

	return confirm_form(
		$form,
		t('Are you sure you want to purge the entire Varnish cache for this domain?'), // title question
		'admin/config/system/expire/specific-url', // path if user clicks on Cancel
		t('This will drastically increase the load on the web server until Varnish '
        . 'can rebuild the cache. Consider doing this during off-peak hours.'), // page description details
		t('Purge Domain'), // confirm button
		t('Nevermind, bad idea.') // cancel link
	);
}

/**
 * Submit handler for domain_purge_admin_settings_full_domain_form
 * 
 * This function is invoked only when the user clicks the confirm button ('Purge Domain')
 * If the user clicks instead on cancel ('Nevermind, bad idea.') they are clickin on cancel, the user goes back to the $path
 */
function domain_purge_admin_settings_full_domain_form_submit($form, &$form_state) {
  global $base_url;
  
  $purge = array();
  $purge['request_method'] = 'PURGEALL';
  $host_url_parts = parse_url($base_url);
  $host_url_host = $host_url_parts['host'];
  // Add ports to the host if one is set
  if (array_key_exists('port', $host_url_parts)) {
    $host_url_host = $host_url_host . ":" . $host_url_parts['port'];
  }
  $purge['headers'] = array("Host: " . $host_url_host);
  
  $proxy_urls = explode(' ', variable_get('purge_proxy_urls', 'http://localhost:80'));
  foreach ($proxy_urls as $proxy_url) {
    $purge['proxy_url'] = $proxy_url;
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $purge['request_method']);
    curl_setopt($ch, CURLOPT_URL, $purge['proxy_url']);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $purge['headers']);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
    //curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8888'); //allows debugging locally with Fiddler
    curl_exec($ch);
    curl_close($ch);
  }
  
  drupal_set_message('The Varnish cache has been purged for the domain.');
	$form_state['redirect'] = 'admin/config/system/expire/specific-url'; // don't reload page
}
Grayside’s picture

I put together a Purge All module based on this issue. It wires up a Purge All option that can be configured for use by nodes.