我正在努力解决这个错误:
https://github.com/openstacknetsdk/openstack.net/issues/333
问题涉及 ProtocolViolationException
带有以下消息:
Chunked encoding upload is not supported on the HTTP/1.0 protocol.
我发现我能够可靠地重现问题,我发出一个产生 502 响应代码的 Web 请求,然后调用使用带有分 block 编码的 POST 请求。我将其追溯到
ServicePoint.HttpBehaviour
值为 HttpBehaviour.HTTP10
的属性在 502 响应之后。我能够使用以下 hack(在
catch
block 中)解决问题。此代码“隐藏”ServicePoint
由来自 ServicePointManager
的失败请求创建的实例, 强制它创建一个新的 ServicePoint
为下一个请求。public void TestProtocolViolation()
{
try
{
TestTempUrlWithSpecialCharactersInObjectName();
}
catch (WebException ex)
{
ServicePoint servicePoint = ServicePointManager.FindServicePoint(ex.Response.ResponseUri);
FieldInfo table = typeof(ServicePointManager).GetField("s_ServicePointTable", BindingFlags.Static | BindingFlags.NonPublic);
WeakReference weakReference = (WeakReference)((Hashtable)table.GetValue(null))[servicePoint.Address.GetLeftPart(UriPartial.Authority)];
if (weakReference != null)
weakReference.Target = null;
}
TestTempUrlExpired();
}
问题:
最佳答案
问:为什么我会观察到这种行为?
A. .NET 框架对连接到 HTTP 服务器的支持基于 ServicePointManager
提供ServicePoint
实例。每个ServicePoint
实例假设它基于端点地址连接到单个“逻辑”服务。此对象缓存有关另一端服务的某些信息,其中一条信息是该服务是否支持 HTTP/1.1。如果对服务的任何请求表明该服务仅支持 HTTP/1.0,ServicePoint
"latches" into that state ,以及 ServicePointManager
只会重新创建一个新的 ServicePoint
如果/当垃圾收集器清除 WeakReference
时,则不会处于该状态指向实例。
由于以下原因,此行为可能被认为不是问题:
问:有没有解决问题的简单方法?
A. 当然有变通办法,但其中一个或多个选项可能不适合特定环境。下面列出了其中一些选项。
Stream.Size
时才依赖分 block 编码。属性抛出 NotSupportedException
. HttpWebRequest.AllowWriteStreamBuffering
至true
. 虽然我没有测试过这个解决方案,但是在浏览引用源时收集的信息表明这个属性允许实现 fall back to buffering在不支持分 block 传输的情况下,而不是简单地 throwing the ProtocolViolationException
. ServicePoint
让我的设置超时ServicePoint.MaxIdleTime
到 0。这仍然是 hacky,但不依赖反射,应该仍然适用于 Mono。修改后的代码如下所示。public void TestProtocolViolation()
{
try
{
TestTempUrlWithSpecialCharactersInObjectName();
}
catch (WebException ex)
{
ServicePoint servicePoint = ServicePointManager.FindServicePoint(ex.Response.ResponseUri);
if (servicePoint.ProtocolVersion < HttpVersion.Version11)
{
int maxIdleTime = servicePoint.MaxIdleTime;
servicePoint.MaxIdleTime = 0;
Thread.Sleep(1);
servicePoint.MaxIdleTime = maxIdleTime;
}
}
TestTempUrlExpired();
}
关于.net - 在 WebException 之后避免 ProtocolViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22973178/