URLSession-URLCache behavior

Greetings,


I'm seeing an issue where URLSession incorrectly returns response from shared URLCache instead of fetching from remote. Here are the steps to reproduce issue,


Steps:

1. Download Xcode project from URLCacheBug.

2. Open and build Xcode project. You will see the CachePolicy is set to `useProtocolCachePolicy` for URLRequest.

2. Tap `Send Request 1` button which sends POST query request with parameters (specifically parameter geometry1). You will see response `Count: 5459` on the screen.

3. Tap `Send Request 2` button which sends POST query request with parameters(specifically parameter geometry2). You will see response `Count: 5459` on the screen. This is the same response for request 1 and being incorrectly getting from shared URLCache

4. Change the cache policy to `reloadIgnoringLocalCacheData` using segmented control.

5. Tap `Send Request 1` and you will see response `Count: 5459` on the screen.

6. Tap `Send Request 2` and you will see response `Count: 4672` on the screen. You can see the different response as local cache is being ignored.


Here is what seems to be happening,


1. First request is send and cached.

2. While sending second request header `if-none-match = etag of first response` is being set as the URL of the reuest same as first one.

3. Server responds with status code `304 - Not Modified`

4. URLSession look for response in the URLCache and finish request with status code `200` and response from cache.

5. When request cache policy is `reloadIgnoringLocalCacheData`, request is not being sent with header `if-none-match` and server responds with new and correct response.


I've logged a Feedback - FB7664947 for this but wanted to know if others are noticing this as well and is there any workaround other than using different cache policy.


What is the correct behavior for client and server in this scenario,


1. URLRequest should not set `if-none-match` header for second request as clearly the HTTPBody is different than first request/response is in the cache?

2. Server should be forgiving of header `if-none-match` and not respond with `304 - Not Modified `?


I have another reproducible case where seeing this behavior and the difference between two request is just one HTTP header.


Regards,

Nimesh

If you change the Etag from request 1/2 at the server level, does this affect the behavior? The thought process here is that the Etag might be identifying the content as always the same version (RFC 7232 Section 2.3) and thus conflicting with the Cache-Control header you have set of 30 seconds.



Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

Hi Matt,


Sorry, but I'm not in control of the server to try changing anything server side.


You can see in screenshots of the headers for request 1 and 2 - https://github.com/njarecha/URLCacheBug/blob/master/README.md, there are two additional headers `if-none-match` and `if-modified-since` for reqeust 2 which seems to be added based on cachePolicy by URLSession before sending request. The server is just honoring the provided headers and respond with status code `304`. So the question is why these headers are added to reqeust even though second request's HTTPbody is different than first request?



Regards,

Nimesh

URLSession-URLCache behavior
 
 
Q