📜 ⬆️ ⬇️

Check if browser is enabled for caching

About the fact that client caching can and should be used, over the past few years, many have learned, but about what problems it causes - everyone will know from experience. Therefore, I hasten to share my experience and the problem that has arisen with users whose browser cache is turned off. Users do not know that their cache is turned off and complain about the slow speed of loading pages.

Background (can be skipped)


On the project in which I had the opportunity to work, there was the problem of a large number of java-script files (about 40 pieces - 2 js libraries were used + a dozen self-written components). Such a number of sequentially loaded files caused a long page load. I, as a person familiar with the works of sunnybear comrade, offered to merge all these files into one and cache it.

As a result, the site flew, and we already wanted to relax, when suddenly there were messages from users who still reported the problem of long page load. After a brief search, it was discovered that these are users who for one reason or another have disabled the browser cache.

So, the task was to identify users with disabled caches and timely inform them. Fortunately, the first page of the project already contained a list of checks for blocking pop-up windows, working js and flash. Therefore, adding a browser cache check was completely logical, and did not spoil the existing concept.
')

How to check browser cache from js?


Curiously, by asking Google this question, I got a list of forums with some crazy ideas for counting request time and other vague ideas. Therefore, the algorithm for checking the working cache had to be invented:
  1. Send a request to the server
  2. We get a response with some content and caching headers for this request
  3. Changing server content
  4. We send the second request to the server
  5. Compare the received content. If the cache is working, the contents of the second request will match the first one, if not - we will receive the modified content from the server


PHP algorithm implementation


I simplify implementation example to two php files + jquery. The essence of the decision is clear from it, so you can make the adaptation for your framework or language yourself.

Listing of the ajaxCacheChecker.php file - we will request this file twice
  1. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  2. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  3. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  4. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  5. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  6. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  7. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  8. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  9. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  10. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  11. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  12. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  13. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>
  14. <?php $etag = 'cacheChecker' ; if ( @ strtotime ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ] ) == $_GET [ 's' ] || trim ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ] ) == $etag ) { header ( 'HTTP/1.1 304 Not Modified' ) ; } else { $maxAge = 60 ; header ( 'Last-Modified: ' . gmdate ( 'r' , $_GET [ 's' ] ) ) ; header ( 'Etag: ' . $etag ) ; header ( 'Pragma: private' ) ; header ( 'Cache-Control: private' ) ; header ( "Expires: " . date ( "r" , $_GET [ 's' ] + $maxAge ) ) ; echo microtime ( ) ; } ?>


Listing of the index.php file - this file is our application, as it were.
  1. <? php $ timeStamp = time ( ) ; ?>
  2. <html>
  3. <head> <script type = "text / javascript" src = "js / jquery.js"> </ script> </ head>
  4. <body>
  5. <div id = "cacheCheck"> checking cache </ div>
  6. <script>
  7. var cacheCheck1 = "";
  8. var cacheCheck2 = "";
  9. function checkBrowserCache () {
  10. $ .get ("ajaxCacheChecker.php? s = <? = $ timeStamp ?> ", function (data) {
  11. cacheCheck1 = data;
  12. $ .get ("ajaxCacheChecker.php? s = <? = $ timeStamp ?> ", function (data2) {
  13. cacheCheck2 = data2;
  14. checkBrowserCacheResults ();
  15. });
  16. });
  17. }
  18. function checkBrowserCacheResults () {
  19. if (cacheCheck1! = cacheCheck2) {
  20. $ ('# cacheCheck'). text ('cache disabled. Please enable browser cache ...');
  21. } else {
  22. $ ('# cacheCheck'). text ('cache enabled!');
  23. }
  24. }
  25. checkBrowserCache ();
  26. </ script>
  27. </ body>
  28. </ html>


Disadvantage


The solution does not work in Opera and Safari
If you know how to add support for these browsers - write a comment

Conclusion


I hope that my research will help you to resolve your disputes with customers and users about the long loading page.

This solution does not imply that verification will occur on every page. If you want to implement verification everywhere, then use the logic given in the comment by maghamed

UPD : Thank you comrades tenshi and TheShock for getting rid of sessions in the algorithm
UPD2 : comments of comrade zerkms are taken into account. Found a bug in Opera and Safari

Source: https://habr.com/ru/post/96934/


All Articles