URLCache behavior for request with different header values

Greetings,

I would like to understand this URLCache behavior for two different requests to the same end point but with a different header value. Here is a code with comment explaining the behavior.

        // Create a request to for a url.
        let url = URL(string: "https://<my url>?f=json")!
        var request = URLRequest(url: url)
        
        // Set custom header with a value.
        request.setValue("myvalue", forHTTPHeaderField: "CustomField")
        
        // Send request to get the response.
        let (data, response) = try await URLSession.shared.data(for: request)
        print("data: \(String(describing: String(data: data, encoding: .utf8)))")
        print("response: \(response)")
        
        // Create second request to the same url but with different value of custom header field.
        var request2 = URLRequest(url: url)
        request2.setValue("newvalue", forHTTPHeaderField: "CustomField")
        
        // Check the URL cache for second request and it returns the response
        // of the first request even though the second request has different header value.
        let cachedResponse = URLCache.shared.cachedResponse(for: request2)
        print("cachedResponse: \(cachedResponse?.response)")

Is this a bug in URLCache that request headers are not matched while returning the response? Is this an expected behavior? If yes, why?

Regarding this code:

let url = URL(string: "https://<my url>?f=json")!
var request2 = URLRequest(url: url)
let cachedResponse = URLCache.shared.cachedResponse(for: request2)

You may be falling through a condition where the only thing the cache has to key off of is the base URL that's used here.

If you make two different POST requests and cache those results does it have the same result?

Thanks for your reply @meaton!

Yes, I see the same issue for POST requests as well. But why the caching is happening only based on the base URL? Shouldn't it consider the header informations too?

Thanks for the reply.

But why the caching is happening only based on the base URL? Shouldn't it consider the header informations too?

In some very rare cases it can happen with the URL, but typically the cached data is looked up based on URL, body data, or header data.

In some very rare cases it can happen with the URL, but typically the cached data is looked up based on URL, body data, or header data.

The POST request with body should not be cached. I logged an issue (FB10141204) in the past and it is fixed in iOS 16. Is this a bug that request matching is not considering the header data/information?

@meaton Appreciate if you can confirm the behavior of URLCache is a bug or as expected. Thank you!

I did look at the bug (FB10141204) and it does look like this was fixed in iOS 16.4 timeframe as mentioned. Technically a POST with a response body is cacheable but it shouldn't be returned if the response body is different. For example, adding the following will invalidate the cache lookup on the second request:

request2.setValue("newvalue", forHTTPHeaderField: "CustomField")
var body = "{\"key\": \"value\"}"
var bodyData = body.data(using: .utf8)!
request2.httpBody = bodyData

Looking at this a bit deeper, the three things that affect the cache lookup are base URL, caching headers for a previous response, and request bodies. Now, I cannot definitely say that this is all of the logic at work here, so if you feel that this should work differently or is a bug, then please open another bug report here.

URLCache behavior for request with different header values
 
 
Q