2012-10-03 209 views
7

在启用了gzip压缩功能的asp.net网站中托管的Hub的开发SignalR客户端时遇到了一些问题。由于我们使用IIS压缩,SignalR的响应也会被压缩,但客户端并不理解响应,并且客户端会收到Json解析错误。SignalR wth gzip压缩

SignalR内部使用HttpWebRequest来使make http请求和HttpWebRequest可以配置为使用AutomaticDecompression属性自动解压缩响应。所以,如果能以某种方式获得SignalR使用的HttpWebRequest对象发出请求,我应该能够设置启用自动解压缩。

,我想我应该能够通过提供HubConnection.Start我的IHttpClient自定义实现来获得访问HttpWebRequestIHttpClient.GetAsync采取prepareRequest行动,我认为应该给我访问HttpWebRequest,但是,HttpHelper.GetAsyncHttpWebRequestHttpWebRequestWrapper包装在传递到prepareRequestHttpWebRequestWrapper之前不提供对HttpWebRequest的访问。

HttpHelper类是内部的所以不能用它为好,所以,我不完全知道如何启用自动解压缩与SignalR。

我可以公开HttpWebRequestHttpWebRequestWrapper,但是,如果存在一个更喜欢更简单的解决方案。你有什么想法?

我使用SignalR版本0.5.1.10822

我自耦减压的HttpClient:

public class HttpClientWithAutoDecompression : IHttpClient 
{ 
    readonly DefaultHttpClient _httpClient = new DefaultHttpClient(); 

    private readonly DecompressionMethods _decompressionMethods; 
    public HttpClientWithAutoDecompression(DecompressionMethods decompressionMethods) 
    { 
     _decompressionMethods = decompressionMethods; 
    } 

    public Task<IResponse> GetAsync(string url, Action<IRequest> prepareRequest) 
    { 
     Task<IResponse> task = _httpClient.GetAsync(url, 
      request => 
       { 
        [ERROR: request is actually HttpRequestWrapper and 
        does not expose HttpWebRequest]**    ] 
        var httpWebRequest = (HttpWebRequest) request; 
        httpWebRequest.AutomaticDecompression = _decompressionMethods; 
        prepareRequest(request); 
       }); 

     return task.ContinueWith(response => 
     { 
      Log.Debug(this, "Response: {0}", response.Result.ReadAsString()); 
      return response.Result; 
     }); 

    } 
.... 
} 
+0

现在我已经检查了也启用了gzip压缩,并发现SignalR.Client不发送的Accept-Encoding的服务器上:在默认情况下的gzip,所以我的服务器未压缩的消息作出响应,一切都按预期工作。看起来你的客户端错误地发送了Accept-Encoding头文件,或者你的服务器强制每一个对gzip的响应(内置IIS压缩都没有)。你可以检查小提琴手是怎么回事? –

回答

9

要尽我所知gzip编码和流媒体的不要混用。在永远帧传输的情况下,客户端将无法解码流内容上的任何内容,直到接收到整个响应或至少一个重要的数据块(由于数据被解码的方式)。在网络套接字的情况下,目前不支持任何类型的编码,尽管对于每个消息编码being worked on的规范明显有一个扩展。这就是说,如果你想试图为LongPolling传输提供支持,唯一可以看到这种情况的方法是提供你自己的SignalR IHttpClient实现。您可以立即将DefaultHttpClient类使用HttpHelper::GetAsync它创建HttpWebRequest内部,你永远不能得到你的手,因为你只能访问到IRequest这是HttpWebRequestWrapper在这一点上看到的。

通过创建自己的IHttpClient你可以接管HttpWebRequest的初始实例,设置AutomaticDecompression,然后换行了自己与HttpWebRequestWrapper

+1

但它应该与longPolling传输一起工作,因为当向客户端返回消息时,长时间运行的请求会完成,或者我错过了什么? –

+0

感谢huys,我明白为什么压缩不能用于流媒体,我认为我的主要问题是SingnalR Api接口不允许你访问它用来发出请求的HttpWebRequest,基本上我想更新' httpWebRequest.AutomaticDecompression'属性,但是,SignalR将'httpWebRequest'封装在一个不公开AutomaticDecompression属性的包装器中。 dfowler建议我修改包装类并重建SignalR。现在我只是使用反射来访问我需要访问的私有属性。 –

+0

@akoeplinger是的,它应该与LP运输工作。当然这是使用效率最差的传输方式,所以它可能会否定gzip的任何潜在好处,除非您的消息有效载荷很大。 –