Chrome displays ajax response when pressing back button

AjaxGoogle ChromeBack Button

Ajax Problem Overview


I've come across a problem that if I use jQuery's Get method to get some content, if I click back, instead of it actually going back one page in the history, it instead shows the content returned by the Ajax query.

Any idea's?

http://www.dameallans.co.uk/preview/allanian-society/news/56/Allanian-test

On the above page, if you use the pagination below the list of comments you will notice when clicking back after changing a page, that it shows the HTML content used to generate the list of comments.

I've noticed it doesn't always do it, but if you click on a different page a few times and click the back button, it simply displays json text within the window instead of the website.

For some reason, this is only affecting Chrome as IE and Firefox work ok.

Ajax Solutions


Solution 1 - Ajax

Make sure your AJAX requests use a different URL from the full HTML documents. Chrome caches the most recent request even if it is just a partial.

https://code.google.com/p/chromium/issues/detail?id=108425

Solution 2 - Ajax

Just in case you are using jQuery with History API (or some library like history.js), you should change $.getJSON to $.ajax with cache set to false:

$.ajax({
	dataType: "json",
	url: url,
	cache: false,
	success: function (json) {...}
});

Solution 3 - Ajax

Actually this is the expected behavior of caching system according to specs and not a chrome issue. The cache only differentiate requests base on URL and request method (get, post, ...), not any of the request headers.

But there is a Vary header to tell browser to consider some headers when checking the cache. For example by adding Vary:X-Requested-With to the server response the browser knows that this response vary if request X-Requested-With header is changed. Or by adding Vary:Content-Type to the server response the browser knows that this response vary if request Content-Type header is changed.

You can add this line to your router for PHP:

header('Vary:X-Requested-With');

And use a middleware in node.js:

app.use(function(req, res) {
    res.header('Vary', 'X-Requested-With');
});

Solution 4 - Ajax

You can also add a random value to the end of the ajax url. This will ignore the previous chrome cache and will request a new version

url = '/?'+Math.random()

Solution 5 - Ajax

Just add the following header to the Response headers :

Vary: Accept

Solution 6 - Ajax

I couldn't give different urls for each ajax request as it was an ajax pagination, declaring no cache on headers did nothing, so i included a little javascript in the view only when headers were for the ajax request:

<script>
if (typeof jQuery == 'undefined') {
	window.location = "<?php echo $this->here; ?>";
}
</script>

It is a dirty trick, but it works, if the ajax content is normally loaded, the container has Jquery loaded so it does nothing. But if you load the ajax supposed content without the surrounding content, Jquery is missing (at least in my case), so i redirect to the current page requesting a normal GET page with all the headers and scripts.

If you put it in the top of the page, the user won't notice because it won't wait till the page loads, it will redirect as soon as the browser gets this 4 lines...

Replace here; ?> by the current url in your APP, this was a CakePhp 2.X

Solution 7 - Ajax

Still had this problem in 2021 in Chrome.

Problem is doing underlying ajax request to the same url as the one the user is currently on. I was working in Symfony and the complete fix that did the work for me was

$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('max-age', 0);
$response->headers->addCacheControlDirective('s-maxage', 0);
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->headers->addCacheControlDirective('no-store', true);

/**
 * from https://stackoverflow.com/a/1975677/5418514
 *
 * The HTTP request header 'Accept' defines the Content-Types a client can process.
 * If you have two copies of the same content at the same URL, differing only in Content-Type,
 * then using Vary: Accept could be appropriate.
 */
$response->headers->set('Vary', 'Accept');

Solution 8 - Ajax

The @abraham's answer is right. I just wanted to post a solution for Rails: all you need is just add different path to routes.rb.

In example, I have resource :people and I want to compose index page from ajax parts one of those is list of people. The straightforward way is to create index.js.erb and to load partial via ajax using url: people_path. But here occurs the issue.

So, for Rails, it needs just add a different route, like

get 'people_list', to: 'people#index', as: :people_list, format: :js

Solution 9 - Ajax

If I want to use index method of a laravel controller returns both html and json response, I add a get parameter at the end of the endpoint to pass browser caching:

axios.get(url, {params: {ajax: 1}})

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGavinView Question on Stackoverflow
Solution 1 - AjaxabrahamView Answer on Stackoverflow
Solution 2 - AjaxDmitrii SorinView Answer on Stackoverflow
Solution 3 - AjaxAliView Answer on Stackoverflow
Solution 4 - AjaxastroanuView Answer on Stackoverflow
Solution 5 - AjaxHamed KamravaView Answer on Stackoverflow
Solution 6 - AjaxGestudio CloudView Answer on Stackoverflow
Solution 7 - AjaxJulesezaarView Answer on Stackoverflow
Solution 8 - AjaxatlascoderView Answer on Stackoverflow
Solution 9 - AjaxmcanvarView Answer on Stackoverflow