2012-07-14 14 views
5

Sto scrivendo una semplice applicazione web usando Nancy. Almeno una richiesta genera un flusso di lunghezza sconosciuta, quindi non posso fornire Content-Length. Mi piacerebbe usare Transfer-Encoding: chunked o (ugualmente accettabile in questo caso, Connection: close).Come si scrive l'output in streaming in NancyFX?

Ho avuto un attacco rapido al codice sorgente di Nancy e ho aggiunto Response.BufferOutput e codice per impostare HttpContext.Response.BufferOutput su false. Si può vedere che qui:

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); 
       } 
      }; 
     } 
    } 

Non sembra avere alcun effetto. La risposta si attiva tutto in una volta, dopo 5 secondi. Ho provato questo un semplice client basato su WebRequest.

Come faccio a ottenere l'output Chunked su Nancy? Sto usando l'hosting ASP.NET, ma sarei interessato alle risposte per le altre opzioni di hosting.

Se scrivo un server semplice utilizzando HttpListener, posso impostare SendChunked a true, ed invia in uscita Chunked, che il mio semplice client riceve correttamente in blocchi.

+0

Dove hai impostato HttpContext.Response.BufferOutput nel codice Nancy? E hai mai trovato un modo per farlo funzionare con OWIN? – Hooligancat

+0

Non ricordo, mi dispiace. –

+0

vedi la risposta contrassegnata su questa domanda => http://stackoverflow.com/questions/29953301/stream-an-sqlfile-stream-using-nancy – sp3tsnaz

risposta

4

È necessario chiamare Flush() dopo ogni Write(), altrimenti la risposta viene memorizzata in ogni caso. Inoltre, Google Chrome non esegue il rendering dell'output finché non viene ricevuto tutto.

Ho scoperto questo scrivendo una semplice applicazione client che registrava quello che stava leggendo dal flusso di risposta al suo arrivo.

+0

Quindi questo è "ordinato"? –

+1

Non proprio. La modifica "BufferOutput" non si trova nel core Nancy e funziona solo per l'hosting ASP.NET. Per WCF, devi modificare WebHttpBinding, non riesco a far funzionare correttamente l'auto hosting e non riesco a vedere alcun modo per farlo con l'hosting OWIN. –

+0

@RogerLipscombe sei mai arrivato ovunque con questo? Sto cercando di farlo funzionare con NancyFx + ASP.NET – RPM1984

5

Durante la mia sperimentazione, ho scoperto che avevo bisogno della seguente configurazione. Innanzitutto, imposta il tuo file web.config come documentato nello Nancy Wiki. Vale la pena notare che per impostare il valore disableoutputbuffer (che è ciò che vogliamo), sembra che al momento sia necessario specificare anche un bootstrapper. La creazione di una classe nell'assembly che eredita da Nancy.Hosting.Aspnet.DefaultNancyAspNetBootstrapper e la sua specifica nel file di configurazione sembra funzionare.

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

Successivamente, non impostare l'intestazione Transfer-Encoding. Piuttosto, la seguente definizione percorso appare per lo streaming correttamente i risultati del mio server di sviluppo IIS Express per 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; 
}; 

ho specificato più contenuti per pezzo rispetto all'esempio precedente a causa delle dimensioni minime prima del primo render documentate in altri StackOverflow questions

0

Se si utilizza .NET 4.5+, in alternativa è possibile utilizzare Stream.CopyTo anziché 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; 
} 
Problemi correlati