- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在 AppDelegate.m 中,我配置了:
NSURLCache *sharedURLCache = [[NSURLCache alloc] initWithMemoryCapacity:20 * 1024 * 1024 diskCapacity:100 * 1024 * 1024 diskPath:@"FhtHttpCacheDir"];
然后是http请求:
- (void) testRestfulAPI{
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://192.168.0.223:8000/v1/topictypes"]];
[request setHTTPMethod:@"GET"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
NSError *error = nil;
if (!error) {
NSURLSessionDataTask *downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (httpResp.statusCode == 200) {
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
NSLog(@"JSON: %@", json);
}
}
}];
[downloadTask resume];
}
}
第一次请求时,它获得了带有 Etag + Cache-Control header 的 HTTP 200。没问题。
如果我没记错的话,Cache-Control: must-revalidate, max-age=86400, private
会告诉 NSURLCache 认为缓存在 24 小时内是新鲜的并且不会建立任何网络在接下来的 24 小时内调用。
但事实并非如此,第二次发起http请求时,它实际上发出了If-None-Match
header ,并返回了HTTP 304。
在我看来 NSURLCache 部分工作。它可以缓存响应,但它不遵守 Apple 文档描述的 RFC 2616 语义 here .仅供引用,我没有更改缓存策略,因此它使用默认的 NSURLRequestUseProtocolCachePolicy
。
我在谷歌上搜索了一天多的类似问题和其他经历过的类似问题,但我没有找到任何解决方案。有些人在 AFNetworking 的 github 问题中询问了同样的问题,但作者关闭了这个问题,因为它与 AFNetworking 没有直接关系 here和 here .
还有各种相关的 stackoverflow 帖子也没有帮助我。
最佳答案
问题是 Cache-Control 响应指令 must-revalidate 的使用。
根据我的理解,通过省略 must-revalidate,您已经对您的用例有了完美的定义:
Cache-Control: max-age=86400, private
这控制请求的资源被认为是新鲜的时间。这段时间过去后,答案不应再直接来自缓存,而应联系服务器以验证后续请求。在您的情况下,由于服务器提供了 ETag,iOS 会向服务器发送带有 If-None-Match header 的请求。
为了检查这一点,我使用了您的没有 NSURLCache 设置的 testRestfulAPI 方法,并在服务器端配置了 60 秒的最大时限,所以我不必等一天就可以检查结果。
之后,我每秒触发一次 testRestfulAPI。我总是从缓存中得到想要的结果。并且 Charles 表明数据必须来自缓存,因为服务器在 60 秒内没有联系。
这是 RFC 7234(废弃 RFC 2616)中 5.2.2.1 的引述。它指出:
The must-revalidate directive is necessary to support reliableoperation for certain protocol features. In all circumstances a cacheMUST obey the must-revalidate directive; in particular, if a cachecannot reach the origin server for any reason, it MUST generate a 504(Gateway Timeout) response.
The must-revalidate directive ought to be used by servers if and onlyif failure to validate a request on the representation could result inincorrect operation, such as a silently unexecuted financialtransaction.
读完之后,如果您将自己置于缓存开发人员的视角,您可以很好地想象当看到 must-revalidate 时,始终会联系原始服务器,并且会简单地忽略任何附加指令,例如 max-age .在我看来,缓存在实践中经常表现出这种行为。
章节 5.2.2.1 中还有另一节。我不会隐瞒,内容如下:
The "must-revalidate" response directive indicates that once it has become stale, a cache MUST NOT use the response to satisfy subsequent requests without successful validation on the origin server.
这通常被解释为通过指定 max-age 和 must-revalidate,您可以确定内容何时过时(在 max-age 秒之后),然后它必须在源服务器上验证才能提供内容。
然而,在实践中,由于上述原因,似乎 must-revalidate 总是导致对源服务器上的每个请求进行验证。
关于ios - NSURLCache,连同 NSURLSession,不尊重 : Cache-Control: max-age:86000, private,must-revalidate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51778155/
我正在使用源代码中的Postgres 13(Rel_13_STRATE分支),并且我使用的是来自apachea/age源代码的(Release/PG13/1.3.0分支)中的1.3.0版的Apache
这是我正在使用的代码: 我想回显 $age 变量的值,但我总是得到“age”这个词。例如,代码应该回显 yourage: 5,但它会输出 yourage:age 最佳答案 首先,您需要运行 SELE
对于这门课, class Person { int age; public Person(int age) { this.age = age; } } 在我的课
我没用过 HTTP 缓存 . 我在 Symfony documentation page 上找到了这些缓存选项. 我只是想知道 expires 和有什么区别, max-age , 和 s-maxage
我正在参加关于 SQL 的 Cousera 类(class),但有一行代码我无法理解。 'hex(name || age)' 是什么意思?我知道它使用 hex() 函数将字符串转换为十六进制格式,但是
两个 header Cache-control: max-age=0 和 Cache-control: max-age=-1 之间的浏览器行为有何不同? 如果浏览器收到 max-age=0,它会立即重
请参阅这个最小示例: 标记 changePeople1Works changePeopleNotWorking {{$store.sta
RFC 2616 Sec 13.2.3给出如下年龄计算算法: apparent_age = max(0, response_time - date_value); corrected_received
像这样,我有一个对象: { 'person': { 'like': { 'color': 'red', 'food': 'rice' }, 'nam
类似这个问题: get CSS rule's percentage value in jQuery 但是,我正在编写一个插件,它需要根据最初指定宽度的方式优雅地处理它。如果元素最初是以像素为单位指定的
我必须使用子查询显示下表中的 Mothers_name、AGE 和平均年龄? 我试过了 SELECT Mothers_name, Age, AVG(Age) FROM
这个问题在这里已经有了答案: What is the purpose of the `self` parameter? Why is it needed? (26 个答案) 关闭 3 个月前。 我最
这里有一个问题要问“Matlab 中记录较少的部分的专家”:是否有一种(未记录的?)方法来确定图形已打开多长时间(即图形的“年龄”)? figure; spy; myfig=gcf; age=get_
有人可以澄清一下有关缓存的说法吗? https://developers.google.com/speed/docs/best-practices/caching说 It is redundant t
这个问题在这里已经有了答案: How to get an age from a D.O.B field in MySQL? (15 个答案) 关闭 7 年前。 我想进行选择查询以搜索最小和最大年龄之
我正在实现一个项目,在该项目中,我必须找到笼子中老鼠的最小值 和 k 年龄。 我使用的代码是: var earTags = ""; var miceAge = "";
我正在编写一个小程序,显示三位教授并打印其中一位最年长和最年轻的教授。我认为我的 if 语句是正确的,但它为两个语句打印出相同的名称。 public class app { /**
我在 PostgreSQL 9.6 转折日期计算中遇到了我的 SQL 代码的一些意外行为。在分析时,我发现 Postgres 不会总是返回相同的值返回 n 天,然后用 age() 计算持续时间。 考虑
我一直在寻找一种像 agerecord 列表一样工作的数据结构。如果没有比你更年轻的人得分更高,你就有了一个年龄记录。 所以我想要一个对 (a,b) 的列表,其中对于所有对 (a1,b1) 和 (
题目地址:https://leetcode.com/problems/friends-of-appropriate-ages/description/ 题目描述: Some people will
我是一名优秀的程序员,十分优秀!