I'm trying to upload an InputStream via HttpPut using the Apache HttpClient 4.5.6:
InputStream inputStream = ..
CredentialsProvider provider = ..
HttpClient client = HttpClientBuilder.create()
.setDefaultCredentialsProvider(provider)
.build();
HttpPut method = new HttpPut("MY_REMOTE_URL");
InputStreamEntity entity = new InputStreamEntity(inputStream);
method.setEntity(entity);
client.execute(method);
Uploading requires authentication and in my case I don't know if the Server used digest or basic authentication, therefore the client automatically sends multiple requests to determine the authentication scheme. But InputStreamEntity is non repeatable , leading to the following errors:
org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
Idea #1: Buffering the InputStream
I can wrap the entity with BufferedHttpEntity which makes it repeatable:
..
BufferedHttpEntity entity = new BufferedHttpEntity(new InputStreamEntity(inputStream));
method.setEntity(entity);
..
.. but then the stream first gets buffered and then sent in total, not chunked / streamed. This does not work for bigger files.
Idea #2: Preemptive Authentication
I can add a hardcoded header with the correct authentication to prevent the request from being repeated. But as I said, I don't know the authentication scheme.
Idea #3: Dummy FileEntity upload to get context (my current solution)
I upload an empty file first, harvest the context and add it to my InputStream PUT request:
HttpPut testMethod = new HttpPut("MY_REMOTE_DUMMY_URL");
FileEntity testEntity = new FileEntity(testFile);
testMethod.setEntity(testEntity);
HttpContext context = new BasicHttpContext();
client.execute(testMethod, context);
// .. delete the testEntity from server ..
HttpPut method = new HttpPut("MY_REMOTE_URL");
InputStreamEntity entity = new InputStreamEntity(inputStream);
method.setEntity(entity);
client.execute(method, context);
It works, but it seems like a hack. Should I do this? Are there alternatives?