You are here

akamai.module in Akamai 6

akamai.module Integration with the Akamai CDN Cache Control Web Service.

Akamai is a registered trademark of Akamai Technologies, Inc.

File

akamai.module
View source
<?php

/**
 * @file akamai.module
 *    Integration with the Akamai CDN Cache Control Web Service.
 *
 *    Akamai is a registered trademark of Akamai Technologies, Inc.
 */
define("AKAMAI_EMAIL_DISABLE", '#disable#');

/**
 * Implementation of hook_init().
 */
function akamai_init() {

  // Only load these if it is not a cached page
  module_load_include('inc', 'akamai', 'akamai.class');
}

/**
 * Implementation of hook_perm().
 */
function akamai_perm() {
  return array(
    'purge akamai cache',
    'administer akamai',
  );
}

/**
 * Implementation of hook_menu().
 */
function akamai_menu() {
  $items = array();
  $items['admin/settings/akamai'] = array(
    'title' => 'Akamai Cache Control',
    'description' => 'Akamai Settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'akamai_settings',
    ),
    'file' => 'akamai.admin.inc',
    'access arguments' => array(
      'administer akamai',
    ),
  );
  $items['admin/settings/akamai/settings'] = array(
    'title' => 'Settings',
    'weight' => -10,
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items['admin/settings/akamai/refresh'] = array(
    'title' => 'Refresh Tool',
    'description' => 'Helper to flush Akamai cache from Drupal',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'akamai_cache_control',
    ),
    'file' => 'akamai.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'access arguments' => array(
      'purge akamai cache',
    ),
  );
  return $items;
}

/**
 * Implementation of hook_theme()
 */
function akamai_theme() {
  return array(
    'akamai_page_cache_control_block' => array(
      'arguments' => array(
        'cache_control_form' => NULL,
      ),
      'template' => 'akamai-page-cache-control-block',
    ),
  );
}

/**
 * Implementation of hook_nodeapi().
 *
 * When nodes are modified, clear URL from the Akamai
 * cache. Clear base node/% url as well as aliases.
 */
function akamai_nodeapi(&$node, $op) {
  switch ($op) {
    case 'update':
    case 'delete':
      $url = base_path() . "node/{$node->nid}";
      akamai_clear_url($url, array(
        'email' => AKAMAI_EMAIL_DISABLE,
      ), $node);
      break;
  }
}

/**
 * Implementation of hook_block().
 */
function akamai_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks[0] = array(
      'info' => t('Akamai Cache Control'),
      'region' => 'footer',
      'weight' => 0,
      'cache' => BLOCK_NO_CACHE,
    );
    return $blocks;
  }
  else {
    if ($op == 'view') {
      $cache_control_form = drupal_get_form('akamai_page_cache_control_form');
      $block = array(
        'subject' => t('Akamai Cache Control'),
        'content' => $content = theme('akamai_page_cache_control_block', $cache_control_form),
      );
      return $block;
    }
  }
}

/**
 * Form for purging the current URL from the Akamai cache.
 */
function akamai_page_cache_control_form() {
  $form = array();
  $path = check_plain($_GET['q']);
  $nid = arg(1);
  if (arg(0) == 'node' && is_numeric($nid) && arg(2) == NULL) {
    $path = arg(0) . '/' . $nid;
  }
  $form['path'] = array(
    '#type' => 'hidden',
    '#value' => $path,
  );
  $form['message'] = array(
    '#value' => t('<p>Clear cache for:<br> @path </p>', array(
      '@path' => $path,
    )),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Refresh Akamai Cache'),
  );
  $form['#node'] = node_load(array(
    'nid' => $nid,
  ));
  return $form;
}

/**
 * Submit handler for akamai_page_cache_control.
 *
 * Purge the 'path' variable from the Akamai cache.
 *
 */
function akamai_page_cache_control_form_submit($form, &$form_state) {
  $values = $form_state['values'];
  $path = $values['path'];
  $did_clear = akamai_clear_url($path, array(), $form['#node']);
  if ($did_clear) {
    $message = t("Akamai Cache Request has been made successfully, please allow 10 minutes for changes to take effect.");
    drupal_set_message($message);
  }
  else {
    drupal_set_message(t("There was a problem clearing the cache for this page.  Check the !watchdog messages for more information.", array(
      '!watchdog' => l("watchdog", "admin/reports/dblog"),
    ), 'error'));
  }
}

/**
 * Clear a URL from Akamai.  Clears node/id and any url aliases.
 *
 * @param $paths_in
 *    a array of paths or single path to clear
 * @param $params
 *   an array of params for the SOAP call
 * @return
 *    TRUE if it was successfully cleared, FALSE otherwise.
 */
function akamai_clear_url($paths_in, $params = array(), $node = NULL) {
  if (!is_array($paths_in)) {
    $paths_in = array(
      $paths_in,
    );
  }

  // Get the system path and all aliases to this url
  $paths = array();
  foreach ($paths_in as $path) {
    $paths = array_merge($paths, _akamai_get_all_paths($path, $node));
  }
  $paths = array_unique($paths);

  // Setup the notification email if an email address is not provided
  if (!array_key_exists('email', $params) || empty($params['email'])) {
    $params['email'] = akamai_get_notification_email();
  }
  try {
    $akamai = new AkamaiCacheControl($params);
    $akamai
      ->clear_url($paths);
    return TRUE;
  } catch (Exception $e) {
    return FALSE;
  }
}

/**
 * Return all system and alias paths for the provided URL.
 *
 * @param $url
 *    The URL to find all aliases
 * @param $node
 *    The Node for the URL being cleared if one exists, NULL otherwise
 * @return
 *    An array of all paths aliased to the provided URL.
 */
