users@jersey.java.net

Re: [Jersey] HTTP Form Posting using Jersey Client vs Apache HttpClient

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 14 Apr 2010 09:10:37 +0200

On Apr 13, 2010, at 7:10 PM, Arul Dhesiaseelan wrote:

> I have logged an issue (505) for the ClassCastException.

Thanks.


> Here is the request debug snip from HttpClient, I do see the
> whitespace, and it may very well be the case here:
>
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> "Content-
> Disposition: form-data; name="
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> """
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> "file"
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> """
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> "; filename="
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> """
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> "customer.bin"
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> """
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> "[\r][\n]"
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> "Content-Type: "
> 2010/04/13 10:54:51:893 MDT [DEBUG] content - >> "application/octet-
> stream"
> 2010/04/13 10:54:51:894 MDT [DEBUG] content - >> "; charset="
> 2010/04/13 10:54:51:894 MDT [DEBUG] content - >> "ISO-8859-1"
> 2010/04/13 10:54:51:894 MDT [DEBUG] content - >> "[\r][\n]"
> 2010/04/13 10:54:51:894 MDT [DEBUG] content - >> "Content-Transfer-
> Encoding: "
> 2010/04/13 10:54:51:894 MDT [DEBUG] content - >> "binary"
> 2010/04/13 10:54:51:894 MDT [DEBUG] content - >> "[\r][\n]"
> 2010/04/13 10:54:51:894 MDT [DEBUG] content - >> "[\r][\n]"
>
> I will try to get access to the server side logs, I am not positive
> though :-(
>

OK. You could try modifying the Jersey Content-Disposition source code
to include a white space after the ';'.

The only other thing i can think of is the Apache HTTP client is
sending a "Content-Transfer-Encoding: binary". That header serves as
an indicator and should not affect processing.


> Thanks for your help again.
>

Np,
Paul.

> Arul.
>
>
> On Apr 13, 2010, at 3:08 AM, Paul Sandoz wrote:
>
>> Hi Arul,
>>
>> There is a silly bug in the multipart module. Can you log an issue.
>>
>> However, i think this is orthogonal to the problem you are
>> encountering. HTTP headers are case insensitive, and Jersey will
>> anyway re-write the Content-Type header value to include the
>> boundary string parameter that declared the delimitation string
>> between body parts.
>>
>> My suspicion is the CGI script cannot parse the value of the
>> Content-Type or Content-Disposition headers. But it would help if
>> you could get access to some sort of server-side information.
>>
>> Developers have reported cases of services consume multipart/form-
>> data being sensitive to white space characters between parameters
>> of media types and content disposition types. Jersey does not use
>> white space.
>>
>> From Jersey:
>>
>> Content-Disposition: form-data;name="file"
>>
>> From Apache HTTP client:
>>
>> Content-Disposition: form-data; name="file"
>>
>> Paul.
>>
>>
>> On Apr 12, 2010, at 6:35 PM, Arul Dhesiaseelan wrote:
>>
>>> Hi Paul,
>>>
>>> I noticed other thing in the requests, the header is set to
>>> "Content-type: multipart/form-data" in case of HttpClient and
>>> "Content-Type: multipart/form-data" in case of JerseyClient, note
>>> the case change in Type. I am not sure if this is causing any of
>>> these problems. I thought of checking this by manually setting the
>>> header using the Jersey Client, but I get a ClassCastException
>>> when performing the POST in the following code:
>>>
>>> ClientResponse response = resource.header("Content-type",
>>> "multipart/form-data").post(ClientResponse.class, multiPart);
>>>
>>> Here is the exception trace (I am using version 1.1.5.1):
>>>
>>> 1 * Out-bound request
>>> 1 > POST https://test.com/cgi-bin/submit.cgi
>>> 1 > Content-type: multipart/form-data
>>> 1 >
>>> Exception in thread "main"
>>> com.sun.jersey.api.client.ClientHandlerException:
>>> java.lang.ClassCastException: java.lang.String
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .client
>>> .urlconnection
>>> .URLConnectionClientHandler.handle(URLConnectionClientHandler.java:
>>> 128)
>>> at
>>> com
>>> .sun
>>> .jersey.api.client.filter.LoggingFilter.handle(LoggingFilter.java:
>>> 152)
>>> at com.sun.jersey.api.client.Client.handle(Client.java:435)
>>> at
>>> com.sun.jersey.api.client.WebResource.handle(WebResource.java:557)
>>> at com.sun.jersey.api.client.WebResource.access
>>> $300(WebResource.java:69)
>>> at com.sun.jersey.api.client.WebResource
>>> $Builder.post(WebResource.java:499)
>>> at
>>> coderyte.flux.poc.JerseyClientTest.main(JerseyClientTest.java:77)
>>> Caused by: java.lang.ClassCastException: java.lang.String
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .multipart.impl.MultiPartWriter.writeTo(MultiPartWriter.java:129)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .multipart.impl.MultiPartWriter.writeTo(MultiPartWriter.java:68)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .api
>>> .client
>>> .TerminatingClientHandler
>>> .writeRequestEntity(TerminatingClientHandler.java:317)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .client
>>> .urlconnection
>>> .URLConnectionClientHandler
>>> ._invoke(URLConnectionClientHandler.java:179)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .client
>>> .urlconnection
>>> .URLConnectionClientHandler.handle(URLConnectionClientHandler.java:
>>> 126)
>>> ... 6 more
>>>
>>> Any clues?
>>>
>>> -Arul
>>>
>>>
>>> On Mon, Apr 12, 2010 at 8:00 AM, Arul Dhesiaseelan <aruld.info_at_gmail.com
>>> > wrote:
>>> Hi Paul,
>>>
>>> I removed the below line from the Apache HTTP Client code and it
>>> still works. So, it looks like auth in not enabled on the CGI
>>> script.
>>> filePost.setDoAuthentication(true);
>>>
>>> Unfortunately, I do not have access to the server side.
>>>
>>> Thanks,
>>> Arul
>>>
>>>
>>> On Mon, Apr 12, 2010 at 3:16 AM, Paul Sandoz <Paul.Sandoz_at_sun.com>
>>> wrote:
>>> Hi,
>>>
>>> The odd thing is in your Apache HTTP client code you have not
>>> specified any credentials. So are you sure authentication on the
>>> CGI script is enabled?
>>>
>>> Can you send the full HTTP request response exchange when using
>>> both clients and any logging information from the CGI script?
>>>
>>>
>>> Paul.
>>>
>>> On Apr 12, 2010, at 5:12 AM, Arul Dhesiaseelan wrote:
>>>
>>>> Hi,
>>>>
>>>> I am trying to use Jersey client to do a multipart form submit to
>>>> a CGI script. But, the service returns the HTML form instead of
>>>> the actual response. I have the code which works on Apache
>>>> HttpClient. I am not sure what I am missing here. Can someone help?
>>>>
>>>> POST using Apache HttpClient (this code works):
>>>>
>>>> HttpClient client = new HttpClient();
>>>> PostMethod filePost = new PostMethod("https://test.com/cgi-bin/submit.cgi
>>>> ");
>>>> filePost.setDoAuthentication(true);//process authentication
>>>> challenges authomatically
>>>> File targetFile = new File("customer.bin");
>>>> Part[] parts = { new FilePart("file", targetFile),
>>>> new StringPart("user", "username"),
>>>> new StringPart("password", "password"),
>>>> new StringPart("type", "X32") };
>>>> filePost.setRequestEntity(new MultipartRequestEntity(parts,
>>>> filePost.getParams()));
>>>> filePost.setRequestHeader("Content-type","multipart/form-data");
>>>> int status = client.executeMethod(filePost);
>>>>
>>>> Log output:
>>>>
>>>> 2010/04/11 17:20:21:594 MDT [DEBUG] header - >> "POST /cgi-bin/
>>>> submit.cgi HTTP/1.1[\r][\n]"
>>>> 2010/04/11 17:20:21:595 MDT [DEBUG] HttpMethodBase - Adding Host
>>>> request header
>>>> 2010/04/11 17:20:21:620 MDT [DEBUG] header - >> "Content-type:
>>>> multipart/form-data[\r][\n]"
>>>> 2010/04/11 17:20:21:621 MDT [DEBUG] header - >> "User-Agent:
>>>> Jakarta Commons-HttpClient/3.1[\r][\n]"
>>>> 2010/04/11 17:20:21:621 MDT [DEBUG] header - >> "Host:
>>>> test.com[\r][\n]"
>>>> 2010/04/11 17:20:21:621 MDT [DEBUG] header - >> "Content-Length:
>>>> 117417[\r][\n]"
>>>> 2010/04/11 17:20:21:621 MDT [DEBUG] header - >> "[\r][\n]"
>>>> 2010/04/11 17:20:21:622 MDT [DEBUG] content - >> "--"
>>>> 2010/04/11 17:20:21:622 MDT [DEBUG] content - >>
>>>> "giTfSy0R4Zrd7j4lruBwymHkrZRJdNLD5kV4zcM"
>>>> 2010/04/11 17:20:21:622 MDT [DEBUG] content - >> "[\r][\n]"
>>>> 2010/04/11 17:20:21:622 MDT [DEBUG] content - >> "Content-
>>>> Disposition: form-data; name="
>>>> 2010/04/11 17:20:21:623 MDT [DEBUG] content - >> """
>>>> 2010/04/11 17:20:21:623 MDT [DEBUG] content - >> "file"
>>>> 2010/04/11 17:20:21:623 MDT [DEBUG] content - >> """
>>>> 2010/04/11 17:20:21:623 MDT [DEBUG] content - >> "; filename="
>>>> 2010/04/11 17:20:21:623 MDT [DEBUG] content - >> """
>>>> 2010/04/11 17:20:21:623 MDT [DEBUG] content - >> "customer.bin"
>>>> 2010/04/11 17:20:21:623 MDT [DEBUG] content - >> """
>>>> 2010/04/11 17:20:21:623 MDT [DEBUG] content - >> "[\r][\n]"
>>>> 2010/04/11 17:20:21:623 MDT [DEBUG] content - >> "Content-Type: "
>>>> 2010/04/11 17:20:21:623 MDT [DEBUG] content - >> "application/
>>>> octet-stream"
>>>> 2010/04/11 17:20:21:624 MDT [DEBUG] content - >> "; charset="
>>>> 2010/04/11 17:20:21:624 MDT [DEBUG] content - >> "ISO-8859-1"
>>>> 2010/04/11 17:20:21:624 MDT [DEBUG] content - >> "[\r][\n]"
>>>> 2010/04/11 17:20:21:624 MDT [DEBUG] content - >> "Content-
>>>> Transfer-Encoding: "
>>>> 2010/04/11 17:20:21:624 MDT [DEBUG] content - >> "binary"
>>>> 2010/04/11 17:20:21:624 MDT [DEBUG] content - >> "[\r][\n]"
>>>> 2010/04/11 17:20:21:624 MDT [DEBUG] content - >> "[\r][\n]"
>>>> ...............
>>>>
>>>> POST using Jersey Client (this does not work) :
>>>>
>>>> MultiPart multiPart = new MultiPart();
>>>> WebResource.Builder builder = resource.getRequestBuilder();
>>>> File targetFile = new File("customer.bin");
>>>> FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("file",
>>>> targetFile, MediaType.APPLICATION_OCTET_STREAM_TYPE);
>>>> multiPart.bodyPart(fileDataBodyPart);
>>>> FormDataBodyPart formDataBodyPart = new FormDataBodyPart("user",
>>>> "username);
>>>> multiPart.bodyPart(formDataBodyPart);
>>>> formDataBodyPart = new FormDataBodyPart("password", "password");
>>>> multiPart.bodyPart(formDataBodyPart);
>>>> formDataBodyPart = new FormDataBodyPart("tyoe", "X32");
>>>> multiPart.bodyPart(formDataBodyPart);
>>>> ClientResponse response = builder.type("multipart/form-
>>>> data").post(ClientResponse.class, multiPart);
>>>>
>>>> Log output:
>>>>
>>>> INFO: 1 * Client out-bound request
>>>> 1 > POST https://test.com/cgi-bin/submit.cgi
>>>> 1 > Content-Type: multipart/form-data
>>>> 1 >
>>>>
>>>> --Boundary_1_1839257702_1271040995070
>>>> Content-Type: application/octet-stream
>>>> Content-Disposition: form-data;name="file"
>>>>
>>>> ........
>>>>
>>>> I tried using FormDataMultiPart, but no luck. I am not sure what
>>>> translates to setDoAuthentication() API in Jersey Client.
>>>>
>>>> I also tried something like using the ApacheHttpClient API in
>>>> Jersey Client, but same result:
>>>>
>>>> DefaultApacheHttpClientConfig config = new
>>>> DefaultApacheHttpClientConfig();
>>>> config.getState().setCredentials(null, null, -1,
>>>> "username", "password");
>>>>
>>>> config
>>>> .getProperties
>>>> ().put(ApacheHttpClientConfig.PROPERTY_PREEMPTIVE_AUTHENTICATION,
>>>> true);
>>>>
>>>> ApacheHttpClient client = ApacheHttpClient.create(config);
>>>>
>>>> I must be missing something fundamental here. Appreciate any
>>>> suggestions.
>>>>
>>>> -Arul
>>>
>>>
>>>
>>
>
>