0
votes

Using Apache Http 4.5 MultipartEntityBuilder and can't seem to figure out why the StringBody(String, ContentType) constructor doesn't actually output the Content-Type in the request form body.

public HttpRequestBase build() throws UnsupportedEncodingException {
    HttpPost httpPost = new HttpPost("https://{server}/restapi/{apiVersion}/accounts/{accountId}/envelopes");

    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.setContentType(ContentType.MULTIPART_FORM_DATA);
    builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    builder.setBoundary("AAA");

    //add form body
    builder.addPart(generateJsonFormBodyPart());

    //add file body
    builder.addPart(generateFileFormBodyPart()); //<--intentionally omitted

    HttpEntity multipart = builder.build();

    httpPost.setEntity(multipart);

    return httpPost;

}

private FormBodyPart generateJsonFormBodyPart() throws UnsupportedEncodingException{
        StringBody json = new StringBody(packageJson(), ContentType.APPLICATION_JSON); //<--THIS DOESN'T SEEM TO WORK    
        StringBuilder buffer = new StringBuilder();
        buffer.append("form-data");

        String contentDisposition = buffer.toString();

        FormBodyPartBuilder partBuilder = FormBodyPartBuilder.create("application/json", json);
        partBuilder.setField(MIME.CONTENT_DISPOSITION, contentDisposition);

        FormBodyPart fbp = partBuilder.build();

        return fbp;
    }

The file portion outputs ok but I get a "Bad Request" return from the peer which I assume is because it has very specific request parameters.


Required Request Output

Accept: application/json Content-Type: multipart/form-data; boundary=AAA

--AAA Content-Type: application/json Content-Disposition: form-data

json removed

--AAA Content-Type: application/pdf Content-Disposition: file; filename="test1.pdf";documentid=1

document removed


Actual Apache Http 4.5 Output

X-Docusign-Act-As-User: [email protected] Accept-Encoding: gzip,deflate User-Agent: Apache-HttpClient/4.5 (Java/1.8.0_65) Connect-Time: 0 Host: requestb.in Connection: close Content-Length: 3178 Authorization: bearer xxxxrandomoauthtokenxxxxx Content-Type: multipart/form-data; boundary=AAA; charset=ISO-8859-1 Via: 1.1 vegur X-Request-Id: 89cd1cf5-3615-41e8-84ba-cd076a03af67 Total-Route-Time: 0

--AAA Content-Disposition: form-data //<--the problem. should be application/json no?

{"status":"created","emailBlurb":"Welcome to Confluence","emailSubject":"Welcome to Confluence","documents":{"name":"Welcome to Confluence.html","documentId":"1","order":"1"},"recipients":{}}

--AAA Content-Disposition: file; filename="Welcome.html";documentid=1 Content-Type: text/html; charset=ISO-8859-1

h t m l string removed

Q: So why does the ContentType in the StringBody constructor get ignored? Is there a workaround or am I doing it wrong?

1

1 Answers

1
votes

I'm convinced this is a bug in Apache Http Mime for the FormBodyPart.build() when processing a StringBody. Evidence from release notes of 4.5.2 indicating bug fixes for other "body" types not outputting "Content-Type" supports this. I will be logging a defect.

The Workaround:

private FormBodyPart generateJsonFormBodyPart() throws UnsupportedEncodingException{
    StringBody json = new StringBody(getMyJsonStuff(), ContentType.APPLICATION_JSON); //<--THE GOGGLES, THEY DO NOTHING!!

    StringBuilder buffer = new StringBuilder();
    buffer.append("form-data");
    buffer.append("\r\n");
    buffer.append("Content-Type: application/json"); //<--tack this on to the 

    String kludgeForDispositionAndContentType = buffer.toString();

    FormBodyPartBuilder partBuilder = FormBodyPartBuilder.create("stuff", json);
    partBuilder.setField(MIME.CONTENT_DISPOSITION, kludgeForDispositionAndContentType);

    FormBodyPart fbp = partBuilder.build();

    return fbp;
}

Works like a charm.