Skip to content

Instantly share code, notes, and snippets.

@kingkool68
Created November 11, 2013 22:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kingkool68/7421460 to your computer and use it in GitHub Desktop.
Save kingkool68/7421460 to your computer and use it in GitHub Desktop.
I wanted to run my entire WordPress site through a CDN so this is what I had to do to make it work. cdn-integration.php is a plugin file that you shouldn't have to change. wp-config.php is some configuration details you'll need to put in wp-config.php Most CDNs let you control the TTL of how long to hold on to assets from the caching headers set…
<?php
/*
Plugin Name: RH CDN Integration
Description: Making Origin Pull Work. Heavilty inspired by https://github.com/markjaquith/WP-Stack/blob/master/WordPress-Dropins/wp-stack-cdn.php
Version: 0.1
Author: Russell Heimlich
Author URI: http://www.russellheimlich.com
*/
// Convenience methods
if(!class_exists('RH_Plugin')){class RH_Plugin{function hook($h){$p=10;$m=$this->sanitize_method($h);$b=func_get_args();unset($b[0]);foreach((array)$b as $a){if(is_int($a))$p=$a;else $m=$a;}return add_action($h,array($this,$m),$p,999);}private function sanitize_method($m){return str_replace(array('.','-'),array('_DOT_','_DASH_'),$m);}}}
// The plugin
class RH_CDN_Plugin extends RH_Plugin {
public static $instance;
public $site_domain;
public $cdn_domain;
public function __construct() {
self::$instance = $this;
if( defined( 'FROMCDN' ) && FROMCDN ) {
$this->hook( 'plugins_loaded' );
}
}
public function plugins_loaded() {
if ( !is_admin() ) {
$this->hook( 'template_redirect' );
$this->hook( 'redirect_canonical' );
$this->hook( 'rh_cdn_content', 'filter' );
$this->hook ( 'wp_footer', 999 );
$this->site_domain = 'http://' . parse_url( get_bloginfo( 'url' ), PHP_URL_HOST );
$this->cdn_domain = RH_CDN_DOMAIN; //Constant defined in wp-config.php
// These are optional but they rewrite JS/CSS URLs that are loaded with wp_enque_* stripping the query string and adding a human readable date before the filename.
// More details are available at https://forrst.com/posts/CDN_Friendly_CSS_and_JS_URLs_in_WordPress-IZn
$this->hook( 'script_loader_src', 'cache_busting_file_src' );
$this->hook( 'style_loader_src', 'cache_busting_file_src' );
}
}
public function filter( $content ) {
return str_replace( $this->site_domain, $this->cdn_domain, $content );
}
public function template_redirect() {
ob_start( array( $this, 'ob' ) );
}
public function ob( $contents ) {
return apply_filters( 'rh_cdn_content', $contents, $this );
}
public function redirect_canonical( $redirect_url, $requested_url ) {
$no_port = preg_replace('/:\d+/i', '', $requested_url ); //Strip port numbers from the requested URL otherwise this could throw the site into an infinite redirect loop.
if( $no_port != $redirect_url ) {
return $redirect_url;
}
if( is_user_logged_in() || $_SERVER['QUERY_STRING'] || $no_port == $redirect_url ) {
return false;
}
return $redirect_url;
}
public function wp_footer() {
date_default_timezone_set( get_option('timezone_string') );
echo "\n\t" . '<!-- Cached by CDN, Generated: ' . date( 'Y-m-d g:i:s a T') . ' -->' . "\n";
}
/*
Rewrites CSS and JavaScript urls that are enqueued via the proper WordPress functions. It adds a date of when the file was last modified before the file name for cacheing efficeny.
Requires the following in the .htaccess file:
RewriteRule ^(.+)/\d.+/(.+)\.(js|css)$ $1/$2.$3 [L]
*/
public function cache_busting_file_src( $src, $handle ) {
global $wp_scripts;
//Strip out query strings.
$src = explode('?', $src);
$src = $src[0];
//Check if script lives on this domain. Can't rewrite external scripts, they won't work.
if( !strstr( $src, $wp_scripts->base_url ) || strstr( $src, 'wp-include' ) ) {
return $src;
}
$regex = '/' . preg_quote($wp_scripts->base_url, '/') . '/';
$path = preg_replace($regex, '', $src);
//If the folder starts with wp- then we can figure out where it lives on the filesystem.
if( strstr($path, '/wp-') ) {
$file = untrailingslashit(ABSPATH) . $path;
}
//If the folder starts with /wp-content/themes and the COMPRESS_THEME_CSS constant is true, modify the path to point to the minified CSS. Note: Minification needs to happen when changes are deployed via a seperate script.
if( strstr($path, '/wp-content/themes') && strstr($path, '/css') && defined('COMPRESS_THEME_CSS') && constant('COMPRESS_THEME_CSS') ) {
$file_parts = pathinfo($file);
$file = $file_parts['dirname'] . '/' . $file_parts['filename'] . '.min.' . $file_parts['extension'];
$src_parts = pathinfo($src);
$src = $src_parts['dirname'] . '/' . $src_parts['filename'] . '.min.' . $src_parts['extension'];
}
if( !file_exists($file) ) {
return $src;
}
$time = 0; //Just in case something goes wrong...
$time = date( 'Y-m-d_g:i', filemtime($file) );
$path_parts = pathinfo($src);
$new_path = $time . '/' . $path_parts['basename'];
$src = preg_replace('/' . preg_quote($path_parts['basename'], '/') . '/i', $new_path, $src);
return $src;
}
}
new RH_CDN_Plugin;
//Add the following code to your wp-config.php file somewhere before the /* Stop Editing comment*/
//Tells WordPress what the IP of the user requesting the page is instead of the IP of the load balancer or CDN.
if ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
$FWD_IP = explode( ",", $_SERVER['HTTP_X_FORWARDED_FOR'] );
$_SERVER['REMOTE_ADDR'] = trim( $FWD_IP[0] );
}
if( strpos( $_SERVER['REQUEST_URI'], '/wp-admin/') === FALSE ||
strpos( $_SERVER['REQUEST_URI'], '/wp-login.php/') === FALSE
) {
define('RH_CDN_DOMAIN', 'http://www.russellheimlich.com'); //Define the URL that goes through your CDN.
if( isset($_GET['cdn']) || ( isset($_SERVER['HTTP_VIA']) && !empty($_SERVER['HTTP_VIA']) ) ) { //Some condition to determine the request came from the CDN. The HTTP VIA header is a good one.
define('WP_HOME', 'http://russellheimlich.com/blog');
define('WP_SITEURL', 'http://russellheimlich.com/blog');
define( 'FROMCDN', TRUE );
}
}
@gonebeta
Copy link

Hi,

Would this still work on current wordpress version?
I'm using keycdn and let's encrypt ssl. I get the green padlock all fine and the site works but I can't login to the site to edit or add new content. it's driving me crazy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment