Skip to content

Instantly share code, notes, and snippets.

@acdha
Last active February 12, 2017 17:24
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 acdha/e8251ad52a2af037f7c1 to your computer and use it in GitHub Desktop.
Save acdha/e8251ad52a2af037f7c1 to your computer and use it in GitHub Desktop.
Load a page using PhantomJS and log Akamai CDN cache diagnostic information for every requested resource
#!/usr/bin/env phantomjs --disk-cache=false
/*
Load one or more URLs requesting Akamai CDN diagnostic information for every resource
and list resources which are configured not to be cached:
phantomjs check-akamai-status.js https://www.microsoft.com/ http://www.state.gov https://www.wdl.org/en/
Additional timing information will be displayed to easily distinguish between requests
made before DOMContentLoaded or the full load event.
*/
"use strict";
var system = require('system');
function logError() {
system.stderr.write(Array.prototype.join.call(arguments, ' ') + '\n');
}
function initPage() {
var page = new WebPage();
page.onError = function (msg, trace) {
logError('\t🌋\tERROR:', msg);
trace.forEach(function(item) {
logError(' ', item.file, ':', item.line);
});
};
page.onConsoleMessage = function(msg) {
if (msg == 'GOTO_NEXT_PAGE') {
page.close();
loadNextPage();
} else {
console.log('\t💻\t' + msg);
}
};
page.onResourceRequested = function(requestData, networkRequest) {
// Request diagnostic info from Akamai:
networkRequest.setHeader('Pragma', 'akamai-x-cache-on, akamai-x-cache-remote-on, akamai-x-check-cacheable, akamai-x-get-cache-key, akamai-x-get-true-cache-key, akamai-x-serial-no');
};
page.onResourceReceived = function(response) {
if (response.stage == 'start') {
var akamaiHeaders = response.headers.filter(function (i) {
return i.name.match(/X-.*(Akamai|Cache)/i);
});
akamaiHeaders.forEach(function (obj) {
if (obj.name == 'X-Check-Cacheable' && obj.value != 'YES') {
console.warning('\t⚠️\tUncacheable response:', response.status, response.url,
JSON.stringify(akamaiHeaders));
} else if (obj.name == 'X-Cache') {
console.info('\t', obj.value.match(/HIT/) ? '🐇' : '🐢' , '\tAkamai:',
response.status, response.url, obj.value);
}
});
}
};
return page;
}
function loadNextPage() {
if (allUrls.length < 1) {
console.log('All URLs complete');
phantom.exit();
return;
}
var url = allUrls.shift();
var page = initPage();
console.log('🌐\tOpening', url, '(' + allUrls.length + ' remaining)');
page.onInitialized = function() {
page.evaluate(function(startTime) {
/* global window, document */
document.addEventListener('DOMContentLoaded', function() {
console.log('DOMContentLoaded', ((Date.now() - startTime) / 1000).toFixed(3) + 's');
});
window.addEventListener('load', function() {
console.log('load event', ((Date.now() - startTime) / 1000).toFixed(3) + 's');
window.setTimeout(function () {
console.log('GOTO_NEXT_PAGE');
}, 500);
});
window.setTimeout(function () {
console.log('\t👎\tAborting page load after one minute');
console.log('GOTO_NEXT_PAGE');
}, 60 * 1000);
}, Date.now());
var prerenderUrls = page.evaluate(function() {
/* global window, document */
var prerenderLinks = document.querySelectorAll('link[rel*=prerender]'),
urls = [];
for (var i = 0; i < prerenderLinks.length; i++) {
urls.push(prerenderLinks[i].href);
}
return urls;
});
if (prerenderUrls.length) {
allUrls.push.apply(allUrls, prerenderUrls);
}
};
var loadStart = Date.now();
page.open(url, function (status) {
var loadComplete = Date.now();
if (status !== 'success') {
logError('\t⚠️\tUnable to load ', url, ': ', status);
page.close();
loadNextPage();
} else {
console.log('\t✅\t', url, 'in', ((loadComplete - loadStart) / 1000).toFixed(1), 'seconds');
}
});
}
var allUrls = system.args.slice(1);
if (allUrls.length < 1) {
console.log('Usage:', system.args[0], 'URL [URL …]');
phantom.exit();
}
loadNextPage();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment