users@jersey.java.net

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

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 13 Apr 2010 11:08:08 +0200

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