1

Hi all I am trying to turn caching off by Adding a random value to the query string component of the URL sent with the request message.

I have a server that sends the etag as a string to my client and I want to make sure no caching is going on I already setRequestHeaders but i'm also supposed to add an http request similar to POST /message?x=0.123456789 HTTP/1.1

this is my client code

<html>
<header><title>This is title</title></header>
<body>
<span id="ajaxButton" style="cursor: pointer; text-decoration: underline">
  Make a request
</span>
<script type="text/javascript">
(function() {
  var httpRequest;
  var x= Math.random();
  document.getElementById("ajaxButton").onclick = function() { makeRequest('http://localhost:5000/'); };
  function makeRequest(url) {
    if (window.XMLHttpRequest) { // Mozilla, Safari, ...
      httpRequest = new XMLHttpRequest();
    } else if (window.ActiveXObject) { // IE
      try {
        httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
      } 
      catch (e) {
        try {
          httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        } 
        catch (e) {}
      }
    }
    if (!httpRequest) {
      alert('Giving up :( Cannot create an XMLHTTP instance');
      return false;
    }
    httpRequest.onreadystatechange = alertContents;
    httpRequest.open('GET', url, true);
    //httpRequest.setRequestHeader("pragma", "no-cache");
    //httpRequest.setRequestHeader("Cache-Control", "no-cache", "no-store"); 
    httpRequest.send();

  }
  function alertContents() {
    if (httpRequest.readyState === 4) {
      if (httpRequest.status === 200) {
        var etagString = httpRequest.responseText;
        alert(etagString);
      } else {
        alert('There was a problem with the request.');
      }
    }
  }
})();
</script>
</body>
</html>

edit for adding errors

XMLHttpRequest cannot load http://localhost:5000/?_0.1909303846769035. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. 

using node.js I run the server using main.js which is

var http = require('http');
var domain = require('domain');
var root = require('./root'); // do I have to replace root w/ message 
var image = require('./image');  // for better readability?


function replyError(res) {
  try {
    res.writeHead(500);
    res.end('Server error.');
  } catch (err) {
    console.error('Error sending response with code 500.');
  }
};

function replyNotFound(res) {
  res.writeHead(404);
  res.end('not found');
}

function handleRequest(req, res) {
  console.log('Handling request for ' + req.url);
  if (req.url === '/') {
    root.handle(req, res);
  }
  if (req.url === '/image.png'){
    image.handle(req, res);
  } 
  else {
    replyNotFound(res);
  }
}



var server = http.createServer();

server.on('request', function(req, res) {
  var d = domain.create();
  d.on('error', function(err) {
    console.error(req.url, err.message);
    replyError(res);
  });
  d.run(function() { handleRequest(req, res)});
});

function listen(){
server.listen(5000);
}

root.init(listen);

and inside root.js is

var http = require('http');
var response = require('./response');
var body;
var etag;



exports.handle = function(req, res) {
  if (req.headers['if-none-match'] === etag) {
    console.log('returning 304');
    return response.replyNotModified(res);
  } 
  res.writeHead(200, {'Content-Type': 'text/plain',
  'Content-Length': body.length,
  "Access-Control-Allow-Origin":"*",
  "Access-Control-Allow-Headers":"X-Requested-With",
  'ETag' : etag
  }); 
  res.end(body);   
}


exports.init = function(cb) {
  require('fs').readFile('app.html', function(err, data) {
    if (err) throw err;
    etag = response.generateETag(data); //
    body = etag;
    console.log("init");
    cb();
  });
}

/*function generateETag(buffer) {   
  var shasum = require('crypto').createHash('sha1');
  shasum.update(buffer, 'binary'); 
  return shasum.digest('hex');    
  console.log(shasum.digest('hex'));
}
var replyNotModified = function(res) {
  res.writeHead(304);
  res.end();
};*/

the errors are in

Ryan Williams
  • 653
  • 3
  • 12
  • 28
  • so what is your question? – Jon Taylor Feb 24 '14 at 00:23
  • how do I add a random add a random value using math.random() – Ryan Williams Feb 24 '14 at 00:28
  • You say it's throwing errors but you haven't provided us with those errors. If you give us some log output or console output so we can see what they are when you used the math.random() function this would help. – Jon Taylor Feb 24 '14 at 00:30
  • 1
    What url are you using to access the page that is making this request? Looks like a cross domain problem to me. – Jon Taylor Feb 24 '14 at 00:34
  • I added the error should I add my server side js code too? – Ryan Williams Feb 24 '14 at 00:42
  • Server side js code? And no, please tell us the url you have in your browser when accessing this page. It looks like you are probably on localhost/blah blah, the default web port and then making a request to port 5000 which is classed as a different domain. – Jon Taylor Feb 24 '14 at 00:45
  • I'm running it using node js and a call localServer.listen(5000) do I have to set the port and the random url to be equal to eachother? I access the page via harddiskpath/client.html – Ryan Williams Feb 24 '14 at 00:47
  • Read this http://en.wikipedia.org/wiki/Same-origin_policy it will give you an understanding of what is going wrong. – Jon Taylor Feb 24 '14 at 00:48

