How does W3 Total Cache CDN URL rewrites work? [closed]
IT Nursery
April 30, 2022
0
I just setup W3 Total Cache S3 CDN (origin push) and most of the URLs are being rewritten correctly but we have some custom plugins where the URLs are not being rewritten. How do I grab the rewritten URL of W3TC from another plugin? I’m currently using the following code to grab the image:
I’m assuming there is a filter of some sort that just replaces the original “origin” url with the asset URL on the S3 bucket but I’ve been unable to find where in the code.
3 s 3
The W3 Total Cache plugin changes the URL of various files in /w3-total-cache/lib/W3/Plugin/Cdn.php in the function *ob_callback*. It uses a series of callbacks to modify an output buffer. The code runs like this:
w3_total_cache.php calls $root->run();
W3_Root::run calls $plugin->run() for each plugin in $this->_loaded_plugins
W3_Plugin_TotalCache::run starts an output buffer which calls W3_Plugin_TotalCache::ob_callback
W3_Plugin_TotalCache::ob_callback calls w3tc_do_ob_callbacks() which runs any callback stored in $GLOBALS['_w3tc_ob_callbacks']
The CDN adds it’s own callback to that global in W3_Plugin_Cdn::run. That callback is W3_Plugin_Cdn::ob_callback
Which callbacks then run is unfortunately hard coded in this line: $buffer = w3tc_do_ob_callbacks(array('minify', 'newrelic', 'cdn', 'browsercache', 'pagecache'), $buffer);
Because this is hard coded, if you ever need to modify what is included and what isn’t, you’ll have to change their callback.
Example:
I have a plugin that exports JSON, and the CDN aspect of W3 Total Cache wasn’t changing any URLs for JSON requests. It turns out that my output was failing the w3_is_xml($buffer) test.
I fixed it by turning their single CDN callback into multiples, like this:
// Modify the output buffer callbacks of W3 Total Cache to work with the JSON API
if (!empty($GLOBALS['_w3tc_ob_callbacks']) && isset($GLOBALS['_w3tc_ob_callbacks']['cdn'])) {
// Back-up the original value of $GLOBALS['_w3tc_ob_callbacks']['cdn']
// This should be W3_Plugin_Cdn::ob_callback
$this->cdn_ob_callback = $GLOBALS['_w3tc_ob_callbacks']['cdn'];
// Replace $GLOBALS['_w3tc_ob_callbacks']['cdn'] with out own method
// which will call the original callback in between two of our own
$GLOBALS['_w3tc_ob_callbacks']['cdn'] = array($this, 'do_multiple_cdn_ob_callbacks');
}
Then doing the changes I need, making sure to call their original callback in the middle.
public function do_multiple_cdn_ob_callbacks(&$buffer) {
// Frist run our own callback to add an XML string to the buffer
// so that the content passes the w3_is_xml($buffer) test
$buffer = $this->w3_total_cache_ob_callback_start($buffer);
// Next run the original callback, which will replace the asset URLs
$buffer = call_user_func($this->cdn_ob_callback, $buffer);
// Finally, run another callback of our own to remove the XML string
$buffer = $this->w3_total_cache_ob_callback_end($buffer);
return $buffer;
}