javajerseyjersey-clientjersey-1.0

How to disable chunked encoding and use buffered for Jersey 1?


I am encountering a HTTP response status of 411 Length Required when performing a call to a 3rd party service in my application.

The problem seems to be related to chuncked encoding, switching it to buffered would solve the problem. There is a solution here for Jersey2: Jersey Http Client replying with 411 on POST request

However due to some legacy, we are using Jersey1 in our application and we can not perform a migration in the close future.

I tried to isolate the problem. Here is the minimal code:

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.json.JSONConfiguration;


/**
 * Main
 */
public class Main {

  public static void main(String[] args) {
    ClientConfig clientConfig = new DefaultClientConfig();
    clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
    clientConfig.getProperties().put(ClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, null);
    Client client = Client.create(clientConfig);

    String postURL = "https://api.napster.com/v2.2/me/library/tracks?id=tra.169783383,tra.30621111";
    WebResource webResourcePost = client.resource(postURL);
    webResourcePost.header("Content-Length", 0);
    ClientResponse response = webResourcePost.type("application/json").post(ClientResponse.class);
    System.out.println(response.getStatus());
  }

}

Here is build.gradle:

apply plugin: 'application'
apply plugin: 'java'

repositories {
  mavenCentral()
  mavenLocal()
}

mainClassName = "Main"

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
    compile group: 'com.sun.jersey.contribs', name: 'jersey-apache-client', version: '1.19.4'
    compile group: 'com.sun.jersey', name: 'jersey-json', version: '1.19.4'
}

What I have tried is to add the configuration which would switch to a buffered call:

clientConfig.getProperties().put(ClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, null);

I quote from the documentation of the property PROPERTY_CHUNKED_ENCODING_SIZE

If the property is absent then chunked encoding will not be used. A value < = 0 declares that chunked encoding will be used with the default chunk size. A value > 0 declares that chunked encoding will be used with the value as the declared chunk size.

Even if I set this property I still receive the HTTP response status of 411 Length Required.

Later edit: My call does not leave the the local machine. When it does so I am expected to receive a 401 Unauthorized, since I will need to add a header with an auth key. Yet this is not the focus of this question, however if anyone considers is better to add details on how to obtain this, please leave a comment and I will describe more.


Solution

  • To start with

    You do not have to set flag ClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, please check here or in your quote above.

    Jersey Client by default will set the Content-Type as application/json (by nature), thus you should have passed the blank json object to get the Content-length correct passed in with http request.

    Thus to get it work, you should post a blank json object without setting the Content-Length Header.

    Here is the working code, where you will get HTTP 401

    import com.sun.jersey.api.client.Client;
    import com.sun.jersey.api.client.ClientResponse;
    import com.sun.jersey.api.client.WebResource;
    import com.sun.jersey.api.client.config.ClientConfig;
    import com.sun.jersey.api.client.config.DefaultClientConfig;
    import com.sun.jersey.api.client.filter.LoggingFilter;
    import com.sun.jersey.api.json.JSONConfiguration;
    
    /**
     * Main
     */
    public class Main {
    
        public static void main(String[] args) {
        ClientConfig clientConfig = new DefaultClientConfig();
        clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
        //clientConfig.getProperties().put(ClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, null);
        Client client = Client.create(clientConfig);
        client.addFilter(new LoggingFilter(System.out));
    
        String postURL = "https://api.napster.com/v2.2/me/library/tracks?id=tra.169783383,tra.30621111";
        WebResource webResourcePost = client.resource(postURL);
        //webResourcePost.header("Content-Length", 0);
        ClientResponse response = webResourcePost.type("application/json").post(ClientResponse.class, "{}");
        System.out.println(response.getStatus());
      }
    }