Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Safari on iOS 6 caching $.ajax results?

Since the upgrade to iOS 6, we are seeing Safari's web view take the liberty of caching $.ajax calls. This is in the context of a PhoneGap application so it is using the Safari WebView. Our $.ajax calls are POST methods and we have cache set to false {cache:false}, but still this is happening. We tried manually adding a TimeStamp to the headers but it did not help.

We did more research and found that Safari is only returning cached results for web services that have a function signature that is static and does not change from call to call. For instance, imagine a function called something like:

getNewRecordID(intRecordType) 

This function receives the same input parameters over and over again, but the data it returns should be different every time.

Must be in Apple's haste to make iOS 6 zip along impressively they got too happy with the cache settings. Has anyone else seen this behavior on iOS 6? If so, what exactly is causing it?


The workaround that we found was to modify the function signature to be something like this:

getNewRecordID(intRecordType, strTimestamp) 

and then always pass in a TimeStamp parameter as well, and just discard that value on the server side. This works around the issue.

like image 411
user1684978 Avatar asked Sep 20 '12 06:09

user1684978


People also ask

Does iPhone Safari have a cache?

In the Safari app , you can erase your browsing history and data to clear the cache on your iPhone. This removes the history of websites you visited and recent searches from your device.

Does Safari store cache?

A cache is a store of data. When you visit a website on your Mac, iPhone, or iPad, the Safari browser keeps a snapshot of the pages you view. If you go back to that website, Safari loads the cached page in an instant, instead of taking the time to retrieve the page from the internet again.

How do I view cached data in Safari?

To view the Site Cache Storage in Safari iOS, one needs to open the Settings on their iOS device and scroll down to Safari Browser. From there the users need to go to the advanced option and tap on Website Data to view the storage Details.

Where does Safari keep cache?

The location of cache files is in your ~/Library/Containers/com. apple. Safari/Data/Library/Caches (earlier versions of macOS: ~/Library/Caches/ ) folder.


2 Answers

I hope this can be of use to other developers banging their head against the wall on this one. I found that any of the following prevents Safari on iOS 6 from caching the POST response:

  • adding [cache-control: no-cache] in the request headers
  • adding a variable URL parameter such as the current time
  • adding [pragma: no-cache] in the response headers
  • adding [cache-control: no-cache] in the response headers

My solution was the following in my Javascript (all my AJAX requests are POST).

$.ajaxSetup({     type: 'POST',     headers: { "cache-control": "no-cache" } }); 

I also add the [pragma: no-cache] header to many of my server responses.

If you use the above solution be aware that any $.ajax() calls you make that are set to global: false will NOT use the settings specified in $.ajaxSetup(), so you will need to add the headers in again.

like image 45
Dave Avatar answered Dec 13 '22 06:12

Dave


After a bit of investigation, turns out that Safari on iOS6 will cache POSTs that have either no Cache-Control headers or even "Cache-Control: max-age=0".

The only way I've found of preventing this caching from happening at a global level rather than having to hack random querystrings onto the end of service calls is to set "Cache-Control: no-cache".

So:

  • No Cache-Control or Expires headers = iOS6 Safari will cache
  • Cache-Control max-age=0 and an immediate Expires = iOS6 Safari will cache
  • Cache-Control: no-cache = iOS6 Safari will NOT cache

I suspect that Apple is taking advantage of this from the HTTP spec in section 9.5 about POST:

Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.

So in theory you can cache POST responses...who knew. But no other browser maker has ever thought it would be a good idea until now. But that does NOT account for the caching when no Cache-Control or Expires headers are set, only when there are some set. So it must be a bug.

Below is what I use in the right bit of my Apache config to target the whole of my API because as it happens I don't actually want to cache anything, even gets. What I don't know is how to set this just for POSTs.

Header set Cache-Control "no-cache" 

Update: Just noticed that I didn't point out that it is only when the POST is the same, so change any of the POST data or URL and you're fine. So you can as mentioned elsewhere just add some random data to the URL or a bit of POST data.

Update: You can limit the "no-cache" just to POSTs if you wish like this in Apache:

SetEnvIf Request_Method "POST" IS_POST Header set Cache-Control "no-cache" env=IS_POST 
like image 164
Kieran Avatar answered Dec 13 '22 06:12

Kieran