Re: ApacheHC driver and stream closing

2015-03-11 Thread Veit Guna
Hi Ignasi.

In fact, in the patch I provided for the other issue (S3 upload
performance), I already
removed the hashing lines and simply took the provided MD5 hash from the
ContentMetadata.
And that worked. But I wasn't sure about the intention of the additional
hashing,
so I thought I better ask for more insight here ;).

So no changes were needed for [1] and [2]. If it makes sense, I can
create a PR so someone
can review the changes.

Thanks,
Veit


Am 11.03.2015 um 22:23 schrieb Ignasi Barrera:
 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 
 

Re: ApacheHC driver and stream closing

2015-03-11 Thread Ignasi Barrera
A PR would be much appreciated :) It is also easier to discuss
impl/design things there.
Thanks!

On 11 March 2015 at 22:47, Veit Guna veit.g...@gmx.de wrote:
 Hi Ignasi.

 In fact, in the patch I provided for the other issue (S3 upload
 performance), I already
 removed the hashing lines and simply took the provided MD5 hash from the
 ContentMetadata.
 And that worked. But I wasn't sure about the intention of the additional
 hashing,
 so I thought I better ask for more insight here ;).

 So no changes were needed for [1] and [2]. If it makes sense, I can
 create a PR so someone
 can review the changes.

 Thanks,
 Veit


 Am 11.03.2015 um 22:23 schrieb Ignasi Barrera:
 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