cachYLT.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /**
  2. * Analyzes HTTP caching headers
  3. *
  4. * @see https://developers.google.com/speed/docs/best-practices/caching
  5. */
  6. exports.version = '0.2.a';
  7. exports.module = function(phantomas) {
  8. 'use strict';
  9. var cacheControlRegExp = /max-age=(\d+)/;
  10. function getCachingTime(url, headers) {
  11. // false means "no caching"
  12. var ttl = false,
  13. headerName,
  14. now = new Date(),
  15. headerDate;
  16. for (headerName in headers) {
  17. var value = headers[headerName];
  18. switch (headerName.toLowerCase()) {
  19. // parse max-age=...
  20. //
  21. // max-age=2592000
  22. // public, max-age=300, must-revalidate
  23. case 'cache-control':
  24. var matches = value.match(cacheControlRegExp);
  25. if (matches) {
  26. ttl = parseInt(matches[1], 10);
  27. }
  28. break;
  29. // catch Expires and Pragma headers
  30. case 'expires':
  31. case 'pragma':
  32. // and Varnish specific headers
  33. case 'x-pass-expires':
  34. case 'x-pass-cache-control':
  35. phantomas.incrMetric('oldCachingHeaders'); // @desc number of responses with old, HTTP 1.0 caching headers (Expires and Pragma)
  36. phantomas.addOffender('oldCachingHeaders', url + ' - ' + headerName + ': ' + value);
  37. headerDate = Date.parse(value);
  38. if (headerDate) ttl = Math.round((headerDate - now) / 1000);
  39. break;
  40. }
  41. }
  42. //console.log(JSON.stringify(headers)); console.log("TTL: " + ttl + ' s');
  43. return ttl;
  44. }
  45. phantomas.setMetric('cachingNotSpecified'); // @desc number of responses with no caching header sent (no Cache-Control header)
  46. phantomas.setMetric('cachingTooShort'); // @desc number of responses with too short (less than a week) caching time
  47. phantomas.setMetric('cachingDisabled'); // @desc number of responses with caching disabled (max-age=0)
  48. phantomas.setMetric('oldCachingHeaders');
  49. phantomas.on('recv', function(entry, res) {
  50. var ttl = getCachingTime(entry.url, entry.headers);
  51. // static assets
  52. if (entry.isImage || entry.isJS || entry.isCSS) {
  53. if (ttl === false) {
  54. phantomas.incrMetric('cachingNotSpecified');
  55. phantomas.addOffender('cachingNotSpecified', entry.url);
  56. } else if (ttl <= 0) {
  57. phantomas.incrMetric('cachingDisabled');
  58. phantomas.addOffender('cachingDisabled', entry.url);
  59. } else if (ttl < 7 * 86400) {
  60. phantomas.incrMetric('cachingTooShort');
  61. phantomas.addOffender('cachingTooShort', entry.url + ' cached for ' + ttl + ' s');
  62. }
  63. }
  64. });
  65. };