2012-10-03 18 views
7

Después de haber algún problema en el desarrollo de un cliente SignalR para un concentrador alojado en el sitio web asp.net con habilita la compresión gzip. Dado que estamos utilizando la compresión IIS, la respuesta de SignalR también se comprime, pero el cliente no comprende la respuesta y obtenemos un error de análisis Json en el lado del cliente.SignalR wth compresión gzip

SignalR internamente usa HttpWebRequest para realizar solicitudes http y HttpWebRequest se puede configurar para descomprimir automáticamente la respuesta usando la propiedad AutomaticDecompression. Entonces, si de alguna manera puedo obtener el objeto HttpWebRequest usado por SignalR para realizar la solicitud, debería poder configurar la descompresión automática de habilitación.

pensé que debería ser capaz de obtener acceso a la HttpWebRequest proporcionando HubConnection.Start con mi implementación personalizada de IHttpClient, IHttpClient.GetAsync realiza una acción prepareRequest lo que pensé que me debería dar acceso a la HttpWebRequest, pero, HttpHelper.GetAsync envuelve el HttpWebRequest con HttpWebRequestWrapper antes de pasar a prepareRequest y HttpWebRequestWrapper no proporciona acceso a HttpWebRequest.

HttpHelper La clase es interna, por lo que no puedo usarla, así que no estoy seguro de cómo habilitar la descompresión automática con SignalR.

Puedo exponer el HttpWebRequest en HttpWebRequestWrapper, pero, preferiría una solución más simple si existe. ¿Algún pensamiento?

estoy usando la versión SignalR 0.5.1.10822

Mi automático de descompresión 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

ahora he comprobado en un servidor que también tiene habilitada la compresión gzip y descubrió que SignalR.Client no envía Accept-Encoding: gzip por defecto, por lo que mi servidor responde con un mensaje sin comprimir y todo funciona como se esperaba. Parece que tu cliente envía incorrectamente el encabezado Aceptar codificación o tu servidor fuerza cada respuesta a gzip (que la compresión integrada de IIS no tiene). ¿Puedes verificar con Fiddler qué está pasando? –

Respuesta

9

A lo mejor de mi conocimiento GZip codificación y transmisión no se mezclan. En el caso del transporte de fotogramas para siempre, el cliente no podrá decodificar ninguno en el contenido de transmisión hasta que se reciba toda la respuesta, o al menos un bloque de datos significativo (debido a la forma en que se decodifican los datos). En el caso de los sockets web, no existe soporte para la codificación de ningún tipo en este momento, aunque aparentemente hay una extensión de la especificación para la codificación por mensaje being worked on.

Dicho esto, si desea intentar proporcionar soporte para el transporte LongPolling, la única forma en que puedo ver que esto es posible es proporcionar su propia implementación de SignalR IHttpClient. Puede ver ahora que la clase DefaultHttpClient usa HttpHelper::GetAsync que crea el HttpWebRequest internamente y nunca puede tener eso en sus manos porque solo tiene acceso al IRequest que es HttpWebRequestWrapper en ese punto.

Al crear su propio IHttpClient que puede hacerse cargo de la creación de instancias inicial de la HttpWebRequest, establecer el AutomaticDecompression y luego envolver que hasta usted mismo con la HttpWebRequestWrapper.

+1

Pero debería funcionar con el transporte longPolling, ya que la solicitud de larga ejecución se completa al devolver un mensaje al cliente, ¿o me falta algo? –

+0

Gracias, huys, entiendo por qué la compresión no funciona con la transmisión, creo que mi principal problema es que la interfaz SingalR Api no te da acceso a la HttpWebRequest que utiliza para realizar la solicitud, básicamente quería actualizar ' propiedad httpWebRequest.AutomaticDecompression', pero SignalR ajusta la 'httpWebRequest' en un contenedor que no expone la propiedad AutomaticDecompression. dfowler sugirió que modifique la clase contenedora y reconstruya SignalR. Por ahora solo estoy usando el reflejo para acceder a la propiedad privada a la que necesito acceder. –

+0

@akoeplinger Sí, debería funcionar con transporte LP. Por supuesto, ese es el peor transporte para usar eficientemente la eficiencia, por lo que probablemente niegue cualquier beneficio potencial de gzip a menos que las cargas de mensajes sean enormes. –

Cuestiones relacionadas