ios - HTTP 缓存适用于 GET,但不适用于 HEAD(在 iOS 7.1 上永远不会为 HEAD 获得 304)

标签 ios objective-c nsurlconnection

我正在使用最新的 RestKit 0.23.3 .您可能知道它适用于 AFNetworking 1.3.x .
我有团队资源并从 API 服务器获取团队集合:我使用 RKObjectManager及其-managedObjectRequestOperationWithRequest:managedObjectContext:success:failure:RestKit本身对我来说可以正常工作 - 我确实使用 GET /teams 获得团队请求 - 我在第一次请求时看到 200,在后续请求中看到 304。
但是,当我使用与 HEAD 完全相同的代码时我从未收到的请求 304但总是 200 .
我对这一切进行了更多调查,发现在我的 iOS 应用程序收到对 GET /teams 的第一个响应后来自 Rails 服务器,此响应包含 Etag:等后续请求iOS应用添加"If-None-Match:"[etag code...]"这有助于 Rails 做出以 304 响应的决定。我注意到,当我使用 HEAD 请求 iOS 应用程序 时不 像 GET 请求一样混合“If-None-Match”。
我尝试设置除 NSURLRequestUseProtocolCachePolicy 之外的所有可能的缓存策略但这些政策都没有改变我。
如果请求 HEAD /teams 的 header 我手动混合If-None-Match:"[etag code...]"使用从 HTTP 日志获得的 etag,即对 GET /teams 的响应我 开始HEAD 获得 304要求。
这让我觉得 NSURLConnection 的内部存在一些问题(错误?)阻止我的 iOS 应用程序发送 HEADIf-None-Match:标题存在且正确。
我将非常感谢任何能够对此有所了解的人。谢谢。

我猜这可能是 NSURLConnection 中的一个错误,如果有可能获得此 etag 并将其手动混合到我的 HEAD 请求中,我也将不胜感激。
相关话题:What response should If-Modified-Since HTTP Header return if request is HEAD?

@MikeS 的重要评论:

I did a quick test with straight NSURLConnection and it seems to work fine. I make a GET request, get back an ETag, and then make a HEAD request to the same URL and I can see the if-none-match header on the server side.

...

My original test was using iOS 8.0 in the simulator. I just re-tested with iOS 7.1 in the simulator and this time I did not get the if-none-match header with the HEAD request. Based on that, it does look like it's a bug in iOS 7.1, but it's fixed in iOS 8.0.

最佳答案

虽然我对此没有任何解释,但以下解决方法对我有用:

- (void)headTeamsWithHandler:(APIRequestArrayHandler)handler {
    RKObjectManager *manager = ...;

    NSDictionary *parameters = ...; // correct parameters with token and device ID

    NSMutableURLRequest *teamsHEADRequest = [manager requestWithObject:nil method:RKRequestMethodHEAD path:TEAMS_PATH parameters:[self addDefaultParamsTo:nil]];

    NSMutableURLRequest *teamsGETRequest  = [manager requestWithObject:nil method:RKRequestMethodGET path:TEAMS_PATH parameters:[self addDefaultParamsTo:nil]];

    NSCachedURLResponse *cachedTeamsResponse     = [[NSURLCache sharedURLCache] cachedResponseForRequest:teamsGETRequest];
    NSHTTPURLResponse   *cachedTeamsHTTPResponse = (NSHTTPURLResponse *)cachedTeamsResponse.response;

    NSString *cachedTeamsEtag = cachedTeamsHTTPResponse.allHeaderFields[@"Etag"];

    [teamsHEADRequest setValue:cachedTeamsEtag forHTTPHeaderField:@"If-None-Match"];

    AFHTTPRequestOperation *requestOperation = [manager.HTTPClient HTTPRequestOperationWithRequest:teamsHEADRequest success:^(AFHTTPRequestOperation *operation, id responseObject) {
        // ...
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        // ...
    }];

    [requestOperation start];
}

这当然需要两种情况都处理:当有缓存GET /teams响应以及当没有响应时。

关于ios - HTTP 缓存适用于 GET,但不适用于 HEAD(在 iOS 7.1 上永远不会为 HEAD 获得 304),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25878340/

相关文章:

ios:如何检测用户取消调用电话号码

ios - 如何从Apple Push Notifications获取userInfo

ios - NSURLConnection 委托(delegate)方法未执行

iphone - 在 NSURLRequest 中通过 POST 发送 JSON

ios - 使用自动布局动画化 UIView 动画化 UITableView 的复选标记

objective-c - iOS/Objective-C : Creating a UIScrollView which fills screen and reorients

objective-c - 后台线程中可取消的加载

ios - 如何更新自动续订订阅收据

json - 从 NSURLConnection 加载 UITableView 时数据加载时间过长

javascript - 排毒问题 : BUILD FAILED Ld build/Build/Products/Debug-iphonesimulator