How to get form Parameter in der request-filter
Ich versuche, den form-Parameter einer Anfrage in eine Anfrage filter:
@Override
public ContainerRequest filter(final ContainerRequest request) {
final Form formParameters = request.getFormParameters();
//logic
return request;
}
Jedoch die form scheint immer leer zu sein. Die HttpRequestContext.getFormParameters()
Dokumentation sagt:
Get form Parameter der Anfrage-Entität.
Diese Methode wird sichergestellt, dass der Antrag Entität ist gepuffert, so dass es sein kann, verbraucht die applicaton.
Gibt:
die Parameter form, wenn es eine Anforderung Einheit und der content type "application/x-www-form-urlencoded", sonst eine Instanz, die keine Parameter zurückgegeben werden.
Meine Ressource ist versehen mit @Consumes("application/x-www-form-urlencoded")
, obwohl es wird nicht abgeglichen wurden, bis nach der Anforderung filter - ist es das, warum funktioniert das nicht?
Ich habe versucht zu tun, einige Forschung, aber konnten keine schlüssigen Beweise dafür, ob dies möglich ist. Es war dieser 4-jährige Diskussion, in denen Paul Sandoz sagt:
Wenn Sie in der Jersey-Filter oder mit der
HttpRequestContext
können Sie den form-Parameter wie folgt: [broken link zu Jersey 1.1.1HttpRequestContext.getFormParameters
]
Fand ich auch diese 3-jährige Diskussion über, wie man multipart/form-data Formular-Felder in einem filter "Anforderung". In es, Paul Sandoz verwendet den folgenden code:
//Buffer
InputStream in = request.getEntityInputStream();
if (in.getClass() != ByteArrayInputStream.class) {
//Buffer input
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ReaderWriter.writeTo(in, baos);
} catch (IOException ex) {
throw new ContainerException(ex);
}
in = new ByteArrayInputStream(baos.toByteArray());
request.setEntityInputStream(in);
}
//Read entity
FormDataMultiPart multiPart = request.getEntity(FormDataMultiPart.class);
Ich habe versucht, zu emulieren, dass der Ansatz für Form
statt, aber das Ergebnis request.getEntityInputStream()
ist immer ein leerer stream. Und schaut der Quellcode von getFormParameters
, dass die Methode ist in der Tat die gleiche Sache schon:
@Override
public Form getFormParameters() {
if (MediaTypes.typeEquals(MediaType.APPLICATION_FORM_URLENCODED_TYPE, getMediaType())) {
InputStream in = getEntityInputStream();
if (in.getClass() != ByteArrayInputStream.class) {
//Buffer input
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
ReaderWriter.writeTo(in, byteArrayOutputStream);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
in = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
setEntityInputStream(in);
}
ByteArrayInputStream byteArrayInputStream = (ByteArrayInputStream) in;
Form f = getEntity(Form.class);
byteArrayInputStream.reset();
return f;
} else {
return new Form();
}
}
Ich kann nicht herausfinden, was schlürfen bis die Einheit Eingabe-stream, bevor ich um es zu bekommen. Etwas in Jersey werden müssen konsumieren, weil es den form-Parametern werden später weitergereicht an die Ressource-Methode. Was mache ich hier falsch, oder ist das unmöglich (und warum)?
EDIT: Hier ist ein Beispiel für eine Anfrage gesendet:
POST /test/post-stuff HTTP/1.1
Host: local.my.application.com:8443
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
form_param_1=foo&form_param_2=bar
Hier ist die (etwas redundant) request-Erfassung:
INFO: 1 * Server in-bound request
1 > POST https://local.my.application.com:8443/test/post-stuff
1 > host: local.my.application.com:8443
1 > connection: keep-alive
1 > content-length: 33
1 > cache-control: no-cache
1 > origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
1 > user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
1 > content-type: application/x-www-form-urlencoded
1 > accept: */*
1 > accept-encoding: gzip,deflate,sdch
1 > accept-language: en-US,en;q=0.8
1 > cookie: [omitted]
1 >
Hier sind die Antwort-Header der Anforderung, einschließlich der Jersey-Trace:
Content-Type →application/json;charset=UTF-8
Date →Fri, 09 Aug 2013 18:00:17 GMT
Location →https://local.my.application.com:8443/test/post-stuff/
Server →Apache-Coyote/1.1
Transfer-Encoding →chunked
X-Jersey-Trace-000 →accept root resource classes: "/post-stuff"
X-Jersey-Trace-001 →match path "/post-stuff" -> "/post\-stuff(/.*)?", [...], "(/.*)?"
X-Jersey-Trace-002 →accept right hand path java.util.regex.Matcher[pattern=/post\-stuff(/.*)? region=0,11 lastmatch=/post-stuff]: "/post-stuff" -> "/post-stuff" : ""
X-Jersey-Trace-003 →accept resource: "post-stuff" -> @Path("/post-stuff") com.application.my.jersey.resource.TestResource@7612e9d2
X-Jersey-Trace-004 →match path "" -> ""
X-Jersey-Trace-005 →accept resource methods: "post-stuff", POST -> com.application.my.jersey.resource.TestResource@7612e9d2
X-Jersey-Trace-006 →matched resource method: public javax.ws.rs.core.Response com.application.my.jersey.resource.TestResource.execute(java.lang.String,java.lang.String)
X-Jersey-Trace-007 →matched message body reader: class com.sun.jersey.api.representation.Form, "application/x-www-form-urlencoded" -> com.sun.jersey.core.impl.provider.entity.FormProvider@b98df1f
X-Jersey-Trace-008 →matched message body writer: java.lang.String@f62, "application/json" -> com.sun.jersey.core.impl.provider.entity.StringProvider@1c5ddffa
Hier ist die (unauffällig) servlet config:
<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.application.my.jersey</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>com.application.my.jersey.MyFilterFactory</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.feature.Trace</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Hier ist die Beispiel-resource:
@Path("/post-stuff")
@Produces(MediaType.APPLICATION_JSON)
public final class TestResource {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response execute(
@FormParam("form_param_1") final String formParam1,
@FormParam("form_param_2") final String formParam2
) {
return Response.created(URI.create("/")).entity("{}").build();
}
}
Bin ich mit Jersey 1.17.
Für diejenigen, die interessiert sind, ich bin versucht zu Rollen, meine eigene erforderlich überprüfung der parameter, wie beschrieben in JERSEY-351. Meine Lösung hier arbeitete für die Abfrage, cookie und header Parameter - form params halten sich auf mich.
- Können Sie uns eine Anfrage, die Sie versenden den rest-Endpunkt.
- Siehe mein edit, und laß mich wissen, wenn es etwas gibt, was ich bieten kann.
formParam1
undformParam2
sindnull
in Ihrem Ressource-Methode so gut ist? Nur um sicher zu seinMyFilterFactory
enthält#filter
Methode aus deinem ersten snippet?formParam1
undformParam1
übergeben werden, die in die Ressource-Methode wie erwartet (nichtnull
). Ja,MyFilterFactory
erstellt die Ressource-filter, die erstellt die container request-filter mit, dassfilter
Umsetzung.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies war eine knifflige Sache. Ich würde entfernt, die andere Jersey-Filter, um Sie zu beseitigen aus das problem, jedoch nicht mit einem einfachen servlet-filter versteckt an der Unterseite von
web.xml
:Entfernen dieser filter wurde das Problem behoben - form params zeigte sich in der Jersey-filter. Aber warum? Ich grub tiefer, eine Eingrenzung des Problems auf eine einzige Anweisung
MyFilter
:Ich habe versucht, zu vereinfachen das problem sogar noch durch das entfernen
MyFilter
und machen den gleichen Anruf in der Jersey-filter (durch EinspritzenHttpServletRequest
) - aber die Parameter form, noch auftauchte. Das Problem scheint zu passieren, insbesondere, wenn die BerufunggetParameter
auf dieorg.apache.catalina.connector.RequestFacade
- Instanz übergeben bekommt injavax.- servlet.Filter.doFilter
. So ist das in der Tat ein Tomcat-bug?In der Dokumentation von
ServletRequest.getParameter
sagt:Also vielleicht das Gegenteil ist auch wahr -, dass der Aufruf
getParameter
könnte erlaubt werden, sich mit den entity-input-stream? Es ist mir unklar, ob die Methode der Vertrag ermöglicht es für dieses Verhalten, und ob es gibt einen bug in Tomcat, Jersey, oder auch nicht.Sowieso, der alte filter war gar nicht nötig, so mein Problem ist gelöst, aber nur, es zu entfernen.
Hier ist eine vollständige Reproduktion des Problems (Tomcat 7.0):
web.xml
:TestServletFilter.java
:TestFilterFactory.java
:TestResource.java
:Stellen Sie sicher, dass Ihre
ResourceFilterFactory
erstellt eine Instanz vonResourceFilter
für dieTestResource#execute
Methode, die erstellt dann einContainerRequestFilter
Beispiel:Aus der
trace
Sie haben vorausgesetzt ich bin nicht sicher, ob IhrContainerRequestFilter
genannt wird. Es sollte eine weitere trace-header mit so etwas wie dieses:Die ganze Spur von meinem test:
EDIT 1:
Aktivieren Anfrage
LoggingFilter
:EDIT 2:
Auch sicherstellen, dass keine anderen Servlet-oder Jersey-filter Lesen Sie die
InputStream
vor. In einem solchen Fall der entity-input-stream nicht mehr verfügbar (aber Sie können immer noch Spritzen@FormParam
in Ihre Ressource-Methode - wie in diesem Fall).Form
ist leer in seiner Ausführung. Ich legte Jersey Quelle und folgte ihm durchgetFormParameters
- es schreibt der input-stream in denByteArrayOutputStream
richtig, aber der stream leer ist. Ich bin mir nicht sicher, warum Sie sehen, dass zusätzliche message-body-reader Spur und ich bin mir nicht - man kommt aus Ihrer BerufunggetFormParameters
aber was ist die andere?1.18-SNAPSHOT
. Die erstenmatched message body reader
ist ausgetEntity(Form.class)
imContainerRequest#getFormParameters()
, die zweite ist von der form param Injektor, bevor Sie in die Ressource-Methode. Können Sie, bitte, aktivierenLoggingFilter
(siehe EDIT 1 in meiner Antwort) und bieten log?