Sto provando a scrivere un semplice middleware OWIN, per intercettare il flusso di risposta. Quello che sto cercando di fare è sostituire lo stream originale con una classe personalizzata basata su Stream, dove potrò intercettare le scritture nel flusso di risposta.Come intercettare in modo sicuro lo stream di risposta in un Owin Middleware personalizzato
Tuttavia, sto affrontando alcuni problemi perché non posso sapere quando la risposta è stata completamente scritta da componenti middleware interni della catena. L'override Dispose
del flusso non viene mai chiamato. Quindi non so quando è il momento di eseguire la mia elaborazione, che dovrebbe accadere alla fine della risposta Stream.
Ecco un esempio di codice:
public sealed class CustomMiddleware: OwinMiddleware
{
public CustomMiddleware(OwinMiddleware next)
: base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
var request = context.Request;
var response = context.Response;
// capture response stream
var vr = new MemoryStream();
var responseStream = new ResponseStream(vr, response.Body);
response.OnSendingHeaders(state =>
{
var resp = (state as IOwinContext).Response;
var contentLength = resp.Headers.ContentLength;
// contentLength == null for Chunked responses
}, context);
// invoke the next middleware in the pipeline
await Next.Invoke(context);
}
}
public sealed class ResponseStream : Stream
{
private readonly Stream stream_; // MemoryStream
private readonly Stream output_; // Owin response
private long writtenBytes_ = 0L;
public ResponseStream(Stream stream, Stream output)
{
stream_ = stream;
output_ = output;
}
... // System.IO.Stream implementation
public override void Write(byte[] buffer, int offset, int count)
{
// capture writes to the response stream in our local stream
stream_.Write(buffer, offset, count);
// write to the real output stream
output_.Write(buffer, offset, count);
// update the number of bytes written
writtenBytes_ += count;
// how do we know the response is complete ?
// we could check that the number of bytes written
// is equal to the content length, but content length
// is not available for Chunked responses.
}
protected override void Dispose(bool disposing)
{
// we could perform our processing
// when the stream is disposed of.
// however, this method is never called by
// the OWIN/Katana infrastructure.
}
}
Come ho accennato nei commenti del codice di cui sopra, ci sono due strategie che mi viene in mente al fine di rilevare se la risposta è completa.
a) È possibile registrare il numero di byte scritti nel flusso di risposta e correlarlo alla lunghezza di risposta prevista. Tuttavia, nel caso di risposte che utilizzano Chunked Transfer Encoding, la lunghezza non è nota.
b) Posso decidere che il flusso di risposta è completo quando Dispose
viene richiamato nel flusso di risposta. Tuttavia, l'infrastruttura OWIN/Katana non chiama mai Dispose sullo stream sostituito.
Ho indagato su Opaque Streaming per vedere se la manipolazione del protocollo HTTP sottostante sarebbe un approccio fattibile, ma non mi sembra di capire se Katana supporti o meno Opaque Streaming.
C'è un modo per ottenere ciò che voglio?
Grazie per la risposta. Punto preso circa derivando da 'OwinMiddleware'. Tuttavia, nella tua risposta, stai usando 'OwinContext', che è anche specifico per Katana. Mi sto perdendo qualcosa ? –
Sì, sei corretto. Ma sto usando 'OwinContext' internamente al middleware, il che significa che sto prendendo una dipendenza da Katana. Tuttavia, non utilizzandolo nel costruttore o nelle firme del metodo 'Invoke', non costringo altri assembly a fare affidamento su Katana. Chiunque costruisca la pipeline OWIN non ha bisogno di sapere nulla di 'OwinMiddleware'. Allo stesso modo, quando un middleware prima di questo nella pipeline chiama 'Invoke'. – Badri
Sono riuscito a trovare un collegamento a una risposta SO di David Fowler relativa a questo. http://stackoverflow.com/a/19613529/1709870 – Badri