Search code examples
javaapache-commons-httpclient

how to properly make a POST request using Java Apache HttpClient?


I am trying to use a web API in a Java program using Apache HttpClient5.

Using a simple request with curl:

curl -X POST -H "x-api-user: d904bd62-da08-416b-a816-ba797c9ee265" -H "x-api-key: xxxxxxxxxxx" https://habitica.com/api/v3/user/class/cast/valorousPresence

I get the expected response and effect.

Using my Java code:

URI uri = new URIBuilder()
              .setScheme("https")
              .setHost("habitica.com")
              .setPath("/api/v3/user/class/cast/valorousPresence")
              .build();
Logger logger = LoggerFactory.getLogger(MyClass.class);
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost(uri);
httpPost.addHeader(new BasicHeader("x-api-user",getApiUser()));
httpPost.addHeader(new BasicHeader("x-api-key", getApiKey()));
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
logger.info(httpResponse.toString());
return httpResponse.getCode();

The output I get when running the Java call is

411 Length Required HTTP/1.0

I'm sure I'm not constructing the POST call correctly, how should it be done? I've tried specifying Content-Type and that has no effect. Trying to set Content-Length in the code causes compilation errors (as I understand it, this is handled behind the scenes by HttpClient5). All my GET requests using HttpClient5 work fine.


Solution

  • A POST always has a payload (content). A POST without content is unusual, so are you sure you didn't forget something?

    You need to call setEntity() to set the payload, even if it is empty, because it is the entity that sets the Content-Length header.

    E.g. you could call httpPost.setEntity(new StringEntity("")), which sets Content-Type: text/plain and Content-Length: 0.