function _akamai_get_all_paths($url, $node = NULL) {
  global $language;

  // If it is not a node path, get the system path
  if (strpos($url, 'node') !== 0) {
    $src = drupal_lookup_path('source', $url);
  }
  if (!isset($src) || !$src) {
    $src = $url;
  }
  $src = preg_replace("/^\\//", "", $src);
  $paths[] = $src;
  $result = db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND language IN('%s', '')", $src, $language->language);
  while ($alias = db_result($result)) {
    $paths[] = $alias;
  }

  // Allow other modules to add/modify paths to be cleared
  drupal_alter('akamai_paths', $paths, $node);
  return $paths;
}

/**
 * Get the email address for notification.
 */
function akamai_get_notification_email() {
  $notification = variable_get('AkamaiCC_email', '');
  if (empty($notification)) {
    global $user;
    $notification = $user->mail;
  }
  return $notification;
}

/**
 * Implementation of hook_context_http_header_def() 
 * from context_http_header module 
 * These are the form items that display for the http header context reaction.
 */
function akamai_context_http_header_def() {
  return array(
    'akamai_ttl' => array(
      '#title' => 'TTL',
      '#type' => 'textfield',
      '#description' => t("Specifies a Time-To-Live (TTL) for the object in the edge server’s cache. This is themaximum amount of time the content will be served before the edge server will issue an If Modified Since request back to the content provider to check whether the object content has changed. The content is an integer, followed by a unit specifier Current unit specifiers are: 's' (seconds), 'm' (minutes), 'h' (hours), 'd' (days)."),
    ),
    'akamai_nostore' => array(
      '#title' => 'No Store',
      '#type' => 'radios',
      '#description' => t("Specifies that the object is not to be cached. The edge server will retrieve the object from the origin server upon every request."),
      '#options' => array(
        FALSE => t('Not Specified'),
        'on' => t('On'),
        'off' => t('Off'),
      ),
    ),
    'akamai_bypass_cache' => array(
      '#title' => 'Bypass Cache',
      '#type' => 'radios',
      '#description' => t("When enabled, bypass-cache causes the request to be passed without caching. It's similar to no-store, except that it doesn't remove the cache entry if one already exists. This is useful if the object returned is an alternate for the content normally delivered"),
      '#options' => array(
        FALSE => t('Not Specified'),
        'on' => t('On'),
        'off' => t('Off'),
      ),
    ),
    'akamai_dynamic_content_assembly' => array(
      '#title' => 'Dynamic Content Assembly (dca)',
      '#type' => 'radios',
      '#description' => t('Nominates the request for Dynamic Content Assembly. Valid argument is a type of processing. This header is used to nominate the object for ESI processing. At this time, "esi" and "akamaizer" specify the available processing types. These headers tell the edge server to process the objects in the ESI processor. The other header dca=noop, tells the edge server not to process the associated content.'),
      '#options' => array(
        FALSE => t('Not Specified'),
        'noop' => t('noop'),
        'esi' => t('esi'),
        'akamaizer' => t('akamaizer'),
      ),
    ),
  );
}

/**
 * @param $http_header_items
 * 
 * Implemantation of hook_http_header_build  
 * from context_http_header module
 * build the akamai edge control headers
 * array( 
 *    'header-1' => array('value1', 'value2', etc),
 *    'header-2' => array(...),
 * )
 */
function akamai_context_http_header_build($http_header_items) {
  $header_builds = array();
  if ($value = $http_header_items['akamai_ttl']) {
    $header_builds["Edge-Control"][] = "Cache-maxage=" . check_plain($value);
  }
  if ($value = $http_header_items['akamai_nostore']) {
    if ($value == 'on') {
      $header_builds["Edge-Control"][] = "No-store";
    }
    elseif ($value == 'off') {
      $header_builds["Edge-Control"][] = "!No-store";
    }
  }
  if ($value = $http_header_items['akamai_bypass_cache']) {
    if ($value == 'on') {
      $header_builds["Edge-Control"][] = "bypass-cache";
    }
    elseif ($value == 'off') {
      $header_builds["Edge-Control"][] = "!bypass-cache";
    }
  }
  if ($value = $http_header_items['akamai_dynamic_content_assembly']) {
    if ($value == 'noop') {
      $header_builds["Edge-Control"][] = "dca=noop";
    }
    if ($value == 'esi') {
      $header_builds["Edge-Control"][] = "dca=esi";
    }
    if ($value == 'akamaizer') {
      $header_builds["Edge-Control"][] = "dca=akamaizer";
    }
  }
  return $header_builds;
}

Functions

Namesort descending Description
akamai_block Implementation of hook_block().
akamai_clear_url Clear a URL from Akamai. Clears node/id and any url aliases.
akamai_context_http_header_build
akamai_context_http_header_def Implementation of hook_context_http_header_def() from context_http_header module These are the form items that display for the http header context reaction.
akamai_get_notification_email Get the email address for notification.
akamai_init Implementation of hook_init().
akamai_menu Implementation of hook_menu().
akamai_nodeapi Implementation of hook_nodeapi().
akamai_page_cache_control_form Form for purging the current URL from the Akamai cache.
akamai_page_cache_control_form_submit Submit handler for akamai_page_cache_control.
akamai_perm Implementation of hook_perm().
akamai_theme Implementation of hook_theme()
_akamai_get_all_paths Return all system and alias paths for the provided URL.

Constants

Namesort descending Description
AKAMAI_EMAIL_DISABLE @file akamai.module Integration with the Akamai CDN Cache Control Web Service.