C# 启用缓存的HttpWebRequest引发异常
我正在开发一个小型的C#/WPF应用程序,该应用程序使用手工编制的C# 启用缓存的HttpWebRequest引发异常,c#,httpwebrequest,C#,Httpwebrequest,我正在开发一个小型的C#/WPF应用程序,该应用程序使用手工编制的HttpWebRequest调用和JSON序列化与rubyonrails中实现的web服务进行接口。在没有缓存的情况下,一切都能正常工作,我还可以使用HTTP身份验证和压缩 启用缓存后,通过设置request.CachePolicy=new-HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable),出现问题-在生产环境中。当连接到一个简单的WEBrick实例时,一
HttpWebRequest
调用和JSON序列化与rubyonrails中实现的web服务进行接口。在没有缓存的情况下,一切都能正常工作,我还可以使用HTTP身份验证和压缩
启用缓存后,通过设置request.CachePolicy=new-HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable)代码>,出现问题-在生产环境中。当连接到一个简单的WEBrick实例时,一切正常,我得到了HTTP/1.1 304未按预期修改的,并且HttpWebRequest
提供了缓存的内容
当我在生产服务器上运行nginx/0.8.53+Phusion-Passenger 3.0.0时,应用程序崩溃。第一个请求(未缓存)得到了正确的服务,但是在第二个请求(导致304响应)上,我得到一个WebException
声明“请求被中止:请求被取消。”只要我调用request.GetResponse()
我已经运行了连接,这并没有帮助很大;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*
########## 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)
(异常引发)nginx连接的标头:
########## 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*
########## 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缓存,但结果是不行的:当调用request.getresponse()
时,我得到一个WebException
,告诉我“远程服务器返回了一个错误:(304)未修改。”-是的,.NET,我知道这一点,我想(尝试)自己处理它,grr
更新2:
越来越接近问题的根源。showstopper似乎与初始请求的响应头有所不同。WEBrick包含一个日期:Wed,2010年12月1日21:30:01 GMT
标题,该标题在nginx回复中不存在。还有其他区别,但是使用fiddler截取最初的nginx回复并添加Date
头,随后的HttpWebRequest
s能够处理(未修改的)nginx 304回复
我们将尝试寻找解决方法,并让nginx添加日期标题
更新3:
服务器端的问题似乎与Phusion乘客有关,他们缺少Date
标题。我仍然认为HttpWebRequest
的行为是。。。次优
更新4:
为bug添加了一张罚单。我认为,当“预期行为”(即获取响应主体)无法完成时,设计师们发现抛出异常是合理的。您可以通过以下方式明智地处理此问题:
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
var statusCode = ((HttpWebResponse)ex.Response).StatusCode;
// Test against HttpStatusCode enumeration.
}
else
{
// Do something else, e.g. throw;
}
}
因此,事实证明是Phusion Passenger(或nginx,取决于您对它的看法,也很瘦)没有添加Date
HTTP响应头,再加上我在.NET HttpWebRequest中看到的bug(在我的情况下,如果自
以来进行了修改,则没有,因此日期应该是不必要的),导致了问题
此特殊情况的解决方法是编辑Rails应用程序控制器:
class ApplicationController < ActionController::Base
# ...other stuff here
before_filter :add_date_header
# bugfix for .NET HttpWebRequst 304-handling bug and various
# webservers' lazyness in not adding the Date: response header.
def add_date_header
response.headers['Date'] = Time.now.to_s
end
end
可能值得一试,但似乎是一个特别令人讨厌的黑客行为——特别是因为(在尝试手动进行缓存时),在事件尝试获取响应流之前,我已经在GetResponse()中获得了异常。另外,如果我能让自动缓存在nginx上工作,那将是最整洁的——不过还是谢谢你:)嗨!我认为您在HttpWebRequest中发现了一个bug。您能否创建复制日志(请参阅)并在上创建错误请求?这样,微软就可以解决这个问题。@feroze:我昨天没时间了,但我已经在Connect now上添加了错误通知单。