Будет ли предотвращено кэширование файла с заголовком ответа `Cache-Control:Private` в NSURLCache?
Будет ли файл с заголовком ответа Cache-Control:Private
быть защищенным от кэширования в NSURLCache
? Либо общий кеш (как в setSharedCache
а также NSURLCache.sharedCache()
) или заказной?
Чтобы расширить, у меня есть UIWebView
что мне нужно получить доступ, когда в автономном режиме. Источник этого WebView
имеет несколько внешних файлов CSS и JS, связанных с ним. Я могу кэшировать большую часть сайта (CSS и т. Д. Выглядит на месте), однако, похоже, что он не кэширует конкретный файл JavaScript, который предоставляет важную информацию для сайта. Разница, которую я заметил между файлом, который не будет кэшироваться, и остальным, заключается в том, что его Cache-Control установлен в private (остальные являются общедоступными). Тем не менее, из того, что я прочитал, установка элемента управления кэшированием на частный является предотвращением кэширования на прокси. Повлияет ли это на кэширование на iOS?
Настройка кеша
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let URLCache: NSURLCache = NSURLCache(memoryCapacity: 10 * 1024 * 1024,
diskCapacity: 50 * 1024 * 1024,
diskPath: nil)
NSURLCache.setSharedURLCache(URLCache)
println("Disk cache usage: \(NSURLCache.sharedURLCache().currentDiskUsage)")
// http://stackru.com/questions/21957378/how-to-cache-using-nsurlsession-and-nsurlcache-not-working
sleep(1)
return true
}
Использование кеша
func getWebPage(onCompletion: (NSString, NSURL) -> Void) {
let url = getApplicationSelectorURL()
let request = NSURLRequest(URL: url, cachePolicy: .ReturnCacheDataElseLoad, timeoutInterval: 10.0)
let queue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler: { response, data, error in
println("Web page task completed")
var cachedResponse: NSCachedURLResponse
if (error != nil) {
println("NSURLConnection error: \(error.localizedDescription)")
if let cachedResponse = NSURLCache.sharedURLCache().cachedResponseForRequest(request) {
if let htmlString = NSString(data: cachedResponse.data, encoding: NSUTF8StringEncoding) {
onCompletion(htmlString, url)
} else {
println("htmlString nil")
}
} else {
println("cacheResponse nil")
}
} else {
cachedResponse = NSCachedURLResponse(response: response, data: data, userInfo: nil, storagePolicy: .Allowed)
NSURLCache.sharedURLCache().storeCachedResponse(cachedResponse, forRequest: request)
if let htmlString = NSString(data: data, encoding: NSUTF8StringEncoding) {
onCompletion(htmlString, url)
} else {
println("htmlString nil")
}
}
})
}
Заполнение UIWebView
APICommunicator.sharedInstance.getWebPage({ htmlString, url in
dispatch_async(dispatch_get_main_queue(),{
self.webView.loadHTMLString(htmlString, baseURL: url)
})
})
2 ответа
Я закончил тем, что создал метод, похожий на NSURLConnectionDelegate
метод willCacheResponse
и заменяя Cache-Control:private
заголовок.
метод willCacheResponse
func willCacheResponse(cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse?
{
let response = cachedResponse.response
let HTTPresponse: NSHTTPURLResponse = response as NSHTTPURLResponse
let headers: NSDictionary = HTTPresponse.allHeaderFields
var modifiedHeaders: NSMutableDictionary = headers.mutableCopy() as NSMutableDictionary
modifiedHeaders["Cache-Control"] = "max-age=604800"
let modifiedResponse: NSHTTPURLResponse = NSHTTPURLResponse(
URL: HTTPresponse.URL!,
statusCode: HTTPresponse.statusCode,
HTTPVersion: "HTTP/1.1",
headerFields: modifiedHeaders)!
let modifiedCachedResponse = NSCachedURLResponse(
response: modifiedResponse,
data: cachedResponse.data,
userInfo: cachedResponse.userInfo,
storagePolicy: cachedResponse.storagePolicy)
return modifiedCachedResponse
}
вызывающий метод
if let cachedResponse = self.willCacheResponse(
NSCachedURLResponse(response: response,
data: data,
userInfo: nil,
storagePolicy: .Allowed)) {
NSURLCache.sharedURLCache().storeCachedResponse(cachedResponse, forRequest: request)
}
И теперь он отображается правильно, когда в автономном режиме. Какое путешествие
Да, ответы с политикой управления частным кэшем не кэшируются NSURLCache
, В RFC № 2616 говорится
private: указывает, что все или часть ответного сообщения предназначены для одного пользователя и НЕ ДОЛЖНЫ кэшироваться общим кешем. Это позволяет исходному серверу утверждать, что указанные части ответа предназначены только для одного пользователя и не являются действительным ответом на запросы других пользователей. Частный (не общий) кеш МОЖЕТ кешировать ответ.
Что ж, NSURLCache
использует sharedCache, который вы даже установили в коде, который вы разместили. Я думаю, это объясняет почти все.
Решением является либо изменение поведения сервера, либо переопределение некоторых методов NSURLCache
учебный класс. (Вы можете, например, переписать заголовок на стороне клиента, но это должно быть довольно ужасно.)