Wie implementiere ich einen HTTP-Antwortfilter, um den gesamten Inhalt gleichzeitig zu verarbeiten, ohne Chunking

8

Wie in einigen anderen Posts erwähnt (siehe Referenzen unten), versuche ich Antwortfilter zu erstellen, um Inhalte zu ändern, die von einer anderen Webanwendung erzeugt werden.

Ich habe die grundlegende String-Transformationslogik, die funktioniert und in Filter eingekapselt ist, die von einer gemeinsamen FilterBase abgeleitet sind. Die Logik muss jedoch auf den vollständigen Inhalt und nicht auf Inhaltsblöcke angewendet werden. Daher muss ich die Chunks zwischenspeichern, während sie geschrieben werden, und den Filter ausführen, wenn alle Schreibvorgänge abgeschlossen sind.

Wie unten gezeigt, habe ich einen neuen ResponseFilter erstellt, der von MemoryStream abgeleitet wurde. Beim Schreiben wird der Inhalt in einen anderen MemoryStream zwischengespeichert. Bei Flush wird der gesamte Inhalt, der jetzt im MemoryStream ist, in eine Zeichenfolge konvertiert und die Filter-Logik wird aktiviert. Der geänderte Inhalt wird dann wieder in den ursprünglichen Stream geschrieben.

Jedoch wird bei jeder zweiten Anfrage (im Grunde, wenn ein neuer Filter instanziert wird) die Flush-Methode des vorherigen Filters ausgeführt. An diesem Punkt stürzt die Anwendung mit der _outputStream.Write () -Methode ab, da der _cachedStream leer ist.

Die Reihenfolge des Ereignisses ist wie folgt:

  1. Erste Anfrage
  2. Schreibmethode heißt
  3. Flush-Methode heißt
  4. Die Methode zum Schließen wird
  5. genannt
  6. Die Methode zum Schließen wird
  7. genannt
  8. An dieser Stelle kehrt die App zurück und der richtige Inhalt wird angezeigt.
  9. Zweite Anfrage
  10. Flush-Methode heißt
  11. Die Anwendung stürzt bei _outputStream.Write ab. ArgumentOutOfRangeException (offset).
  12. Weiter durch Absturz (in Visual Studio)
  13. Die Methode zum Schließen wird
  14. genannt

Es gibt ein paar Fragen, die ich habe:

  1. Warum wird Close zweimal aufgerufen?
  2. Warum wird Flush aufgerufen, nachdem Closed aufgerufen wurde?
  3. Nach Jay's Punkt kann Flush aufgerufen werden, bevor der Stream vollständig gelesen wurde. Wo sollte die Filterlogik liegen? In der Nähe? In Flush, aber mit "wenn geschlossen"?
  4. Was ist die richtige Implementierung für einen Antwortfilter, der gleichzeitig für den gesamten Inhalt funktioniert?

Hinweis : Ich erlebe das exakt gleiche Verhalten (minus Schließen von Ereignissen), wenn ich die Close-Methode nicht überschreibe.

%Vor%

Referenzen:

Ryan Taylor 16.12.2010, 20:19
quelle

2 Antworten

7

Dank eines Tipps von Jay, dass Flush für inkrementelle Schreibvorgänge aufgerufen wurde, konnte ich den Filter wie gewünscht ausführen, indem ich die Filterlogik nur dann durchführe, wenn der Filter schließt und noch nicht geschlossen ist. Dadurch wird sichergestellt, dass der Filter beim Schließen des Streams nur einmal gespült wird. Ich habe dies mit ein paar einfachen Feldern erreicht, _isClosing und _isClosed, wie im letzten Code unten gezeigt.

%Vor%

Ich habe noch keine Antworten auf meine anderen oben genannten Fragen gefunden, daher werde ich diese Antwort zu diesem Zeitpunkt nicht als ausgenommen markieren.

    
Ryan Taylor 17.12.2010 03:41
quelle
0

Flush wird nicht explizit aufgerufen. Vielleicht wird es aufgerufen, wenn der Code erkennt, dass ein neues Objekt benötigt wird, oder vielleicht als Ergebnis eines Finalizers.

Ich denke, man kann flush nach jedem inkrementellen Schreiben aufrufen, daher bin ich mir nicht sicher, ob ein Aufruf zum Leeren sowieso eine ausreichende Anzeige für eine vollständige Nachricht ist.

    
jay 16.12.2010 20:50
quelle

Tags und Links