1

I am trying to hit a REST API with Apache http client 4.5.5. I can successfully POST to the API using cURL like so:

curl -X POST --user username:password  --header "Content-Type: application/json" --data "@/path/to/file.json" https://some.restfulapi.com/endpoint

However when I try to POST to the API using Apache http client, it always fails with HTTP error code :401 Unauthorized when using the same credentials:

HttpClient httpclient = new DefaultHttpClient();

CredentialsProvider credentialsPovider = new BasicCredentialsProvider();
credentialsPovider.setCredentials(new AuthScope(request.getHost(), 443),  new UsernamePasswordCredentials(user, password));
                

HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credentialsPovider);


HttpPost httppost = new HttpPost(request.getHost()); 


// append headers
for(Header header : request.getHeaders()){
    httppost.addHeader(header.getKey(), header.getValue());
}
                
if(body_entity.length()>0){
    // append the  data to the post
    StringEntity stringentity = new StringEntity(body_entity, HTTP.UTF_8);
    stringentity.setContentType(content_type);
    httppost.setEntity(stringentity);                                           
}


HttpResponse response = httpclient.execute(httppost, context);

I have also tried adding the authentication directly as a header:

String encoding = Base64.getEncoder().encodeToString((user + ":" + password);
httppost.addHeader("Authentication", encoding);

returns a 401 Unauthorized too.

Furthermore, direct header variants:

- httppost.addHeader("user", "Basic " + encoding);
- httppost.addHeader("Authentication", "Basic " + encoding);
- httppost.addHeader(BasicScheme.authenticate(new UsernamePasswordCredentials(user, password), "UTF-8", false));

all result in 400 Bad request response.

Using an HttpClientBuilder with CredentialsProvider

HttpClientBuilder clientbuilder = HttpClients.custom();
clientbuilder = clientbuilder.setDefaultCredentialsProvider(credentialsPovider);
httpclient = clientbuilder.build();

also results in 400 Bad request response.

How do I create an Apache http client POST request that does what the cURL utility is doing? What is cURL doing differently than Apache httpclient? Might the encoding (UTF-8) be the issue?

Other posts and documentation:

Roy Hinkley
  • 10,111
  • 21
  • 80
  • 120
  • The authentication header is not called "user" but "Authentication" – f1sh Jun 24 '20 at 13:52
  • @f1sh. I have tried that header label too. Please see edited post. – Roy Hinkley Jun 24 '20 at 13:57
  • It's not even `Authentication` but `Authorization`. It's called the Authorization header. Also, you are missing a space when you append the encoded credentials to `Basic` in your second example. It should be `"Basic " + encoding` – Krisz Jun 24 '20 at 13:59
  • To help you find the answer, you should check how to log the actual HTTP request and compare it with what cURL produces. You will certainly see what's the difference there. – Krisz Jun 24 '20 at 14:03
  • @Krisz. Even using `Authorization ` as header instead of `Authentication` - 400 response. – Roy Hinkley Jun 24 '20 at 14:03
  • You could try to explicitly set the content-type header as you do with cURL, it might be required by the web service you try to call. But then again, I am not familiar with this Apache library, it might be set by default. – Krisz Jun 24 '20 at 14:07
  • @Krisz Setting content type explicitly makes no difference. If I set the user/pass header directly, always 400. If I using `BasicCredentialsProvider` always 401. – Roy Hinkley Jun 24 '20 at 14:13

1 Answers1

0

Solution

httppost.addHeader("Authorization", "Basic "+Base64.getEncoder().encodeToString("user:password".getBytes()));

plus the missing (and required - undocumented) header:

httppost.addHeader("Content-Length", json.toString().length);
Roy Hinkley
  • 10,111
  • 21
  • 80
  • 120