Looking at the code I would say it is an issue, but at some point that
should be intentional. The Apache HC driver explicitly excludes the
Content-MD5 header when converting the jclouds request to its request
object (see [1]).

By looking at the other drivers (the default Java one and OkHttp),
both use that method to populate the Content-MD5 header (here you can
see what it does [2]) which does pretty much the same than what the
ApacheHC does *after*, by computing the hash again.

Could you try removing the lines that rehash the stream and populate
the Content-MD5 header from the Apache HC driver, and add the
Content-MD5 header to the list of "allowed headers" in the first link?
I'm pretty sure that would work. And if that works, mind opening a
pull request with the fix?


HTH!

I.


[1] 
https://github.com/jclouds/jclouds/blob/master/drivers/apachehc/src/main/java/org/jclouds/http/apachehc/ApacheHCUtils.java#L155-L162
[2] 
https://github.com/jclouds/jclouds/blob/master/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java#L98-L99

On 11 March 2015 at 17:22, Veit Guna <veit.g...@gmx.de> wrote:
>
> Hi.
>
> I have a problem with the ApacheHC driver using jclouds 1.8.1. I'm using it 
> to upload files
> to an S3 bucket. For the payload I'm using an InputStream that is not 
> resettable nor "rereadable".
> When I try to send the file via:
>
>         PayloadBlobBuilder blobBuilder = blobStore.blobBuilder("test")
>                 .payload(inputStream)
>                 .contentDisposition("attachment; filename=test")
>                 .contentType("application/octet-stream")
>                 .contentMD5(hash)
>                 .contentLength(file.length()
>                         );
>
> It dies with the exception below.
>
> A quick look at ApacheHCHttpCommandExecutorService shows:
>
>
>    @Override
>    protected HttpUriRequest convert(HttpRequest request) throws IOException {
>       HttpUriRequest returnVal = 
> apacheHCUtils.convertToApacheRequest(request);
>       if (request.getPayload() != null && 
> request.getPayload().getContentMetadata().getContentMD5() != null) {
>          String md5 = 
> base64().encode(ByteStreams2.hashAndClose(request.getPayload().openStream(), 
> md5()).asBytes());
>          returnVal.addHeader("Content-MD5", md5);
>       }
>       return returnVal;
>    }
>
> That means, that if an MD5 is specified, it reads the whole(!) stream to 
> create his own MD5. Why is that? The "client" already
> supplied an MD5. So why hashing it again?
>
> Does that mean, using Md5 together with ApacheHC and non "rereadable" streams 
> isn't working at all? Is that by design?
> The normal JavaUrlHttp driver works like a charm though.
>
> Maybe someone could shed some light on this :)?
>
> Thanks!
> Veit
>
>
>
> Exception in thread "main" org.jclouds.http.HttpResponseException: null 
> connecting to PUT https://mybucket.s3-eu-west-1.amazonaws.com/test HTTP/1.1
>     at 
> org.jclouds.http.internal.BaseHttpCommandExecutorService.invoke(BaseHttpCommandExecutorService.java:110)
>     at 
> org.jclouds.rest.internal.InvokeHttpMethod.invoke(InvokeHttpMethod.java:90)
>     at 
> org.jclouds.rest.internal.InvokeHttpMethod.apply(InvokeHttpMethod.java:73)
>     at 
> org.jclouds.rest.internal.InvokeHttpMethod.apply(InvokeHttpMethod.java:44)
>     at 
> org.jclouds.rest.internal.DelegatesToInvocationFunction.handle(DelegatesToInvocationFunction.java:156)
>     at 
> org.jclouds.rest.internal.DelegatesToInvocationFunction.invoke(DelegatesToInvocationFunction.java:123)
>     at com.sun.proxy.$Proxy42.putObject(Unknown Source)
>     at org.jclouds.s3.blobstore.S3BlobStore.putBlob(S3BlobStore.java:235)
>     at 
> org.jclouds.aws.s3.blobstore.AWSS3BlobStore.putBlob(AWSS3BlobStore.java:95)
>     at org.jclouds.s3.blobstore.S3BlobStore.putBlob(S3BlobStore.java:213)
>     at org.jclouds.test.S3UploadTest.performUpload(S3UploadTest.java:71)
>     at org.jclouds.test.S3UploadTest.main(S3UploadTest.java:36)
> Caused by: org.apache.http.client.ClientProtocolException
>     at 
> org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:867)
>     at 
> org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:115)
>     at 
> org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
>     at 
> org.jclouds.http.apachehc.ApacheHCHttpCommandExecutorService.executeRequest(ApacheHCHttpCommandExecutorService.java:109)
>     at 
> org.jclouds.http.apachehc.ApacheHCHttpCommandExecutorService.invoke(ApacheHCHttpCommandExecutorService.java:78)
>     at 
> org.jclouds.http.apachehc.ApacheHCHttpCommandExecutorService.invoke(ApacheHCHttpCommandExecutorService.java:52)
>     at 
> org.jclouds.http.internal.BaseHttpCommandExecutorService.invoke(BaseHttpCommandExecutorService.java:89)
>     ... 11 more
> Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry 
> request with a non-repeatable request entity.  The cause lists the reason the 
> original request failed.
>     at 
> org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:659)
>     at 
> org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:487)
>     at 
> org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
>     ... 17 more
> Caused by: java.io.IOException: Stream Closed
>     at java.io.FileInputStream.readBytes(Native Method)
>     at java.io.FileInputStream.read(FileInputStream.java:272)
>     at 
> org.apache.http.entity.InputStreamEntity.writeTo(InputStreamEntity.java:138)
>     at 
> org.apache.http.entity.HttpEntityWrapper.writeTo(HttpEntityWrapper.java:89)
>     at 
> org.apache.http.impl.client.EntityEnclosingRequestWrapper$EntityWrapper.writeTo(EntityEnclosingRequestWrapper.java:108)
>     at 
> org.apache.http.impl.entity.EntitySerializer.serialize(EntitySerializer.java:117)
>     at 
> org.apache.http.impl.AbstractHttpClientConnection.sendRequestEntity(AbstractHttpClientConnection.java:265)
>     at 
> org.apache.http.impl.conn.AbstractClientConnAdapter.sendRequestEntity(AbstractClientConnAdapter.java:231)
>     at 
> org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:236)
>     at 
> org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:121)
>     at 
> org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:685)
>     ... 19 more
>
>
>
>

Reply via email to