2 Answers2

3

So, the error that you're getting is to do with cross-origin resource sharing, which has nothing to do with caching or query strings. It looks like you're trying to make AJAX calls from a file:// url, which you can't do.

If you serve the page in question from your Node.js app, that message should go away.

If you can't do that, set up that app to send CORS headers. You can read about CORS in detail at MDN, but the short version is that you need to send a header that looks like this (where otherdomain.com is where the Web page is hosted):

Access-Control-Allow-Origin: http://otherdomain.com

Note that you'll still have to serve the page over HTTP; to my knowledge you can't do AJAX at all from a page loaded via a file:// URL.

Daisy Leigh Brenecki
  • 7,571
  • 6
  • 28
  • 43
  • well If I take away the math.random and just use makeRequest('http://localhost:5000') it will correctly alert the httpRequest.responsetext isn't that an ajax request? – Ryan Williams Feb 24 '14 at 00:54
  • how would i "serve the page in question from your Node.js app" – Ryan Williams Feb 24 '14 at 00:56
  • @RyanWilliams Okay, that's interesting. What happens if you change `'http://localhost:5000'` so that it says `'http://localhost:5000/'` (note the trailing slash)? – Daisy Leigh Brenecki Feb 24 '14 at 01:00
  • IF I comment out httpRequest.setRequestHeader("pragma", "no-cache"); httpRequest.setRequestHeader("Cache-Control", "no-cache", "no-store"); the ajax button will correctly display the etag with alert(etagstring) is there a way to run my file from an http:/localhost/ instead of file:/ without using wamp just using node.js and code? – Ryan Williams Feb 24 '14 at 01:02
  • @RyanWilliams I'm getting really confused, here. Can you post a file that works, and a file that produces the error you're seeing, so we can try to figure out what the difference is? – Daisy Leigh Brenecki Feb 24 '14 at 01:07
  • @RyanWilliams Also, what is in the address bar of the browser you're viewing the page in? – Daisy Leigh Brenecki Feb 24 '14 at 01:08
  • the address bar im in the page is file://c:/stuff/app.html My apologies for any confusion I'm not completely sure what I'm even asking I am just trying to fix the domain cross error without using wamp or other programs/libraries... I run the server in the command prompt using node main.js – Ryan Williams Feb 24 '14 at 01:15
  • Right, so as I said in my answer, you shouldn't be able to do AJAX **at all** from a page at a `file://` URL, and you'll need to serve it from your Node.js app. This means setting it up so that if someone requests a certain page at the `http://localhost:5000/` domain, the server sends back the HTML that calls this JS. How you do this depends on how your Node.js app is written. – Daisy Leigh Brenecki Feb 24 '14 at 01:18
  • can't I just set body = data; to do this in exports.init function? now when I go to http://localhost:5000/ in chrome it displays the html code for my server in the body. – Ryan Williams Feb 24 '14 at 01:25
  • 1
    You need to set your `Content-Type` to `text/html`, otherwise Chrome will think it's a plain text file. – Daisy Leigh Brenecki Feb 24 '14 at 03:15
2

You could add '_=' + new Date().getTime(); to the query string of the url. Since it isn't clear whether the url already has a query string attached to it, it's hard to give a more complete answer. It'd be either url += '?_=' + new Date().getTime(); or url += '&_=' + new Date().getTime();.

I'll leave this answer here because it seems to answer the question that the OP was asking. But the solution to the problem the OP was experiencing is Adam Brenecki's answer below.

jameslafferty
  • 2,152
  • 2
  • 21
  • 25
  • does this go in httpRequest.open(POST, 'url_=' + stuff, true); I heard I had to use POST – Ryan Williams Feb 24 '14 at 00:30
  • If you're going to go to POST, you should use POST, or GET for GET. I'm trying to piece it together from the sample you provided and my best bet as to your question. It looks like the crux of what you're asking is how to prevent caching of responses, no? – jameslafferty Feb 24 '14 at 00:31
  • @RyanWilliams You don't have to use POST. GET will work just fine too. It depends entirely on what your requirements are as to whether yu use POST or GET. – Jon Taylor Feb 24 '14 at 00:31
  • @JonTaylor ... but you do need to use POST if you want to POST, no? To do a POST (if that's what's really needed), the OP could look here: http://stackoverflow.com/questions/9713058/sending-post-data-with-a-xmlhttprequest – jameslafferty Feb 24 '14 at 00:34
  • 1
    @jameslafferty yes, of course, I simply meant his question seems to be about preventing caching, which has nothing to do with GET or POST. He would get the same behaviour our of both. – Jon Taylor Feb 24 '14 at 00:36
  • I added the '?_=' + Math.random but I still get the cross domain error T_T – Ryan Williams Feb 24 '14 at 00:41