我使用以下代码从TfL下载一些数据。
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api.tfl.gov.uk/StopPoint/490012211N/Arrivals"]];
[[session dataTaskWithRequest:req
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSLog(@"Loaded Succesfully");
}
NSCachedURLResponse *resp = [[NSURLCache sharedURLCache] cachedResponseForRequest:req];
if (resp) {
NSLog(@"Response in cache");
}
[[session dataTaskWithRequest:req
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSLog(@"Loaded Sucessfully again");
}
}] resume];
}] resume];
响应的缓存控制头字段为public, must-revalidate, max-age=5, s-maxage=10
这似乎意味着即使第二个请求在max-age给出的5秒内,服务器也会发送请求。如果我使用Charles编辑响应并删除必须重新生效,那么上面的代码只会向服务器发送一次请求。
HTTP / 1.1规范说
该缓存在变为陈旧以响应a之后不得使用该条目 后续请求,而不首先使用原始服务器重新验证它。
对于must-revalidate
,但似乎iOS似乎忽略了"它变得陈旧"部分?并将must-revalidate
表示忽略max-age。那么如何将字段设置为根本不缓存呢?我已经检查过并且请求/响应正被添加到缓存中,所以看起来must-revalidate
只是膨胀缓存,因为它不会使用它,但仍然将它添加到缓存中?
服务器错误地将must-revalidate
与max-age
结合使用,或者iOS处理must-revalidate
的方式不正确吗?
有没有办法拦截回复,以便我可以删除must-revalidate
? NSURLProtocol似乎有用,但我只能看到如何修改请求,而不是响应。
答案 0 :(得分:0)
如果你使用NSURLProtocol,你可以发出一个新请求(确保标记它以便你不会再次修改它),然后在响应上,你可以创建一个新的响应对象,基于旧的,并将修改后的响应发送给客户端。这是否足以解决您的问题,我不确定。
然而,更好(阅读"更直接实现")解决方案可能是子类化NSURLCache对象并使用您的自定义子类作为共享缓存(对于NSURLConnection和NSURLSession共享会话)或作为每会话缓存(对于其他NSURLSession会话)。