Ändern Sie den HttpServletRequest-Text

8

Ich arbeite an Legacy-Code und muss einen Patch machen.

Das Problem: Eine alte Anwendung sendet fehlerhafte HTTP-POST-Anfragen. Einer der Parameter ist nicht URL-codiert. Ich weiß, dass dieser Parameter immer zuletzt kommt und ich weiß seinen Namen. Ich versuche jetzt, es auf der Serverseite zu beheben, die in Tomcat ausgeführt wird.

Dieser Parameter ist nicht über die getParameter-Standardmethode von HttpServletRequest verfügbar, da er fehlerhaft ist. Methode gibt einfach null zurück. Aber wenn ich manuell den ganzen Körper der Anfrage durch ServletInputStream lese, verschwinden alle anderen Parameter. Sieht so aus, als könnten darunterliegende Klassen den Inhalt von ServletInputStream nicht analysieren, da er leer ist.

Bisher habe ich einen Wrapper erstellt, der alle Parameter von body liest und alle Parameterzugriffsmethoden überschreibt. Aber wenn irgendein Filter in der Kette vor mir versucht, auf irgendeinen Parameter zuzugreifen, wird alles brechen, da ServletInputStream leer ist.

Kann ich dieses Problem irgendwie umgehen? Könnte es anders sein?

Zusammenfassend: Wenn ich den Rohanforderungskörper im Filter lese, werden die Parameter aus der Anfrage verschwinden. Wenn ich einen einzelnen Parameter lese, wird ServletInputStream leer und eine manuelle Verarbeitung ist nicht möglich. Darüber hinaus ist es unmöglich, fehlerhafte Parameter über die getParameter-Methode zu lesen.

    
clorz 25.03.2009, 11:59
quelle

5 Antworten

9

Lösung, die ich gefunden habe:

Es ist nicht genug, Parameterzugriffsmethoden neu zu definieren. Mehrere Dinge müssen getan werden.

  1. Ein Filter wird benötigt, wenn die Anfrage umgebrochen wird.
  2. Ein benutzerdefinierter HttpRequestWrapper wird benötigt, damit alle Parameterzugriffsmethoden überschrieben werden. Der Anfragetext sollte im Konstruktor geparst und als Feld gespeichert werden.
  3. Die Methoden getInputStream und getReader sollten ebenfalls neu definiert werden. Die Rückgabewerte hängen vom gespeicherten Anfragetext ab.
  4. Die benutzerdefinierte Klasse, die ServletInputStream erweitert, ist erforderlich, da diese eine Zusammenfassung ist.

Mit diesen vier kombinierten Funktionen können Sie getParameter ohne Beeinträchtigung der Methoden getInputStream und getReader verwenden.

Beachten Sie, dass das Parsen von manuellen Anfrageparametern mit mehrteiligen Anfragen kompliziert werden kann. Aber das ist ein anderes Thema.

Um dies zu verdeutlichen, habe ich Parameterzugriffsmethoden neu definiert, weil meine Anfrage wie in der Frage angegeben beschädigt wurde. Du brauchst das vielleicht nicht.

    
clorz 31.03.2009, 08:39
quelle
8

Warum sollten Sie anstelle eines Überschreibens von Methoden einen Servlet-Filter installieren, der die Anfrage umschreibt?

Jason Hunter hat einen ziemlich guten Artikel über Filter .

    
Jon Skeet 25.03.2009 12:04
quelle
5

Ich habe einen vollständigeren Wrapper erstellt, mit dem Sie immer noch auf den Inhalt zugreifen können, wenn der Inhaltstyp "application / x-www-form-urlencoded" lautet und Sie bereits eine der Methoden getParameterXXX aufgerufen haben:

%Vor%     
Plamen 07.05.2009 14:13
quelle
3

Ich wollte dies als Kommentar posten, aber ich habe nicht genug Rep. Ihre Lösung ist unzureichend, da ServletInputStreamWrapper negative ganze Zahlen zurückgibt. Zum Beispiel, mock eine Anfrage mit Eingabe-Codierung UTF-16, entweder Big oder Little Endian. Die Eingabe kann mit der Byte Order Mark beginnen, die Endianess anzeigt, und wenn ich meine Aussage teste, bitte konstruiere den Mock Request Inhalt um dies zu tun. Ссылка Eine dieser Stücklisten enthält ein 0xFF-Byte. Da Java kein vorzeichenloses Byte hat, wird dieses 0xFF als -1 zurückgegeben. Um dies zu umgehen, ändern Sie einfach die Lesefunktion wie folgt

%Vor%

Ich mag Ihre Lösung etwas, weil sie gut mit Spring funktioniert. Zuerst habe ich versucht, einen Teil des Delegationscodes, den Sie geschrieben haben, zu entfernen, indem ich von HttpServletRequestWrapper erweitert habe. Spring macht jedoch etwas Interessantes: Wenn es auf eine Anfrage vom Typ ServletRequestWrapper stößt, entfaltet es es und ruft getRequest () auf. Problem ist, dass meine Methode getRequest (), wie aus Ihrem Code kopiert, eine neue Klasse zurückgibt, die sich von HttpServletRequestWrapper erstreckt ... spülen und unendlich wiederholen. Es ist also traurig zu sagen, einen Gewinn für den Verzicht auf Schnittstellen zu erzielen!

    
DanielKWinsor 11.09.2013 20:53
quelle
1

Sie könnten Ihren eigenen Servlet-Filter schreiben und hoffentlich sicherstellen, dass er zuerst in der Kette erscheint. Wickeln Sie dann das ServletRequest-Objekt in etwas, das das Neuschreiben bei Bedarf übernimmt. Sehen Sie sich den Abschnitt Benutzerdefinierte Anforderungen und Antworten für die Programmierung von Ссылка

an

------ Aktualisierung ------

Ich muss etwas verpassen. Sie sagen, Sie können den Anfragetext lesen und die Parameter selbst lesen. Könnten Sie dann nicht sicherstellen, dass Ihr Filter zuerst ist, das ServletRequest-Objekt umschließen, die Parameter lesen, verarbeiten und speichern, Ihr Anfrageobjekt die Kette hinaufreichen und die von Ihnen gespeicherten Parameter anstelle der ursprünglichen Parameter anbieten?

    
Matt Large 25.03.2009 12:09
quelle

Tags und Links