Comment puis-je sans risque d'interception du flux de la Réponse à une coutume Owin Middleware
Je suis en train d'écrire une simple OWIN Middleware, afin d'intercepter le flux de réponse. Ce que j'essaie de faire est de remplacer le flux d'origine avec personnalisés à partir de Flux de classe, où je serai en mesure d'intercepter écrit dans le flux de réponse.
Cependant, je suis confronté à quelques problèmes parce que je ne peut pas savoir quand la réponse a été entièrement écrite par l'intérieur des composants intergiciels dans la chaîne. Le Dispose
de remplacer le Flux n'est jamais appelée. Donc, je ne sais pas quand il est temps de faire mon traitement, ce qui devrait arriver à la fin du Flux de réponse.
Voici un exemple de code:
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.
}
}
Comme je l'ai déjà évoqué dans les commentaires du code ci-dessus, il y a deux stratégies que je pense, afin de détecter si la réponse est complète.
a) je peux enregistrer le nombre d'octets écrits dans le flux de réponse et de corréler que la longueur de la réponse. Toutefois, dans le cas de réponses qui utilisent l'Encodage de Transfert en Bloc, la durée n'est pas connue.
b) je peux décider que le flux de réponse est complète lorsque Dispose
est appelée sur le flux de réponse. Cependant, la OWIN/Katana de l'infrastructure n'appelle jamais Céder sur l'remplacé flux.
J'ai étudié Opaque En Streaming afin de voir si la manipulation de la sous-jacentes HTTP protocole de serait une approche possible, mais je ne semble pas trouver si Katana support Opaque en Streaming ou pas.
Est-il un moyen de réaliser ce que je veux ?
Vous devez vous connecter pour publier un commentaire.
Je ne pense pas que vous aurez besoin d'un sous-classés flux, mais puis ici, c'est la façon dont vous pouvez lire la réponse. Assurez-vous juste de ce middleware est le premier dans la OWIN pipeline de sorte qu'il sera le dernier à inspecter la réponse.
BTW, autant que je sache, découlant de
OwinMiddleware
n'est pas considéré comme une bonne pratique carOwinMiddleware
est spécifique à Katana. Il est cependant rien à voir avec votre problème.OwinMiddleware
. Cependant, dans votre réponse, vous êtes à l'aideOwinContext
qui est également spécifique à Katana. Ai-je raté quelque chose ?OwinContext
en interne pour le middleware, ce qui signifie que je vais prendre une dépendance sur le Katana. Cependant, en n'utilisant pas dans le constructeur ouInvoke
signatures de méthode, je ne force pas les autres assemblées de prendre une dépendance sur Katana. Celui qui construit le OWIN pipeline n'a pas besoin de savoir quelque chose au sujet deOwinMiddleware
. De même, lorsqu'un middleware avant cette dans le pipeline appelsInvoke
.Using
? Je vois cela dans la plupart des middleware de Réponse\Demande de Messages.. c'Est juste parce qu'elle est connue, la durée de vie du middleware est court?