我正在使用手工调制的HttpWebRequest
调用和JSON序列化来处理与Ruby on Rails中实现的Web服务接口的小型C#/ WPF应用程序。如果没有缓存,所有事情都按照预期运行,并且我也有HTTP认证和压缩工作。启用缓存的HttpWebRequest引发异常
一旦启用缓存,通过设置request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable);
,事情就会出错 - 在生产环境中。当连接到一个简单的WEBrick实例,事情工作正常,我得到HTTP/1.1 304 Not Modified
预期和HttpWebRequest
提供缓存的内容。
当我对生产服务器进行同样的尝试时,运行nginx/0.8.53 + Phusion Passenger 3.0.0,应用程序中断。第一个请求(未缓存)被正确地服务,但是对于导致304响应的第二个请求,我得到一个WebException
,说明“请求已中止:请求被取消。”“只要我调用request.GetResponse()
。
我已经通过fiddler运行连接,这并没有帮助很多; WEBrick和nginx都返回一个空的实体主体,虽然不同的响应头。拦截请求并更改nginx的响应头以匹配WEBrick的响应头并没有改变任何内容,导致我认为它可能是一个存活问题;设置request.KeepAlive = false;
不会改变任何内容,但它不会在连接到WEBrick时破坏内容,并且在连接到nginx时不会修正内容。
对于它的价值,在WebException.InnerException
是NullReferenceException
具有以下StackTrace
:
at System.Net.HttpWebRequest.CheckCacheUpdateOnResponse()
at System.Net.HttpWebRequest.CheckResubmitForCache(Exception& e)
at System.Net.HttpWebRequest.DoSubmitRequestProcessing(Exception& exception)
at System.Net.HttpWebRequest.ProcessResponse()
at System.Net.HttpWebRequest.SetResponse(CoreResponseData coreResponseData)
头的(工作)的WEBrick连接:
########## 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*
头的(除了投掷) nginx连接:
########## 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)
更新:
我试图做一个快速和肮脏的手动ETag的缓存,但事实证明这是一个不走的:我得到一个WebException
调用request.GetResponce()
的时候,告诉我,“远程服务器返回错误:( 304)未修改“。 - 是的,.NET,我有点知道,我想(尝试)自己处理它,grr。
UPDATE 2:
更接近问题的根源。 showstopper似乎是初始请求的响应标题中的差异。 WEBrick包含一个Date: Wed, 01 Dec 2010 21:30:01 GMT
标题,它在nginx答复中不存在。还有其他的不同点,但是用提琴手拦截最初的nginx回复并添加一个Date
标题,后续的HttpWebRequest
能够处理(未修改的)nginx 304回复。
想要寻找解决方法,以及让nginx添加Date标头。
更新3:
看来,服务器端的问题是与乘客的Phusion,他们有一个open issue关于缺乏Date
头的。我仍然认为HttpWebRequest
的行为是......不理想。
UPDATE 4:
增加了Microsoft Connect票的bug。
嗨!我认为你在HttpWebRequest中发现了一个错误。您可以创建repro日志(请参阅http://ferozedaud.blogspot.com/2009/08/tracing-with-systemnet.html)并在http:// connect?上创建一个bug请求。这样,微软可以解决这个问题。 – feroze 2010-12-02 00:37:16
@feroze:昨天我用完了时间,但我现在在Connect上添加了错误票。 – snemarch 2010-12-02 09:37:53