6

I've got a page that can be accessed at URL /products. When I visit it in a browser it responds with a full page within a layout. Here is a simplified example of request headers and response body:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

<layout>
<products />
</layout>

When a user does some search the javascript updates results via AJAX. The results are rendered without a layout since it takes time to render and I don't need it anyway:

Accept: */*;q=0.5, text/javascript, application/javascript, application/ecmascript, application/x-ecmascript
X-Requested-With: XMLHttpRequest

<products />

So, this worked fine until I added caching Cache-Control: private, max-age=3600. Initially I though I would add Vary: X-Requested-With header and a browser would distinguish the two responses. However, when I get /products via AJAX and then visit /products in the browser it displays the partial AJAX response.

Is there a simple way to solve this problem?

P.S. I'm using Ruby on Rails and jQuery if that matters.

Simon Perepelitsa
  • 20,350
  • 8
  • 55
  • 74
  • 2
    Have you tried `Vary: Accept`? – regilero Jul 10 '12 at 12:09
  • Yes, it does not work also. I think the browser is properly caching both responses. But because of Content-Type: text/html it treats them equally and shows the last one which happens to be partial. – Simon Perepelitsa Jul 13 '12 at 09:57
  • Actually, I've tried to respond with JSON, and now it shows JSON. So this does not depend on Content-Type: text/html. I'm quite surprised that "Vary" does not have any effect here. – Simon Perepelitsa Jul 13 '12 at 10:16

6 Answers6

1

Have your Ajax call use a different URL like /products/partial.

SargeATM
  • 2,483
  • 14
  • 24
  • This looks like the only solution for now. But it means that I will need to modify each URL on the client-side javascript which is not very convenient. – Simon Perepelitsa Jul 13 '12 at 09:58
0

You should have a diferent url for partial results (i.e ?partial=yes or something like this...)

OR

you can get the whole page via ajax and extract just the part you want using jquery.load().

$("#productsContainerHolder").load("/my/products/url #productsContainer", { myParam: "beer", myParam2: "cold"});

$.load will call your server with a 'GET' method, retrieve all contents, extract the #productsContainer from there and insert on "#productsContainerHolder"

<div id="productsContainerHolder">
    <div id="productsContainer>
         ...
    </div>
</div>
Marcelo De Zen
  • 9,439
  • 3
  • 37
  • 50
0

This article by Steve Luscher describes a similar case the problem was more intermittent than what you describe. The suggested solutions are:

  1. Cancel all of the AJAX requests at the time the form is submitted

  2. Use a different URL according to the response you expect

Steve went for #1 using cancel() on the ajax requests.

You don't mention what browsers you have used, there is a browser related question here

Community
  • 1
  • 1
Tommy Grovnes
  • 4,126
  • 2
  • 25
  • 40
  • 1
    The first solution is not really applicable in my situation. But I'm glad to see other people reporting the same problem. The question you linked does not seem to be related for me, but I'm using Safari. Tested in Firefox also. – Simon Perepelitsa Jul 13 '12 at 10:15
0

Use Vary: Accept. This should work.

Bharath
  • 797
  • 6
  • 14
  • I have tried this but the issue is still there. Copying my thoughts from above: I think the browser is properly caching both responses. But because of Content-Type: text/html it treats them equally and shows the last one which happens to be partial. – Simon Perepelitsa Jul 13 '12 at 10:02
0

probably the easiest is to set to 'False' the 'cache' parameter of the Ajax method of jquery. It will automatically append a timestamps to the URI preventing it from being cached.

This can be done application wide with the following snippet:

$.ajaxSetup({
    cache: false
});

If the cache does matter even for dynamic request, you can generate yourself the timestamp based on the date along with the hour.

yadutaf
  • 6,840
  • 1
  • 37
  • 48
0

Try sending must-revalidate instead of private (which is more for proxy).

Cache-Control: max-age=3600, must-revalidate

I recommend reading this article: http://www.mnot.net/cache_docs/ it might help. And also use Mark's tool http://redbot.org/ to test your results to eliminate your local machine or isp or what not.

Anthony Hatzopoulos
  • 10,437
  • 2
  • 40
  • 57