4

I am using NSURLSession for networking and making POST requests to a server. I want to be able to cache these requests, however the URL is always the same.

Is it possible to cache with NSURLCache and change the cache key to something unique such as the request body?

agandi
  • 561
  • 7
  • 15

1 Answers1

0

By default, IIRC, POST requests are not cached at all. But yes, you can certainly do it. IIRC, on the NSURLSession side, the only thing you can control is whether the request gets cached or not. To actually control the name under which it is cached, you'll need to implement a custom URL protocol. I've never done what you're trying to do, but I'm pretty sure you'd do it roughly as follows:

  • Create an NSURLProtocol subclass, and provide it via the protocolClasses property on your session configuration. From that point on, your class gets called first whenever any that session makes a URL request.

  • In that subclass, in your startLoading method, use setProperty:forKey:inRequest: to tag the request as having been processed by your protocol.

  • In your canInitWithRequest method, call propertyForKey:inRequest: to see if the request is already tagged, and if so, return NO. That way, you'll see each request exactly once.

  • In your startLoading method, start a new data task with the tagged request.

  • In stopLoading, cancel the task.

  • In canonicalRequestForRequest:, do your conversion. You might have to use setProperty:forKey:inRequest: to store the original, unmodified URL, just in case you get back the modified URL. (I'm not sure.)

  • I don't think you'll need to implement requestIsCacheEquivalent:toRequest:, but keep it in mind, just in case I'm wrong. You might be able to implement that instead of the canonicalization method, also.

dgatwood
  • 10,129
  • 1
  • 28
  • 49
  • @dgatwoord, I've checked the documentation of NSURLCache, but I can't find any about if it can cache POST request. Could you please share with me ? – aelam Aug 23 '16 at 08:53
  • By default, the NSURLSession/Connection does not cache POST requests, as they are not guaranteed to be idempotent. That said, the cache itself is, if memory serves, pretty much just a dumb key-value store that gets persisted to disk. If you put an object in there, it should be there when you request it. The explanation above tells how to do so. (You might also have to change the request type to "GET" when you add it to and retrieve it from the cache. I'm not sure.) – dgatwood Aug 23 '16 at 20:55
  • Alternatively, if the above steps don't work, you can always start with the stuff listed above, and then add code to store the data yourself in a file. There's nothing that says you have to use an actual NSURLCache object to do your caching. It's just a convenient way to do so. :-) – dgatwood Aug 23 '16 at 20:56
  • I am setting the cache policy NSURLRequestReturnCacheDataElseLoad in a NSMutableURLConnection and the NSURLSession is returning a cached version of the response from an HTTP post request, so I suppose your assumption is nor completely right? – David Feb 17 '17 at 13:10
  • There are very limited situations where the spec allows some caching of the response to POST requests (see https://www.mnot.net/blog/2012/09/24/caching_POST). It is possible that Apple recently modified their code to allow caching in those limited circumstances, but chances are, if you're seeing caching of POST requests, it is probably a bug, and you should file a bug at bugreport.apple.com ASAP. – dgatwood Feb 17 '17 at 21:43