Note that there are some explanatory texts on larger screens.

plurals
  1. POHttpWebRequest with caching enabled throws exceptions
    primarykey
    data
    text
    <p>I'm working on a small C#/WPF application that interfaces with a web service implemented in Ruby on Rails, using handcrafted <code>HttpWebRequest</code> calls and JSON serialization. Without caching, everything works as it's supposed to, and I've got HTTP authentication and compression working as well.</p> <p>Once I enable caching, by setting <code>request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable);</code>, things go awry - in the production environment. When connecting to a simple WEBrick instance, things work fine, I get <code>HTTP/1.1 304 Not Modified</code> as expected and <code>HttpWebRequest</code> delivers the cached content.</p> <p>When I try the same against the production server, running <strong>nginx/0.8.53 + Phusion Passenger 3.0.0</strong>, the application breaks. First request (uncached) is served properly, but on the second request which results in the 304 response, I get a <code>WebException</code> stating that "<em>The request was aborted: The request was canceled.</em>" as soon as I invoke <code>request.GetResponse()</code>.</p> <p>I've run the connections through <a href="http://www.fiddler2.com/fiddler2/" rel="nofollow">fiddler</a>, which hasn't helped a whole lot; both WEBrick and nginx return an empty entity body, albeit different response headers. Intercepting the request and changing the response headers for nginx to match those of WEBrick didn't change anything, leading me to think that it could be a keep-alive issue; setting <code>request.KeepAlive = false;</code> changes nothing, though - it doesn't break stuff when connecting to WEBrick, and it doesn't fix stuff when connecting to nginx.</p> <p>For what it's worth, the <code>WebException.InnerException</code> is a <code>NullReferenceException</code> with the following <code>StackTrace</code>:</p> <pre><code>at System.Net.HttpWebRequest.CheckCacheUpdateOnResponse() at System.Net.HttpWebRequest.CheckResubmitForCache(Exception&amp; e) at System.Net.HttpWebRequest.DoSubmitRequestProcessing(Exception&amp; exception) at System.Net.HttpWebRequest.ProcessResponse() at System.Net.HttpWebRequest.SetResponse(CoreResponseData coreResponseData) </code></pre> <p>Headers for the (working) WEBrick connection:</p> <pre><code>########## request GET /users/current.json HTTP/1.1 Authorization: Basic *REDACTED* Content-Type: application/json Accept: application/json Accept-Charset: utf-8 Host: testbox.local:3030 If-None-Match: "84a49062768e4ca619b1c081736da20f" Accept-Encoding: gzip, deflate Connection: Keep-Alive ########## response HTTP/1.1 304 Not Modified X-Ua-Compatible: IE=Edge Etag: "84a49062768e4ca619b1c081736da20f" Date: Wed, 01 Dec 2010 18:18:59 GMT Server: WEBrick/1.3.1 (Ruby/1.8.7/2010-08-16) X-Runtime: 0.177545 Cache-Control: max-age=0, private, must-revalidate Set-Cookie: *REDACTED* </code></pre> <p>Headers for the (exception-throwing) nginx connection:</p> <pre><code>########## request GET /users/current.json HTTP/1.1 Authorization: Basic *REDACTED* Content-Type: application/json Accept: application/json Accept-Charset: utf-8 Host: testsystem.local:8080 If-None-Match: "a64560553465e0270cc0a23cc4c33f9f" Accept-Encoding: gzip, deflate Connection: Keep-Alive ########## response HTTP/1.1 304 Not Modified Connection: keep-alive Status: 304 X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.0 ETag: "a64560553465e0270cc0a23cc4c33f9f" X-UA-Compatible: IE=Edge,chrome=1 X-Runtime: 0.240160 Set-Cookie: *REDACTED* Cache-Control: max-age=0, private, must-revalidate Server: nginx/0.8.53 + Phusion Passenger 3.0.0 (mod_rails/mod_rack) </code></pre> <h1>UPDATE:</h1> <p>I tried doing a quick-and-dirty manual ETag cache, but turns out that's a no-go: I get a <code>WebException</code> when invoking <code>request.GetResponce()</code>, telling me that <em>"The remote server returned an error: (304) Not Modified."</em> - yeah, .NET, I kinda knew that, and I'd like to (attempt to) handle it myself, grr.</p> <h1>UPDATE 2:</h1> <p>Getting closer to the root of the problem. The showstopper seems to be a difference in the response headers for the <strong>initial</strong> request. WEBrick includes a <code>Date: Wed, 01 Dec 2010 21:30:01 GMT</code> header, which isn't present in the nginx reply. There's other differences as well, but intercepting the initial nginx reply with fiddler and adding a <code>Date</code> header, the subsequent <code>HttpWebRequest</code>s are able to process the (unmodified) nginx 304 replies.</p> <p>Going to try to look for a workaround, as well as getting nginx to add the Date header.</p> <h1>UPDATE 3:</h1> <p>It seems that the serverside issue is with Phusion Passenger, they have an <a href="http://code.google.com/p/phusion-passenger/issues/detail?id=485" rel="nofollow">open issue</a> about lack of the <code>Date</code> header. I'd still say that <code>HttpWebRequest</code>'s behavior is... suboptimal.</p> <h1>UPDATE 4:</h1> <p>Added a <a href="https://connect.microsoft.com/VisualStudio/feedback/details/626833/httpwebrequest-bug-on-304-cached-when-200-ok-had-missing-date-response-header" rel="nofollow">Microsoft Connect</a> ticket for the bug.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload