WKWebCache Cache - ios

I need to cache webview url on WKWebview. I'm able to do it using the below configuration
var webViewConfiguration:WKWebViewConfiguration {
get {
// Create WKWebViewConfiguration instance
let webCfg:WKWebViewConfiguration = WKWebViewConfiguration()
// Configure the WKWebViewConfiguration instance with the WKUserContentController
webCfg.userContentController = userContentController
webCfg.websiteDataStore = WKWebsiteDataStore.default()
webCfg.processPool = ProcessPool.shared.processPool
return webCfg
}
}
and while loading the webview I'm using the below code:
let request = URLRequest(url: self.url!, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 600)
self.webView.load(request)
Issue I'm facing right now is the cache is taking time on every launch. i.e on every launch webview is taking a lot of time to load, after one load it is loading fast.
What I need to achieve is once webview is loaded, it should load faster on consecutive loads.

.useProtocolCachePolicy is the default policy for URL load requests. It should work for your case.
let request = URLRequest(url: self.url!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 600)

Using the default .useProtocolCachePolicy instead of .returnCacheDataElseLoad is OK. This policy will automatically look at the response from the server to decide whether or not it should actually go and grab the data again. On the server side, set the Cache-Control HTTP headers max age for its responses.

Related

iOS background download not respecting httpMaximumConnectionsPerHost

I am on iOS 14.2...
I have a URLSession that i configure that way:
private lazy var backgroundURLSession: URLSession = {
let config = URLSessionConfiguration.background(withIdentifier: "background-download")
config.sessionSendsLaunchEvents = true
config.httpMaximumConnectionsPerHost = 2
config.timeoutIntervalForRequest = 120
return URLSession(configuration: config, delegate: self, delegateQueue: nil)
}()
I give it like 100 URLs to download
let downloadTask = session.downloadTask(with: offlineTile.url)
downloadTask.resume()
and even with httpMaximumConnectionsPerHost = 2 the server gets ALL requests at ONCE... ?!?
What could I be doing wrong
One more note: We have a Varnish Cache in the background... and noticed that the behavior differs, if Varnish is set to pipe (no caching)
In our case it was the load balancer of our server that did not properly to it's https termination, which caused iOS to send all requests at basically once.

how to support incognito/private mode in wkwebview/uiwebview

I am working on a incongnito browser.I am using wkwebview when I clear all the cookies I can see that popular search engine like google remembers the searches that has been made.
I tried cleaning all the cookies in NSHTTPCookieStorage and resetcookies using NSURLSession but its still not working.
Set nonpersistentdatastore for wkwebsitedatastore for wkwebviewconfiguration for wkwebview
Set NSURLrequestreloadcacheignoringlocalandremotecachedata for NSURlrequest in uiwebview
Reference
Creating a non-tracking in-app web browser
Private browsing in iOS using WKWebView
As per apple documentation:
To support private browsing,create a data store object and assign it to the websiteDataStore property of a WKWebViewConfiguration object before you create your web view. The default() method returns the default data store that saves website data persistently to disk. To implement private browsing, create a nonpersistent data store using the nonPersistent() method instead.
let webConfiguration = WKWebViewConfiguration()
webConfiguration.processPool = WKProcessPool()
webConfiguration.websiteDataStore = WKWebsiteDataStore.nonPersistent()
let webView = WKWebView(frame: self.webContainerView.bounds, configuration: webConfiguration)
// Set up request
if let requestURL = URL(string: "enter_url_to_load") {
var request = URLRequest(url: requestURL)
request.httpShouldHandleCookies = false
request.cachePolicy = .reloadIgnoringLocalAndRemoteCacheData
webView.navigationDelegate = self
webView.load(request)
}
self.webContainerView.addSubview(webView)

How to save dynamic webpage in cache using UIWebview in Swift 3

I am developing an application(Swift 3 using UIWebview). I need to load webpages into webview and save some webpages into cache. If there is not internet user will able to see those pages. But I am confused on how to save whole webpage in cache. The main thing is we need to show pages back even if there is not internet.
I used the following documention : http://nshipster.com/nsurlcache/
and https://developer.apple.com/reference/foundation/urlcache
let url = NSURL(string: load_url1)
let request = NSURLRequest(url: url as! URL,cachePolicy: NSURLRequest.CachePolicy.returnCacheDataElseLoad, timeoutInterval: 60)
self.webView.loadRequest(request as URLRequest);
Has anyone implemented this before. Please provide some demo code as this is my first attempt on cache
Just use
let url = URL(string: urlString)
var urlRequest = URLRequest(url: url!)
urlRequest.cachePolicy = .returnCacheDataElseLoad
webView.loadRequest(urlRequest)

WKWebview injecting cookie header cause redirect loop

I'm trying to inject session cookies I've acquired separately into a WKWebview request, which turns out to be quite a pain...
I managed to inject the session cookies using this solution, as follows:
// Acquiring the cookies
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headers, for: s.request!.url!)
//Appending all the cookies into one raw string.
var cookiesRawString = ""
for c in cookies {
cookiesRawString += "\(c.name)=\(c.value); "
}
var req: URLRequest = try! URLRequest(url: URL, method: method)
// Then the injection itself
request.setValue(cookiesRawString, forHTTPHeaderField: "Cookie")
webView.load(req)
Let me quickly explain the server logic with pseudo code:
Server receive call to endpoint /endpoint1 with initial session cookies appended
It then proceed to redirect the client to /endpoint2 with user generated token appended in the url.
requesting the second endpoint with token appended results in the final redirect to /endpoint3 with Set-Cookie header containing one time session cookies
/endpoint3 with the one time session cookies appended results in 200 response, and the user is recognized.
The problem is that for some reason the when I append the cookies to the initial request using the method above, it results with a redirect loop, while on the Android platform it works flawless (I used there a similar injection method).
The only difference that I saw between them was that the android app injected the cookies only on the initial request, and all the subsequent redirect calls were without those session cookies.
While the ios repeated the initial session cookies on all the redirect calls (even ignoring the server set-cookie header and appending the initial session cookies..).
Am I doing something wrong? How can I make the wkwebview use the injected cookies only on the initial request?
Edit 1: Also tried falling back to UIWebview, but it produces the same results, it seems that injecting the cookies as a header is not good, but I tried using HTTPCookieStorage, but it won't save the cookies!
// the count is 7
var cookiesCount = HTTPCookieStorage.shared.cookies(for: s.request!.url!)?.count
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headers, for: s.request!.url!)
for c in cookies {
HTTPCookieStorage.shared.setCookie(c)
}
// Count is still 7!
cookiesCount = HTTPCookieStorage.shared.cookies(for: s.request!.url!)?.count
Edit 2:
Well I found out the UIWebview is using a global instance of the cookie storage, the same as alamofire (which I've used to fetch the session cookies), so there was no need to add the cookies manually, the site recognized the user.
But I still prefer to use WKWebview, as the UIWebview memory leak sky rockets (over 100 mb after couple of web pages navigation!).
Is there a way to use the global cookie jar (used by alamofire) in WKWebview??
I think this might be unrelated, but i had a similar issue.
The reason was the modified cookie was messing up all my subsequent request using NSURL.sharedSession. It turns out the cookie set using WKWebView was wiping out the headers from NSURLSession.sharedSession. I think the cookie storage is shared across multiple sessions. So, i ended up using EphemeralSession, instead of sharedSession.
I managed to get it working on WKWebview, using a hackish solution:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction:
WKNavigationAction, decisionHandler:
#escaping (WKNavigationActionPolicy) -> Void) {
let url = navigationAction.request.url!.absoluteString
if UserAppendix.isLogin && url != previousNavigateUrl {
previousNavigateUrl = url
if url.contains("/endpoint1") {
let headerFields = navigationAction.request.allHTTPHeaderFields
let headerIsPresent = headerFields!.keys.contains("Cookie")
if headerIsPresent {
decisionHandler(WKNavigationActionPolicy.allow)
} else {
var req = URLRequest(url: navigationAction.request.url!)
let cookies = NetworkAppendix.httpSessionCookies
let values = HTTPCookie.requestHeaderFields(with: cookies)
req.allHTTPHeaderFields = values
webView.load(req)
decisionHandler(WKNavigationActionPolicy.cancel)
}
}
else if firstTime {
firstTime = false
let req = URLRequest(url: navigationAction.request.url!)
webView.load(req)
decisionHandler(WKNavigationActionPolicy.cancel)
}
else {
decisionHandler(.allow)
}
}
else {
decisionHandler(.allow)
}
}
I set the cookies on the first request, and on the second request break the flow and create a new request (with the redirect url), to avoid the session cookies I set on the first request, all subsequent requests are treated the same.
I know it's not perfect, but it gets the job done.

Getting redirected url from instagram server

I am grabbing images from instagram and am receiving urls like "http://instagram.com/p/1JiWygQUSu/media/?size=l" the issue is this url directs to "https://scontent-lax3-1.cdninstagram.com/hphotos-xfa1/t51.2885-15/e15/1527608_451589571655110_1239072675_n.jpg" I need the file extension to properly cache the image on a user device.
The first url is redirecting to the second. I need a way to retrieve the second url from the first.
Tried using this code but it just returns the original url:
let urlString = "http://instagram.com/p/1JiWygQUSu/media/?size=l"
let request: NSMutableURLRequest = NSMutableURLRequest(URL: NSURL(string:urlString)!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringCacheData, timeoutInterval: 15.0)
request.HTTPMethod = "HEAD"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {
(response, data, error) in
print("instaResponse \(response?.URL)")
})
Try looking at NSURLSessionTaskDelegate method
- URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler: Documentation here.
You should be able to handle the redirect there and cache the image. Alternatively, you can try using SDWebImage or AFNetworking which have image caching built in, and probably handle the redirect case already.

Resources