4

I have a web application that runs on an Apache server on the intranet of an organisation. In this web application there is a JavaScript function that loads a specific text file via JavaScript

xhttp = new XMLHttpRequest();
var data = xhttp.open("GET", "data.txt", false);

During the use of the webapp this text file may change its contents. These changes need to be reflected in the web app, i.e. the text file must be reloaded, and not be read from browser cache. However, the browser (esp. Chromium) caches the text file. What can be done that the browser always requests the textfile from the server and never caches it?

Can this always reload be done purely with HTML/JavaScript (or perl)?

I don't have access to the apache server configuration. The app uses a lot of perl scripts to assemble the webpage that I'm not familiar with but have access to.

9

You have two approaches to this problem.

The clean way is to set the headers returned for GET data.txt preventing the browser (or proxy) from storing the response in cache. Using apache, this can usually be done by adding a few lines in a .htaccess file. If this data.txt is a static file, this is the only way you could control the headers. From https://stackoverflow.com/questions/11532636/prevent-http-file-caching-in-apache-httpd-mamp

<filesMatch "data\.txt$">
  FileETag None
  <ifModule mod_headers.c>
     Header unset ETag
     Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
     Header set Pragma "no-cache"
     Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
  </ifModule>
</filesMatch>

If GET data.txt is handled by a script (perl, php, java, etc...) then setting those header can be done from the script itself (has to be executed before any content is sent out). Here an example in php

<?php
header("Cache-Control: max-age=0, no-cache, no-store, must-revalidate"); // HTTP/1.1
header("Expires: Wed, 11 Jan 1984 05:00:00 GMT"); // Date in the past
?>

A perl example can be found here https://stackoverflow.com/questions/18056127/set-http-header-in-perl-to-force-download-the-content

If none of those applie, here comes...

The quick and dirty way.

If you can't prevent the call from being cache, then you just change the call and 'trick' the cache. GET data.txt?anyting-different-here-will-do-the-job.just-needs-to-be-different-each-time

A common way is either to use a random number, of to use the current time in milliseconds, or a combination of both.

var ms = Date.now();
var xhttp = new XMLHttpRequest();
var data = xhttp.open("GET", "data.txt?dummy="+ms, false);
  • 2
    The dirty was is actually the best way. It also bypasses crappy proxies that ignore headers. There are a lot of these. – coteyr May 23 '16 at 19:31
  • 1
    It's always easier to build a crappy world ;) – Antony Gibbs May 24 '16 at 10:30
  • I haven't had the chance to test it yet, but could you explain how the quick and dirty way works? what does the server do with the random string? just ingore it and send the requested file? – nutgoodinuff May 25 '16 at 16:37
  • a request to a static file (ex: image.jpg?dummy=123 ) will return the static file. The only difference will be in the the url (it's the id key for the cache. It can also be used in javascript -navigation history- or in the server logs on the server end) – Antony Gibbs May 25 '16 at 17:49
  • sorry for coming back to you this late. Your propsed solution die the trick. Thank you very much! – nutgoodinuff Jun 21 '16 at 10:35
2

The right way would be to change the Apache configuration (via htaccess or conf file) with the expire headers with very low caching time. Double check if you have access to .htaccess file if not Apache conf file.

However, if you absolutely can't alter .htaccess or Apache conf, there may be a trick to achieve it. Most developers use this trick to renew the browser cache whenever they make some change to files which are cached for longer times in the browser cache but this trick may also be used in your case.

The trick is appending version to the filename. e.g. data.txt?v=1 for clearing the browser cache. In your case, you can use a random number as a version number so browser renews the file on every call. However, if the random number is repeated the user will see an old file again. You may use Math.random(); for random number generation in JS.

var data = xhttp.open("GET", "data.txt?v=0.2544544383", false);

Caution: This is only a trick and not the right way. It just reduces the probability of reloading the cached file to a very small number but doesn't guarantee that the cache file will not be fetched.

You should check what is the caching time period of .txt files in the browser. If it is very large (say 1 month), you shouldn't use this technique but if it is much lower (say 1 hr), you may use this technique as the probability of same random number generated for the same user will be increasing lower.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.