So erhalten Sie Formularparameter im Anforderungsfilter

Ich versuche, die Formularparameter einer Anforderung in einem Anforderungsfilter abzurufen:

@Override
public ContainerRequest filter(final ContainerRequest request) {

    final Form formParameters = request.getFormParameters();

    //logic

    return request;
}

Das Formular scheint jedoch immer leer zu sein. DasHttpRequestContext.getFormParameters() Dokumentation sagt:

Ruft die Formularparameter der Anforderungsentität ab.

Diese Methode stellt sicher, dass die Anforderungsentität so gepuffert wird, dass sie von der Anwendung verwendet werden kann.

Kehrt zurück: die Formularparameter, wenn es eine Anforderungsentität 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 kommentiert@Consumes("application/x-www-form-urlencoded"), obwohl es erst nach dem Anforderungsfilter abgeglichen wurde - funktioniert das deshalb nicht?

Ich habe einige Nachforschungen angestellt, konnte aber keine schlüssigen Beweise dafür finden, ob dies möglich ist. Dort warDiese 4-jährige Diskussion, in dem Paul Sandoz sagt:

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

Habe ich auch gefundenDiese 3-jährige Diskussion Informationen zum Abrufen von mehrteiligen / Formulardaten-Formularfeldern in einem Anforderungsfilter. Darin verwendet Paul Sandoz 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, diesen Ansatz zu emulierenForm stattdessen aber das Ergebnis vonrequest.getEntityInputStream() ist immer ein leerer Strom. Und schau zudie Quelle vongetFormParametersTatsächlich macht diese Methode bereits dasselbe:

@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 den Entitätseingabestrom verschluckt, bevor ich dazu komme. Etwas in Jersey muss es verbrauchen, da die Formularparameter später an die Ressourcenmethode übergeben werden. Was mache ich hier falsch oder ist das unmöglich (und warum)?

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

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 überflüssige)Anforderungsprotokollierung:

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 Antwortheader dieser Anfrage, einschließlich derJersey 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ällige) Servlet-Konfiguration:

<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 Beispielressource:

@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();
    }
}

Ich benutze Jersey 1.17.

Für Interessenten versuche ich, meine eigene erforderliche Parameterüberprüfung durchzuführen, wie in beschriebenJERSEY-351. Meine LösungHier Arbeitete für Abfrage-, Cookie- und Header-Parameter - Formular-Parameter halten mich in Schach.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage