2012-07-14 11 views
5

Estoy escribiendo una aplicación web simple usando Nancy. Al menos una solicitud da como resultado una transmisión de longitud desconocida, por lo que no puedo proporcionar Content-Length. Me gustaría usar Transfer-Encoding: chunked, o (igualmente aceptable en este caso, Connection: close).¿Cómo escribo el flujo de salida en NancyFX?

He tenido un truco rápido en el código fuente de Nancy, y he agregado Response.BufferOutput, y el código para establecer HttpContext.Response.BufferOutput en . Puede verlo aquí:

public class HomeModule : NancyModule 
{ 
    public HomeModule() 
    { 
     Get["/slow"] = _ => new SlowStreamResponse(); 
    } 

    private class SlowStreamResponse : Response 
    { 
     public SlowStreamResponse() 
     { 
      ContentType = "text/plain"; 
      BufferOutput = false; 
      Contents = s => { 
       byte[] bytes = Encoding.UTF8.GetBytes("Hello World\n"); 
       for (int i = 0; i < 10; ++i) 
       { 
        s.Write(bytes, 0, bytes.Length); 
        Thread.Sleep(500); 
       } 
      }; 
     } 
    } 

No parece tener ningún efecto. La respuesta aparece de una vez, después de 5 segundos. He probado esto como un cliente simple basado en WebRequest.

¿Cómo puedo obtener salida fragmentada para trabajar en Nancy? Estoy usando el alojamiento ASP.NET, pero me interesarían las respuestas para las otras opciones de alojamiento.

Si escribo un servidor simple usando HttpListener, puedo establecer SendChunked a true, y envía la salida fragmentada, que mi sencilla cliente recibe correctamente en trozos.

+0

¿Dónde estableciste el HttpContext.Response.BufferOutput en el código de Nancy? ¿Y alguna vez encontró la manera de hacer que esto funcione con OWIN? – Hooligancat

+0

No lo recuerdo, lo siento. –

+0

vea la respuesta marcada en esta pregunta => http://stackoverflow.com/questions/29953301/stream-an-sqlfile-stream-using-nancy – sp3tsnaz

Respuesta

4

Tiene que llamar al Flush() después de cada Write(), de lo contrario, la respuesta se almacena de todos modos. Además, Google Chrome no procesa el resultado hasta que se haya recibido todo.

Descubrí esto escribiendo una aplicación cliente simple que registraba lo que estaba leyendo de la secuencia de respuesta cuando llegó.

+0

¿Así que está esto "ordenado"? –

+1

No realmente. El cambio de 'BufferOutput' no está en el núcleo de Nancy, y realmente solo funciona para el alojamiento de ASP.NET. Para WCF, tiene que cambiar el WebHttpBinding, no puedo hacer que el autohospedaje funcione correctamente, y no veo ninguna manera de hacerlo en absoluto con el hosting de OWIN. –

+0

@RogerLipscombe ¿alguna vez llegaste a algún lado con esto? Estoy intentando hacer que esto funcione con NancyFx + ASP.NET – RPM1984

5

Durante mi experimentación, descubrí que necesitaba la siguiente configuración. Primero, configure su archivo web.config como se documenta en el Nancy Wiki. Vale la pena señalar que para establecer el valor disableoutputbuffer (que es lo que queremos), parece que actualmente también necesita especificar un bootstrapper. Crear una clase en su ensamblado que hereda de Nancy.Hosting.Aspnet.DefaultNancyAspNetBootstrapper y especificarlo en el archivo de configuración parece funcionar.

<configSections> 
    <section name="nancyFx" type="Nancy.Hosting.Aspnet.NancyFxSection" /> 
</configSections> 
<nancyFx> 
    <bootstrapper assembly="YourAssembly" type="YourBootstrapper"/> 
    <disableoutputbuffer value="true" /> 
</nancyFx> 

Después, no debe establecer el encabezado Transfer-Encoding. Más bien, la siguiente definición de la ruta aparece para transmitir correctamente los resultados de mi servidor de desarrollo IIS Express para Chrome:

Get["/chunked"] = _ => 
{ 
    var response = new Response(); 
    response.ContentType = "text/plain"; 
    response.Contents = s => 
    { 
    byte[] bytes = System.Text.Encoding.UTF8.GetBytes("Hello World "); 
    for (int i = 0; i < 10; ++i) 
    { 
     for (var j = 0; j < 86; j++) 
     { 
     s.Write(bytes, 0, bytes.Length); 
     } 
     s.WriteByte(10); 
     s.Flush(); 
     System.Threading.Thread.Sleep(500); 
    } 
    }; 

    return response; 
}; 

he especificado más contenido por porción que el ejemplo anterior, debido a los tamaños mínimos antes del primer render documentado en otros StackOverflow questions

0

Si usa .NET 4.5+, puede usar Stream.CopyTo en lugar de flush.

Get["/chunked"] = _ => 
{ 
    var response = new Response(); 
    response.ContentType = "text/plain"; 
    response.Contents = s => 
    { 
    using(var helloStream = new MemoryStream(Encoding.UTF8.GetBytes("Hello World "))) 
     helloStream.CopyTo(s); 
    } 
    return response; 
} 
Cuestiones relacionadas