2

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?

1 Answer 1

1

Activate expect-continue handshake instead.

HttpClientContext context = HttpClientContext.create();
RequestConfig config = RequestConfig.custom().setExpectContinueEnabled(true).build();
context.setRequestConfig(config);
Sign up to request clarification or add additional context in comments.

1 Comment

It did answer my question! Will try to edit the answer providing the relevant code snippet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.