I've just come across something that has entirely changed my mental image of URLSession caching in iOS.
We were hitting an endpoint that only ever got hit once.
Restarting the app wouldn't hit the endpoint again.
Deleting the app would cause it to hit the endpoint again... but only once.
The header of the response contains...
Cache-Control public, max-age=1800
So it is down to caching. By manually telling the URLSession to ignore the cache it would hit the endpoint again.
In the docs it shows the caching policy and how it works as a workflow diagram.
https://developer.apple.com/documentation/foundation/nsurlrequestcachepolicy/nsurlrequestuseprotocolcachepolicy
But where is the cached data stored once the app is terminated? Surely the app and everything to do with it is removed from memory?
The URLSession is using URLCache for it's caching system. It's used for all network resources. You can access it directly or setting your own through URLSessionConfiguration. The underlying location of the URLCache is on the file system rather than in memory. There is a way to manage cache yourself though. Say, for instance, your response should be encrypted on the device. Slightly bad example, but you get the point. ;)
Here's an article how to manage cache programmatically if you are needing more control over caching.
Related
I have a web app that wants to load bootstrap.min.js
It's on these two CDN's (among others):
https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js
https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js
The odds of a cache hit from some other app using these CDN's is relatively high.
How can I tell the browser to check if they are cached and load from browser cache?
Can a service worker do this?
I believe that there are some privacy/security restrictions in place that attempt that make it difficult to determine, using JavaScript, whether a third-party URL is present in the browser's cache.
Adding a service worker into the mix will not get around those restrictions.
It's possible to use the Fetch API to create a Request with a mode of 'only-if-cached', which will behave more or less in the way you describe, but that will only work if the request's mode is 'same-origin'. In other words, only if the Request is for a first-party URL, not a third-party CDN URL as in your example.
I've built a Progressive Web App that uses caching, but it's unclear to me whether users can (accidentally or on purpose) clear the service worker cache, which may clear my tracking data.
When a user clears their browsing data / cookies, this clears all site storage which includes the SW cache, cookies, local storage, indexeddb, and any other local caching system.
Furthermore, Ctrl-F5 forces a cache refresh, and is intended to abandon all cached content including service worker cache and just retrieve all content from the servers again.
"Clear site data" in Chrome 76 will delete the caches and the worker, however the deleted worker remains "activated and running". So that's a case that needs dealing with.
Whenever I have an issue with a website, one of the first suggestions I will hear is “try to clear your browser cache” along with “and delete your cookies“. So what is this browser cache? What does it store and what is it good for?
I have googled. but didn't find the proper answer.I appreciate if anyone help on this.
A browser cache "caches" (as in keeps local copies) of data downloaded from the internet. The next time your browser needs the same data it can get it from the cache (fast) instead of downloading it over the internet (slow)
The problem is that data can be old. For example imagine the browser cached www.nytimes.com today and 24hrs later you visited www.nytimes.com again. If the browser loaded the cached data it would be old news.
So there are headers (metadata) that the servers send to browser telling them how long they should cache something (if at all).
The data the browser generally caches are "requests" which. In other words if your browser asks for "http://foo.com/bar.html" the first time the browser will "request" that "foo.com" send it "bar.html". If the headers from "foo.com" are set a certain way the browser will the save a local copy of "bar.html". If you request the same thing again the browser may load "bar.html" from it's cache. I say "may" because it depends on the headers sent from the server. The server can say how long (say 10 minutes, 10 hours, 10 days, etc..) or it can say "don't cache this at all, always download the newest version".
If you go to your browser's dev tools (chrome shown below) and look at the network tab (not sure what it's called in other browsers). Load the page again and you can see all the requests. You'll also notice which ones were loaded from the cache
If you click on a request you can see the metadata from both the browser (request headers) and the server (response headers)
The reason clearing the cache often fixes things is if for some reason the server (a bug?) said it was ok to cache or used the cached version but the data on the server has actually been updated. The browser, doing what the server told it to do, is using its copy from the cache, not the newer version which is actually needed. There might also from time to time be bugs in the browser itself related to caching.
When everything is working correctly it's great but if one thing or another is mis-configured or sending the wrong headers then the browser can end up loading old data from the cache instead of downloading the newest data. Clearing your cache effectively forces the browser to download the data again.
You can find out the details of what the various headers do here.
Browser caches are not mere rubbish bins but a mechanism to speed up the way we browse the web. Each website we visit has certain common elements like logos, navigation buttons, GIF animation files, script files etc. It doesn’t make sense for the browser to download each element (also commonly called as Temporary Internet files) when we hop from page to the other and back.
The page elements are downloaded when we visit a website and the browser checks its cache folder for copies when we browse the website. If a copy exists, then the browser doesn’t download the same file again, thus significantly speeding up web browsing speeds.
for more info..
http://www.guidingtech.com/8925/what-are-browser-cache-cookies-does-clearing-them-help/
https://en.wikipedia.org/wiki/Cache_(computing)
First result in Google, this is the proper answer, but I will summarize =]
1) What is Browser Cache?
Cache is a component that stores data so future requests for that data can be served faster; the data stored in a cache might be the results of an earlier computation, or the duplicates of data stored elsewhere.
2) What does it store?
Web browsers and web proxy servers employ web caches to store previous responses from web servers, such as web pages and images.
3) What is it good for?
Web caches reduce the amount of information that needs to be transmitted across the network, as information previously stored in the cache can often be re-used. This reduces bandwidth and processing requirements of the web server, and helps to improve responsiveness for users of the web.
I am using AFNetworking with NSURLCache. Requests are created with NSURLRequestUseProtocolCachePolicy. App receives responses with headers:
Etag = "1398684731";
Cache-Control = "public";
and everything works perfect. But now I need to add an offline mode.
How it should work:
If internet connection is available everything should work as usual
(application asks back-end for new data and if it has different
Etag new data is downloaded if Etag is the same - cached response
is used).
If there is no internet connection - cached response is
used.
The problem is that in offline mode requests fail.
I have tried to solve this using various Cache-Control options but it seems that it does not work this way.
I have found possible solution here https://stackoverflow.com/a/15885318/3140927 . It should work but it is not very elegant and I think something might have changed in the last year.
Also I have found that "NSURLCache was not made for explicit offline scenarios and that it was designed to speed up Safari and should not be used for manual downloads". Will SDURLCache be better for my purposes?
So what could be the best way to implement offline mode?
It sounds like you want the request to succeed, even though the cache says the data has expired and should be retrieved from the server. You may have some luck setting the cache policy (different policy for online vs. offline) of certain requests where you'd rather use stale data than fail.
Great Link is here->
SDURLCache with AFNetworking and offline mode not working
Today I tried to solve exactly the same problem with this article and it works pretty well: http://blog.originate.com/blog/2014/02/20/afimagecache-vs-nsurlcache/. The key point is here to subclass NSURLCache to make your cache independent from response headers.
I've found couple mistypes in examples, but hope it still will be helpful for you!
I actually have more than one question regarding this... I'm still new to NSURLCache and UIWebViews but somehow got the basics down I think.
Anyway, I was able to successfully implement Caching for my UIWebView(I think). I initialized the NSURLCache. My UIWebView loads its contents with the loadRequest: method. I assigned the ViewController that owns the UIWebView as it's delegate. I also had the ViewController implement NSURLConnectionDataDelegate. I implemented the connection:willCacheResponse: method just to log a message in the console so I could check that caching was done. I also logged the current disk and memory usage. It increases after the caching so I can see that it did work.
However, when I load the page again, I think the request is sent again to the server because the connection delegate methods like connection:didReceiveResponse: and connection:willCacheResponse are being called.
I also wanted to try getting the cachedResponse from the cache by using cachedResponseForRequest:. I called this method in webViewDidFinishLoad: but it always returns null. Did caching really work?
How can you tell if the WebView loaded from the cache? Am I misusing cachedResponseForRequest:? And on another note, what proper Control-Cache header values should be present in the very least for caching? I'm testing on google's homepage URL and it returns the private value for its Cache Control header but I can see that caching works because the connection:willCacheResponse: is called.
Help please?
If you run a HTTP proxy like Charles or Fiddler you can keep tabs on what network traffic is actually going out over the wire(less).
You can also inspect the request/response headers to see whether the response is indeed destined for the cache.
Note that in some cases you might see a conditional-GET (returns a 304) meaning the client asked for content that it has in its cache, but only wants to download the content if the server has a more recent version.