1
votes

I have problem implementing caching using AFNetworking and ETag values. My server returns Cache-Control and ETag headers values for every request. But if I make a second request for the same resource AFNetworking won't add ETag. Should I manually save etag for each response I got and append it to next requests?

In app delegate I have set cache object:

 NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:20 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:nil];
 [NSURLCache setSharedURLCache:URLCache];

Also, I'm using default cache policy of AFHTTPRequestSerializer.

Any ideas what is the problem? Maybe I don't understand the idea of http caching. As far as I know it should be transparent, and all I have to do is to attach ETag and Cache-Control headers for every response.

EDIT:

The headers of response looks like this:

"Cache-Control" = "max-age=3600";
"Content-Encoding" = gzip;
"Content-Type" = "application/json; charset=utf-8";
Date = "Wed, 05 Aug 2015 07:52:33 GMT";
Etag = "W/f6c8a0f47deb7db0eeea3069061de9ab";
Expires = "Wed, 05 Aug 2015 08:52:30 GMT";
"Last-Modified" = "Wed, 05 Aug 2015 08:52:30 GMT";
Server = "cloudflare-nginx";
Vary = "Accept-Encoding";
"cf-ray" = "2110ec564bde0afc-WAW";
"x-cache-id" = "api_3447fddb8680ed5d082ae871e95214dc";
"x-powered-by" = "PHP/5.5.19";
"x-whom" = "www-stage02-b"
1
It should work by default, are you sure you have all headers properly set on both sides ? Server side need to attach those headers as well.Grzegorz Krukowski
You can check server reponses using "[[operation response] allHeaderFields]"Grzegorz Krukowski
What do you mean on both sides? Shouldn't AFNetworking automatically attach If-None-Match header with latest Etag value for corresponding request path? I have attached the responses headers (using edit). Can you see something that could make any problems?MichalMoskala
It looks ok, let me paste you the code to confirm if request is loaded from cache or notGrzegorz Krukowski

1 Answers

0
votes

To check if your AFHTTPRequestOperation is coming from cache or not, you can use this code:

- (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request
                                                    success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                                                    failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
    NSMutableURLRequest* mutableRequest = [request mutableCopy];
    BOOL __block responseFromCache = YES;

    AFHTTPRequestOperation* operation = [super HTTPRequestOperationWithRequest:mutableRequest
    success:^(AFHTTPRequestOperation *operation, id responseObject)
    {
        NSString* source = responseFromCache ? @"CACHE" : @"SERVER";
        NSLog(@"Request from %@", source);
        success(operation, responseObject);
    }
    failure:nil];

    [operation setCacheResponseBlock:
     ^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) {
         responseFromCache = NO;
         return cachedResponse;
     }];

    return operation;
}

Make sure you also enabled NSURLCache when your application starts running.

NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:5 * 1024 * 1024
                                                     diskCapacity:50 * 1024 * 1024
                                                         diskPath:nil];
[NSURLCache setSharedURLCache:URLCache];