Lesen Sie den POST-Body von HTTPServletRequest UND rufen Sie dann getParameter in Tomcat auf

8

Ich bin in der Situation, in der meine Anwendung den Inhalt / Daten / Körper / Payload einer POST-Anfrage untersuchen muss, ohne die Ergebnisse der nachfolgenden getParameter-Aufrufe zu ändern.

Lesen des Körpers aus dem inputStream:

Der Body kann mit dem InputStream von request.getInputStream oder BufferedReader von request.getReader gelesen werden.

Lesen von POST-Parametern:

POST-Anfragen enthalten normalerweise Anforderungsparameter im Hauptteil der Anfrage. Diese können mit getParameter abgerufen werden.

Das Problem:

Der erste getParameter -Aufruf parst intern den InputStream und fügt alle Parameter in einen Parameter HashMap ein. Es erfordert, dass der inputStream immer noch den Inhalt zum Parsen enthält. Daher kann man den Inhalt nicht überprüfen und trotzdem einen funktionierenden getParameter-Aufruf haben.

Vorgeschlagene (aber nicht ausreichende) Lösung

Erstellen Sie einen Anforderungswrapper, der den Eingabestream zwischenspeichert und den Cache für getInputStream zurückgibt.

Ich habe die im Web vorgeschlagene Lösung gesehen, aber es funktioniert nicht, weil getParameter nicht tatsächlich getInputStream aufruft, sondern sich auf den ursprünglichen in den Request-Objekt eingebetteten inputBuffer bezieht. Ich habe es versucht, sowohl aus dem Servlet als auch mit einem Filter

Die einzige Lösung, die ich mir vorstellen kann, ist das Umschreiben von getParameter, um den zwischengespeicherten Eingabestream manuell zu analysieren. Aber das fühlt sich wie eine schlechte Idee an.

Hat jemand eine Alternative, die funktioniert? (Dies ist Tomcat 5.5) Dies fühlt sich an, als sollte es ein häufiger Anwendungsfall sein; Ich kann nicht glauben, wie schwer es ist.

    
rewolf 28.08.2013, 13:31
quelle

2 Antworten

1

Wie von @caskey vorgeschlagen, wäre eine mögliche Lösung, reflection zu verwenden, um den inputBuffer durch einen wiedergabefähigen Eingabepuffer zu ersetzen. Aber ich habe diesen Ansatz nicht benutzt, weil er sich ungezogen anfühlte.

Stattdessen habe ich einen Anforderungswrapper in einem Filter erstellt, der den Eingabestream in ein Bytearray liest und ein neues InputStream zurückgibt, das intern ein ByteArrayInputStream um dieses Array für alle getInputStream Aufrufe verwendet.

Nach dem Lesen des Eingabestreams in das Bytearray, erstelle ich eine Parameterzuordnung, indem ich die Nutzlast analysiere. Ich habe die Superklassen-Parameterzuordnung zusammengeführt, um GET-Fälle mit Abfrageparametern zu unterstützen. Ich habe alle getParameter * () -Methoden überschrieben, um diese Parameterzuordnung zu verwenden.

Ich habe apache.axis.utils.IOUtils.readFully verwendet, um den Stream einfach in das Byte-Array einzulesen. Und ich verwende derzeit javax.servlet.http.HttpUtils.parsePostData , um die Daten in Parameter-Map zu parsen. HttpUtils.parsePostData ist eigentlich veraltet, daher werde ich es wahrscheinlich durch eine bessere Version ersetzen, wenn ich es finde.

Aber das funktioniert, yay!

    
rewolf 03.09.2013, 07:41
quelle
1

(Das ist ein ziemlich alter Kater, ich gehe davon aus, dass ein Upgrade auf ein moderneres keine Option ist.)

Was Sie tun möchten, muss die Konstruktion des konkreten HttpServletResponse-Objekts abfangen, das den zugrunde liegenden InputStream umhüllt. Es ist notwendig, diesen InputStream in einem Push-Back-Eingabestream (oder einem Äquivalent) zu verpacken.

Tomcat 5.5 ist so alt, dass ich nicht einmal daran denken kann, wie das "normal" erreicht werden würde. Aber vielleicht könnten Sie einen Filter schreiben, der das InputStream-Objekt innerhalb des konkreten Request-Objekts erreicht und austauscht.

>     
caskey 03.09.2013 02:45
quelle

Tags und Links