dev@jersey.java.net

Re: [Jersey] How to get encoded entity in filter?

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 12 May 2009 11:15:53 +0200

On May 12, 2009, at 2:33 AM, Paul C. Bryan wrote:

> What is the best way to access the request entity when a filter is
> invoked?
>
> A bit of background:
>
> 1. The filter needs to access the entity because it may be POST of
> application/x-www-form-urlencoded content.
>
> 2. The filter probably shouldn't assume the object type of the entity
> (e.g. MultivaluedMapImpl), because any type of Java object could
> represent the message body, to be encoded in a deeper layer
> (MessageBodyWriter?)
>

Correct.


> So, what's the best way to get the encoded version of the entity in
> the
> filter handle method, without inadvertently changing other states
> (e.g.
> prematurely writing headers, etc.)?
>
> Alternately, is it a safe enough assumption that POST of
> x-www-form-urlencoded will ALWAYS have an entity type of
> MultivaluedMapImpl?
>

No. Because it may be processed as a String for byte[] if say the
request is forwarded to something else.

The best way is on a POST request with the content type "application/x-
www-form-urlencoded" is to buffer the request entity to a byte array,
the logging filter does this:

https://jersey.dev.java.net/nonav/apidocs/1.1.0-ea/jersey/com/sun/jersey/api/container/filter/LoggingFilter.html

     public ContainerRequest filter(ContainerRequest request) {
         // Check if a POST and a content type of "application/x-www-
form-urlencoded"

         ByteArrayOutputStream out = new ByteArrayOutputStream();
         InputStream in = request.getEntityInputStream();
         try {
             // Buffer the request
             int read;
             final byte[] data = new byte[2048];
             while ((read = in.read(data)) != -1)
                 out.write(data, 0, read);

             byte[] requestEntity = out.toByteArray();
             ByteArrayInputStream bais = new
ByteArrayInputStream(requestEntity));
             request.setEntityInputStream(bais);

             // Get the request as an instance of Form
             Form f = request.getEntity(Form.class);
             // Do some checking

             // reset the input stream so it can be re-read
             bais.reset();

             return request;
         } catch (IOException ex) {
             throw new ContainerException(ex);
         }

     }


What i think the above implies is we could make it easier to perform
such operations.

Paul.