I am using the following code for caching, the response received form the server has the following headers. Is there any header that needs to be set from the request side, for the caching to work for 10 seconds of age.
Connection Received Resopnse Headers= [Date: Sat, 12 Sep 2015 22:51:16 GMT, Transfer-Encoding: Identity, Server: Apache-Coyote/1.1, Content-Type: application/json;charset=UTF-8, Expires: Sat, 12 Sep 2015 22:51:26 GMT, Cache-Control: max-age=10, must-revalidate]
The mighty code which is not caching.
import UIKit
class HTTPJSONDonwload: NSObject , NSURLConnectionDataDelegate , NSURLConnectionDelegate {
static let httpjsonDownloader:HTTPJSONDonwload = HTTPJSONDonwload()
func startDownload(){
let serverRequest = getServerURL()
NSURLConnection(request: serverRequest, delegate: self, startImmediately: true)
}
func getServerURL() -> NSMutableURLRequest{
let request:NSMutableURLRequest = NSMutableURLRequest(URL:NSURL(string:"http://citiesfav-jcitiesj.rhcloud.com/Cache/getAllCities")! )
request.cachePolicy = NSURLRequestCachePolicy.UseProtocolCachePolicy
request.HTTPMethod = "POST"
return request
}
func connection(connection: NSURLConnection, didReceiveData data: NSData) {
print("Connection Data= \(NSString(data: data, encoding: NSUTF8StringEncoding))")
}
func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
print("Connection Received Resopnse Headers= \((response as! NSHTTPURLResponse).allHeaderFields)")
}
func connection(connection: NSURLConnection, willCacheResponse cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse? {
print("Connection will cache Response")
return cachedResponse
}
}
After removing must-revalidate from the header it was still fetching the request.
Connection Received Resopnse Headers= [Cache-Control: max-age=10, Transfer-Encoding: Identity, Date: Sun, 13 Sep 2015 18:35:43 GMT, Content-Type: application/json;charset=UTF-8, Server: Apache-Coyote/1.1, Expires: Sun, 13 Sep 2015 18:35:53 GMT]
Later findings show the POST request does get cached, but does not work like GET, where max-age is considered.
func startDownload(){
let serverRequest = getServerURL()
let cache = NSURLCache.sharedURLCache()
let response = cache.cachedResponseForRequest(serverRequest)
if response != nil {
serverRequest.cachePolicy = NSURLRequestCachePolicy.ReturnCacheDataDontLoad
}
NSURLConnection(request: serverRequest, delegate: self, startImmediately: true)
}
tl;dr
You need to use
GET
instead ofPOST
.Lengthy Explanation
The issue is that you're request is a
POST
.In general,
POST
requests are used to create (or sometimes also to update) a resource on the server. Reusing the cached response for a creation or update request doesn't make much sense because you have to send the request to the server anyway (otherwise nothing is going to be created or updated). It seems that iOS automatically circumvents the cache onPOST
requests.In your particular case, however, you don't really need the
POST
because you're merely reading data from the server. That means you should use aGET
request instead.I verified that the iOS system actually reuses the cache with the following snippet.
When I run this in the simulator and monitor the network calls with Charles Proxy, I indeed only see two events:
The first call is the initial request
and the second call is the third request which was issued after a delay of 11 seconds.
Note that the second request, which was issued after 5 seconds, does not appear which means that the response was retrieved from the cache. The delegate methods of
NSURLConnection
will, however, still be called just as if the response came from the network. With the logging output in your code you'll, therefore, see all three requests on the console.Note that there is no
Connection will cache Response
after the second request because the response was retrieved from the cache and there is no point in caching it again.