3

I am experimenting with caching in HttpClient in order to understand the topic better.

I have written a command line dot net tool that uses a single HttpClient and can send GET requests to a server, displaying the response headers. I also have a Python web server (based on BaseHTTPServer) that returns 304 whenever it sees an if-modified-since header in the request.

When I use my tool to hit the server the first time, this is what I see:

HTTP:>GET http://localhost:7777
Status 200 OK (OK in 00:00:01.7794986):
Cache-Control = must-revalidate, no-cache
Date = Sat, 08 Jul 2017 16:41:28 GMT
Server = BaseHTTP/0.3, Python/2.7.13
Content-Type = text/html
Last-Modified = Sat, 08 Jul 2017 16:41:24 GMT

When I repeat the request a few seconds later (same instance of the sending tool and therefore same singleton instance of HttpClient), the request is visibly much faster and I see:

HTTP:>GET http://localhost:7777
Status 200 OK (OK in 00:00:00.1773793):
Cache-Control = must-revalidate, no-cache
Date = Sat, 08 Jul 2017 16:42:40 GMT
Server = BaseHTTP/0.3, Python/2.7.13
Age = 0
Content-Length = 24000000
Content-Type = text/html
Last-Modified = 2017-07-08 12:41:24.187000

Looking at the output of BaseHTTPServer, I can see that the first time my server did the "work" of generating the request and returned 200 and the request body. The second time, it simply returned a header with 304.

But HttpClient did not tell me about the 304, instead it reported 200. It showed an age of 0 when I waited at least ten seconds between requests. And it introduced the Content-Length header, which was not in the original response.

Can anyone tell me, is the correct and expected status code from HttpClient on that second response 200 instead of 304? Why is the Age header never more than 0? And, other than the apparent speed of the response, how can I determine on the client what actually happened during this transaction?

Larry Lustig
  • 49,320
  • 14
  • 110
  • 160
  • anyway .net does not use wininet but winhttp on windows – David Haim Jul 09 '17 at 11:43
  • Is that so? Do wininet and winhttp share the same caching system? I ask because I can see that using Internet Explorer (which I'm pretty sure is wininet-based) to clear the cache clears my HttpClient-based application cache. In any event, do you know where I can read about the caching built into winhttp, at least enough to learn whether I should be seeing those 304 status codes? – Larry Lustig Jul 09 '17 at 12:02
  • I'm pretty sure Winhttp does not do any caching behind the scenes. I think you got performance boost not because of caching, but because the second time the .net platform is "hot" (all the pools are initialed, the JIT run etc.) – David Haim Jul 09 '17 at 12:06
  • you can also read the .net core code regarding winhttp: https://github.com/dotnet/corefx/tree/master/src/System.Net.Http.WinHttpHandler – David Haim Jul 09 '17 at 12:07
  • In this case, I'm sure that the server is returning 304 because I can see it on the server console. What I don't understand is why HttpClient tells me 200 -- is that because it's "translated" the 304 to say "give the requester back the exact last response received"? And why Age is always 0. (I have another related question about freshness caching: https://stackoverflow.com/questions/44988241/is-dot-net-httpclient-unexpectedly-caching-responses). – Larry Lustig Jul 09 '17 at 12:13
  • what happens if you dispose the HttpClient and create a new one instead? is the response still "cached"? – David Haim Jul 09 '17 at 12:16
  • I will attempt this (for the scenario in this question) and post the result when I have it. However, in the other question I referenced (which is about freshness caching, not a 304 from validation) I definitely see that the unexpected freshness cache lasts across separate invocations of my program. – Larry Lustig Jul 09 '17 at 12:26
  • @DavidHaim: That was a good question, and the behavior is different than I expected. When I use the *same* HttpClient, I get the results as described above. When I use a *different* HttpClient my server does not receive `if-modified-since` in the subsequent requests and returns the the entire body. This is in conflict with my other question (about `max-age` caching) which appears to cache *across* instances of HttpClient. – Larry Lustig Jul 11 '17 at 12:53
  • I guess each WinHTTP session does indeed cache the result if it can. by creating a new http client the application has created a new underlying WinHTTP session hence non-cached results – David Haim Jul 11 '17 at 13:43

0 Answers0