On Oct 9, 2009, at 10:27 AM, Zoltan Arnold NAGY wrote:
> Paul Sandoz wrote:
>>
>> On Oct 9, 2009, at 10:13 AM, Zoltan Arnold NAGY wrote:
>>
>>> Zoltan Arnold NAGY wrote:
>>>> Paul Sandoz wrote:
>>>>>
>>>>> On Oct 7, 2009, at 5:36 PM, Felipe Gaucho wrote:
>>>>>
>>>>>> A filter?
>>>>>>
>>>>>
>>>>> Yes, see ClientFilter and the source code for the LoggingFilter
>>>>> (see below because java.net is so damn slow).
>>>>>
>>>>> You need to return an output stream in the implementation of
>>>>> AbstractClientRequestAdapter .adapt that buffers the bytes then
>>>>> on the close calculates the hash, sets the header and writes out
>>>>> the bytes of the buffered output stream to the actual output
>>>>> stream.
>>>> Thanks, it seems to be working. :)
>>> Spoken too soon.
>>> In the message to be hashed I need to add the method, the date,
>>> and other data as well.
>>>
>>> It seems to me that if I do a simple .get() (no entity present)
>>> and I do attach an adapter with
>>> request.setAdapter(new Adapter(request.getAdapter(), b));
>>> then it's adapt() method wont even get called (at least I've put
>>> logging there, and never saw
>>> it's output).
>>>
>>> In all the examples I've seen one only attaches such an adapter if
>>> there's an entity present, so
>>> I'm thinking that maybe these request adaptert are only used to
>>> modify the entity's serialized form?
>>>
>>
>> Yes, because it is adapting a *request* entity. If there is no
>> request entity present then no adaption will occur because there is
>> nothing to adapt.
>>
>> Do you want to hash a request entity or a response entity?
> It's a bit more complicated than that :)
>
> from Amazon's docs: (http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/index.html?RESTAuthentication.html
> ):
>
> StringToSign = HTTP-Verb + "\n" +
> Content-MD5 + "\n" +
> Content-Type + "\n" +
> Date + "\n" +
> CanonicalizedAmzHeaders +
> CanonicalizedResource;
>
> For example, let's say Jersey would send this request:
> GET /testresource HTTP/1.1
> Content-type: application/json
> Host: test.something.com
>
> then I'd still need to alter it and calculate the hash from various
> input fields as seen above, and add the header to it.
> Of course, if there _is_ an entity, I'd need to include it's
> serialized (xml/json/whatever) form in the calculations.
>
> Is there a way to catch the output stream before it gets written at
> all to the server?
>
Yes, that is what a filter is for, you can modify the request headers.
You just need to work out if there is an entity present or not to
decide where the creation of the signed string and header addition
occurs. See ClientRequest.getEntity(). If it returns null then
adaption will not occur, unless another filter further along in the
filter chain adds one (a security filter should really be the last one
in the chain).
@Override
public ClientResponse handle(ClientRequest request) throws
ClientHandlerException {
if (request.getEntity() != null) {
// Adapt request and do signing with adaption
request.setAdapter(new Adapter(request.getAdapter()));
} else {
// Do signing here
}
ClientResponse response = getNext().handle(request);
return response;
}
I agree it is a little inconsistent. Perhaps it would have been better
to have start, and finish methods on ClientRequestAdapter which are
always called whether an entity is present or not.
Paul.