So erhalten Sie Formularparameter im Anforderungsfilter

8

Ich versuche, die Formularparameter einer Anfrage in einem Anforderungsfilter zu erhalten:

%Vor%

Die Form scheint jedoch immer leer zu sein. Die HttpRequestContext.getFormParameters() Dokumentation sagt:

  

Erhalte die Formularparameter der Anfrageeinheit.

     

Diese Methode stellt sicher, dass die Request-Entity so gepuffert ist, dass sie von der Anwendung konsumiert werden kann.

     

Rückgabe:   die Formularparameter, wenn es eine Anfrageeinheit gibt und der Inhaltstyp "application / x-www-form-urlencoded" ist, andernfalls wird eine Instanz zurückgegeben, die keine Parameter enthält.

Meine Ressource ist mit @Consumes("application/x-www-form-urlencoded") versehen, obwohl sie erst nach dem Anforderungsfilter gefunden wurde - funktioniert das nicht?

Ich habe versucht, Nachforschungen anzustellen, konnte aber keine schlüssigen Beweise dafür finden, ob dies möglich ist. Es gab diese 4 Jahre alte Diskussion , in dem Paul Sandoz sagt:

  

Wenn Sie in Jersey-Filtern oder mit HttpRequestContext arbeiten, können Sie die Formularparameter wie folgt erhalten: [defekter Link zu Jersey 1.1.1 HttpRequestContext.getFormParameters ]

Ich fand auch diese 3-jährige Diskussion zum Erhalten von Multipart / Formulardatenformularfeldern in einem Anforderungsfilter. Darin verwendet Paul Sandoz den folgenden Code:

%Vor%

Ich habe versucht, diesen Ansatz für Form zu emulieren, aber das Ergebnis von request.getEntityInputStream() ist immer ein leerer Stream. Und schau dir Die Quelle von getFormParameters , diese Methode macht tatsächlich dasselbe:

%Vor%

Ich kann nicht herausfinden, was den Entity-Eingabestrom verschlingt, bevor ich dazu komme. Etwas in Jersey muss es verbrauchen, weil die Formparameter später in die Ressourcenmethode übernommen werden. Was mache ich hier falsch, oder ist das unmöglich (und warum)?

BEARBEITEN: Hier ist ein Beispiel für eine gesendete Anfrage:

%Vor%

Hier ist die (etwas überflüssige) Anfrage Protokollierung :

%Vor%

Hier sind die Antwortheader dieser Anfrage, einschließlich Jersey Trace :

%Vor%

Hier ist die (unauffällige) Servlet-Konfiguration:

%Vor%

Hier ist die Beispielressource:

%Vor%

Ich benutze Jersey 1.17.

Für diejenigen, die daran interessiert sind, versuche ich, meine eigene erforderliche Parameterprüfung durchzuführen, wie in JERSEY-351 beschrieben >. Meine Lösung hier arbeitete für Abfrage-, Cookie- und Header-Parameter - form params halten mich ab.

    
Paul Bellora 09.08.2013, 01:32
quelle

2 Antworten

2

Das war eine schwierige Frage. Ich hatte andere Jersey-Filter entfernt, um sie von dem Problem zu entfernen, aber ich vermisste einen einfachen Servlet-Filter, der sich am unteren Rand von web.xml versteckt:

%Vor%

Durch das Entfernen dieses Filters wurde das Problem behoben - Formularparameter wurden im Jersey-Filter angezeigt. Aber warum? Ich grub tiefer und beschränkte das Problem auf eine einzige Aussage in MyFilter :

%Vor%

Ich habe versucht, das Problem noch weiter zu vereinfachen, indem ich MyFilter entfernte und denselben Aufruf im Jersey-Filter machte (indem ich HttpServletRequest injizierte) - aber die Formularparameter tauchten immer noch auf. Das Problem scheint speziell beim Aufruf von getParameter in der Instanz org.apache.catalina.connector.RequestFacade zu passieren, die an javax.servlet.Filter.doFilter . Ist das tatsächlich ein Tomcat Bug?

Die Dokumentation von ServletRequest.getParameter sagt:

  

Wenn die Parameterdaten im Anfragetext gesendet wurden, wie dies bei einer HTTP-POST-Anfrage der Fall ist, kann das direkte Lesen des Textkörpers über getInputStream() oder getReader() die Ausführung dieser Methode beeinträchtigen.

Vielleicht ist das Gegenteil auch der Fall - dass das Aufrufen von getParameter den Entity-Eingabestream stören könnte? Es ist mir unklar, ob der Vertrag der Methode dieses Verhalten zulässt und ob es einen Fehler in Tomcat, Jersey oder beidem anzeigt.

Wie auch immer, dieser alte Filter wurde nicht wirklich benötigt, also ist mein Problem gelöst, aber nur entfernt.

Hier ist eine vollständige Reproduktion des Problems (Tomcat 7.0):

web.xml :

%Vor%

TestServletFilter.java :

%Vor%

TestFilterFactory.java :

%Vor%

TestResource.java :

%Vor%     
Paul Bellora 15.08.2013, 17:01
quelle
1

Stellen Sie sicher, dass Ihre ResourceFilterFactory eine Instanz von ResourceFilter für die Methode TestResource#execute erstellt, die dann eine ContainerRequestFilter -Instanz erstellt:

%Vor%

Von der von Ihnen bereitgestellten trace bin ich nicht sicher, ob Ihr ContainerRequestFilter aufgerufen wurde. Es sollte noch einen weiteren Header geben, der so etwas enthält:

%Vor%

Die ganze Spur von meinem Test:

%Vor%

EDIT 1:

Aktiviere Anfrage LoggingFilter :

%Vor%

EDIT 2:

Stellen Sie außerdem sicher, dass kein anderer Servlet- oder Jersey-Filter den InputStream zuvor gelesen hat. In diesem Fall ist der Entity-Eingabestream möglicherweise nicht mehr verfügbar (Sie können jedoch wie in diesem Fall @FormParam weiterhin in Ihre Ressourcenmethode einfügen).

    
Michal Gajdos 13.08.2013 09:00
quelle