sahaya / rest-assured

Automatically exported from code.google.com/p/rest-assured
0 stars 0 forks source link

Missing content-type in multipart/form-data request #223

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
*** What steps will reproduce the problem?
1. Create any request that is multipart/form-data.
2. Try sending a String as "application/json":

String metadata = "{ \"number\": 4 }"

given()
  .multiPart("metadata", metadata, "application/json")

*** The request body sent to the server SHOULD BE:

--RandomBoundaryString
Content-Disposition: form-data; name="metadata"
Content-Type: application/json

{  "number": 4 }
--RandomBoundaryString--

*** The request body ACTUALLY SENT to the server:
--RandomBoundaryString
Content-Disposition: form-data; name="metadata"

{  "number": 4 }
--RandomBoundaryString--

*** My configuration
OS: Windows 7 (Microsoft Windows [Version 6.1.7600])
JDK: jdk1.7.0_13
Rest-Assured: rest-assured-1.7.2.jar

Other Libs:
- antlr-2.7.7.jar
- asm-3.2.jar
- asm-analysis-3.2.jar
- asm-commons-3.2.jar
- asm-tree-3.2.jar
- asm-util-3.2.jar
- groovy-1.8.4.jar
- hamcrest-core-1.2.1.jar
- hamcrest-library-1.2.1.jar
- httpclient-4.2.3.jar
- httpcore-4.2.2.jar
- httpmime-4.2.3.jar
- tagsoup-1.2.1.jar

Without the content-type, my application server is not able to deserialize the 
JSON content. It tries to interpret it as 'plain/text'.

I examined RestAssured code quickly and could not determine if it's a issue 
with RestAssured or Apache HTTP Client.

Attached in the file:
- JUnit Test case using RestAssured that sends the incorrect request.
- Simple HTTP Server to verify the request being sent.

Original issue reported on code.google.com by victorcl...@gmail.com on 1 Apr 2013 at 3:02

Attachments:

GoogleCodeExporter commented 9 years ago
This seems to be an issue with Apache HttpMime. The following code using Apache 
HttpComponents 4.2.3 exhibits the same behavior.

HttpClient httpClient = new DefaultHttpClient();
MultipartEntity entity = new 
MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.addPart("metadata", new StringBody(getImageFieldMetadata(), 
"application/json", Charset.forName("UTF-8")));
HttpPost httpPost = new HttpPost("http://localhost:8080/");
httpPost.setEntity(entity);
httpClient.execute(httpPost);

Original comment by victorcl...@gmail.com on 1 Apr 2013 at 9:12

GoogleCodeExporter commented 9 years ago
Thanks for reporting. How do you suggest we go about? Is there a new version of 
HttpMime that address the issue? 

Original comment by johan.ha...@gmail.com on 2 Apr 2013 at 4:58

GoogleCodeExporter commented 9 years ago
I found the problem. It's a simple configuration detail.

I posted an Issue on Apache HttpComponents's JIRA with that code and was 
informed that HttpMultipartMode.BROWSER_COMPATIBLE makes the MultipartEntity 
omit the 'Content-Type' and 'Content-Transfer-Encoding' flags for compatibility 
with older web servers.

However, that does not work properly with JBoss AS 7 and RESTEasy though, as 
RESTEasy tries to interpret the data as 'plain/text' (the default when 
Content-Type is omitted according to the RFC) instead of 'application/json'.

On 
src/main/groovy/com/jayway/restassured/internal/RequestSpecificationImpl.groovy,
 line 905, we can see that RestAssured is constructing the MultipartEntity with 
the BROWSER_COMPATIBLE flag.

In my opinion, Rest Assured should let this be configured by the user. The 
default behavior for MultipartEntity is HttpMultipartMode.STRICT, which is RFC 
compliant. This could also be the default behavior for RestAssured.

More information about this can be found in the JavaDocs:
http://hc.apache.org/httpcomponents-client-ga/httpmime/apidocs/org/apache/http/e
ntity/mime/HttpMultipartMode.html#STRICT

http://hc.apache.org/httpcomponents-client-ga/httpmime/apidocs/org/apache/http/e
ntity/mime/MultipartEntity.html

Thanks for creating this great library! Please let me know if something is not 
clear in my explanation.

Original comment by victorcl...@gmail.com on 2 Apr 2013 at 11:11

GoogleCodeExporter commented 9 years ago
Thanks for investigating. I'll try to find time to implement this in the next 
release.

Original comment by johan.ha...@gmail.com on 2 Apr 2013 at 12:06

GoogleCodeExporter commented 9 years ago
Fixed in git master. It's now possible to configure the multipart mode using 
the HttpClientConfig in REST Assured. Thanks for your help!

Original comment by johan.ha...@gmail.com on 14 Apr 2013 at 2:13

GoogleCodeExporter commented 9 years ago
Thank you for such an awesome library!

Original comment by victorcl...@gmail.com on 14 Apr 2013 at 3:36

GoogleCodeExporter commented 9 years ago
Is this fixed in a release?

Original comment by jessica....@gmail.com on 30 May 2013 at 9:10

GoogleCodeExporter commented 9 years ago
No it's not yet released. Though you can use a snapshot release if you like. 
Depend on version 1.8.1-SNAPSHOT after having added the following maven repo:

<repositories>
        <repository>
            <id>sonatype</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
            <snapshots />
        </repository>
</repositories>

Original comment by johan.ha...@gmail.com on 30 May 2013 at 9:23

GoogleCodeExporter commented 9 years ago
Thanks, this is working now. However, I cannot change the charset used. Is 
there a way to do this?

Original comment by jessica....@gmail.com on 30 May 2013 at 12:56

GoogleCodeExporter commented 9 years ago
Could you share how your test looks like?

Original comment by johan.ha...@gmail.com on 30 May 2013 at 1:01

GoogleCodeExporter commented 9 years ago
HttpClientConfig clientConfig = new HttpClientConfig();
clientConfig.httpMultipartMode(HttpMultipartMode.STRICT);

RestAssuredConfig raConfig = new RestAssuredConfig();
raConfig.httpClient(clientConfig);

RequestSpecification req = given().filter(new RequestLoggingFilter(System.out))
                .header(USERID_HEADER, "th\\mdulpers")
                .header(TENANTID_HEADER, "1234")
                .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)
                .header(IDMSESSIONID_HEADER, "RandomStringValue")
                .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA)
                .header(REQUESTID_HEADER, UUID.randomUUID().toString())
                .config(raConfig)
                .multiPart("request", draftInput, "application/xml")
                .multiPart("config", docConfig, "application/xml");

        Response response = req.post("v1/job/finalizeDraft");

I have tried using the EncoderConfig but it doesn't work. The multipart is 
created as:
"aPL2ZUSloKKtdhubafA_AS0a0u-i5fIe"
"[\r][\n]"
"Content-Disposition"
": "
"form-data; name="request""
"[\r][\n]"
"Content-Type"
": "
"application/xml; charset=US-ASCII"
"[\r][\n]"
"Content-Transfer-Encoding"
": "
"8bit"

But I want to use UTF-8. Thanks.

Original comment by jessica....@gmail.com on 30 May 2013 at 1:04

GoogleCodeExporter commented 9 years ago
Thanks. Just looked in the code and it seems like it's actually not possible :( 
Please add it as a new issue.

Original comment by johan.ha...@gmail.com on 30 May 2013 at 1:09

GoogleCodeExporter commented 9 years ago
https://code.google.com/p/rest-assured/issues/detail?id=239

Original comment by jessica....@gmail.com on 30 May 2013 at 1:29