New Community Forums are coming. Watch this space for news.
Subscribe: RSS
  • I’m using Amazon’s CloudFront to speed op my site (a lot; about 80% faster). To make this a no-brainer I made a plugin that converts all local images to CDN URLs. This is not Amazon-specific; just change the $cdn array to match your URLs and it will work.

    Disclaimer
    Use this at your own risk; this is just a first attempt to write a CDN URL plugin. There will most likely be bugs, but so far it’s working great for me. Code is still a bit messy though; could use some cleanup.

    How does it work?
    - The plugin is fired just before the page is rendered (OnWebPagePrerender event)
    - Every local image (whether inside img, a or input tag) on the page is checked for existence on the CDN
    - If a CDN version exists the image URL (src) is replaced by a CDN URL
    - The CDN URL is also cached so that it will always be the same (prevents too much checking as well)
    - If a CDN version does not exist, the local image is used

    <?php
    class CDN {
    
        var $cdn; //array of CDN hostnames
        var $cdncache = array(); //files already checked to be on CDN
    
        function __construct($output, &$modx) {
            $this->modx = $modx;
    
            $this->cdn = array('http://cdna.kenters.com', 'http://cdnb.kenters.com', 'http://cdnc.kenters.com', 'http://cdnd.kenters.com');
    
            //get cached images
            $this->cdncache = $this->modx->cacheManager->get('cdncache');
            if(!is_array($this->cdncache)) {
                $this->cdncache = array();
            }
        }
    
        function process($output) {
    
            $output = preg_replace_callback('|<img(?:.+?)src\=\"(\S+)\"|', array($this ,'doCDN'), $output);
            $output = preg_replace_callback('|<input(?:.+?)src\=\"(\S+)\"|', array($this ,'doCDN'), $output);
            $output = preg_replace_callback('|<a(?:.+?)href\=\"(\S+)\"|', array($this ,'doCDN'), $output);
            $this->modx->cacheManager->set('cdncache', $this->cdncache,7200);
    
            return $output;
        }
    
        function doCDN($match) {
          //only process local images
          if( (!stripos($match[1], '.jpg') && !stripos($match[1], '.png') && !stripos($match[1], '.gif') || stripos($match[1], 'http://') !== false || stripos($match[1], 'https://') !==false || stripos($match[1], 'mailto:') !== false) )
          {
              return $match[0];
          }
          else
          {
              $replace = $match[1]; //text to replace
    
              if(array_key_exists($replace, $this->cdncache)) {
                  $replaced = $this->cdncache[$replace];
                  return str_replace($replace, $replaced, $match[0]);
              }
              else {
                    $replaced = $this->cdn[array_rand($this->cdn)].( substr($match[1], 0, 1) == '/' ? '' : '/' ).$match[1]; //replaced url
                    if(  $this->url_validate($replaced) ) {
                        $this->cdncache[$replace] = $replaced; //add to cache
                        return str_replace($replace, $replaced, $match[0]);
                    }
                    else {
                        return $match[0];
                    }
              }
          }
        }
    
        function url_validate( $link )
        {
            $url_parts = @parse_url( $link );
    
            if ( empty( $url_parts["host"] ) ) return( false );
    
            if ( !empty( $url_parts["path"] ) )
            {
                $documentpath = $url_parts["path"];
            }
            else
            {
                $documentpath = "/";
            }
    
            if ( !empty( $url_parts["query"] ) )
            {
                $documentpath .= "?" . $url_parts["query"];
            }
    
            $host = $url_parts["host"];
            $port = $url_parts["port"];
    
            if (empty( $port ) ) $port = "80";
            $socket = fsockopen( $host, $port, $errno, $errstr, 30 );
            if (!$socket)
            {
                return(false);
            }
            else
            {
                fwrite ($socket, "HEAD ".$documentpath." HTTP/1.0\r\nHost: $host\r\n\r\n");
                $http_response = fgets( $socket, 22 );
    
                if ( stripos($http_response, "200 OK") )
                {
                    return(true);
                    fclose( $socket );
                } else
                {
                    return(false);
                }
            }
        }
    }
    
    $output = &$modx->resource->_output;
    $cdn = new CDN($output, $modx);
    $output = $cdn->process($output);
    
      Jeroen Kenters

      MODX Professional | MODX Ambassador | Dutch MODX forums moderator

      website | twitter
    • Hi,

      this plugin is for Revolution, right?

      thanks, j
      • Yep, it’s a revo plugin. Just posted this here because it’s only a simple plugin and still experimental.
          Jeroen Kenters

          MODX Professional | MODX Ambassador | Dutch MODX forums moderator

          website | twitter