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 18:14:12 +0200

On May 12, 2009, at 6:08 PM, Paul C. Bryan wrote:

> Unfortunately, the side effect of this would be that the headers would
> already be written. Too late for me. :(
>

As i said in a previous email this should be possible with
ClientRequestAdapter: the first byte written to the OutputStream
received from the adapt method will commit the request headers, so
there is the opportunity to obtain the complete entity as an array of
bytes, add more headers based on the value of those bytes, then write
those bytes, which will commit the headers.

Paul.

> On Tue, 2009-05-12 at 12:06 -0400, Marc Hadley wrote:
>> On May 12, 2009, at 11:45 AM, Paul C. Bryan wrote:
>>
>>> Right, as it's serialized. I don't see a way to get the entity in
>>> its
>>> encoded form when in the handle() method.
>>>
>>> So, I could assume the entity is a MultivaluedMap, which I think the
>>> majority of the time, it will be when it's POST
>>> application/x-www-form-urlencoded. But it could be other types, up
>>> to
>>> the caller of the client library, correct? For example, String
>>> (pre-encoded) seems to work if I pass that in as the entity to the
>>> client library.
>>>
>>> What I'm trying to do: I want to get the entity body to extract form
>>> parameters, in order to calculate a digital signature.
>>>
>>> I considered just assuming it's MultivaluedMap, and throwing
>>> exception
>>> otherwise, but was hoping there could be a way I could get the
>>> encoded
>>> entity (which I would then decode) to allow virtually any object
>>> type to
>>> be provided -- flexibility.
>>>
>> Ideally then you'd like to be able to get the entity after the
>> message
>> body writer has done its work. That way you'd always be working
>> with a
>> stream of bytes.
>>
>> Marc.
>>
>>>
>>> On Tue, 2009-05-12 at 17:28 +0200, Paul Sandoz wrote:
>>>> On May 12, 2009, at 5:15 PM, Paul C. Bryan wrote:
>>>>
>>>>> Thanks for the info.
>>>>>
>>>>> My apologies, I wasn't clear, in my case I was referring to Jersey
>>>>> client filter. The client logging filter only reports on the
>>>>> response
>>>>> entity, not the request entity.
>>>>
>>>> It reports both. The request side of the filter sets a
>>>> ClientRequestAdapter to log the output as it is being serialized.
>>>>
>>>>
>>>>> What's the easy way to get the entity
>>>>> there?
>>>>>
>>>>
>>>> ClientRequest.getEntity();
>>>>
>>>> https://jersey.dev.java.net/nonav/apidocs/1.1.0-ea/jersey/com/sun/jersey/api/client/ClientRequest.html
>>>> #getEntity()
>>>>
>>>> Since the entity of the request will be an object, you can check in
>>>> this case for an instance of the form type you are utilizing,
>>>> essentially/ an instance of MultivaluedMap.
>>>>
>>>> If you need access to this entity to do something specific with it
>>>> then you are going to have to make some assumptions about the type.
>>>> Difficult for me to offer advice in this respect without knowing
>>>> more
>>>> about what you want to do with the entity.
>>>>
>>>> Paul.
>>>>
>>>>> Paul
>>>>>
>>>>> On Tue, 2009-05-12 at 11:15 +0200, Paul Sandoz wrote:
>>>>>> 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.
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
>>>>>> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>>>>>>
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
>>>>> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
>>>> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
>>> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>