[
https://issues.apache.org/jira/browse/JCLOUDS-1547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17114273#comment-17114273
]
Alexander Chernavin commented on JCLOUDS-1547:
----------------------------------------------
Hi [~gaul],
I appreciate your quick response!
I looked into [testPutIncorrectContentMD5
|[https://github.com/jclouds/jclouds/blob/7af4d8e8f19c479b0a8f35e06dd68418a8367b3e/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java#L298]].
It uploads a blob with a byte array payload:
{code:java}
byte[] payload = createTestInput(1024).read(); {code}
Here is the catch, if you replace stream payload in my example with a byte
array payload then will also start failing with the error you mentioned:
{code:java}
.payload("hi".getBytes()) {code}
Also, if you modify the test case to use InputStream, it should also start
failing.
It happens, because
[putBlob|[https://github.com/jclouds/jclouds/blob/master/providers/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/blobstore/GoogleCloudStorageBlobStore.java#L211]]
method of GoogleCloudStorageBlobStore has a fork that treats payloads
differently:
{code:java}
if (length != 0 && (options.isMultipart() ||
!blob.getPayload().isRepeatable())) {
// JCLOUDS-912 prevents using single-part uploads with InputStream payloads.
// Work around this with multi-part upload which buffers parts in-memory.
return putMultipartBlob(container, blob, options);
} else {
// skipped some lines for readability
return api.getObjectApi().multipartUpload(container, template,
blob.getPayload()).etag();
}{code}
Input stream payload falls into "if" statement, byte array payload falls into
"else" statement.
putMultipartBlob method eventually calls
org.jclouds.googlecloudstorage.features.ObjectApi.simpleUpload, here is the
definition of this method:
{code:java}
GoogleCloudStorageObject simpleUpload(@PathParam("bucket") String bucketName,
@HeaderParam("Content-Type") String contentType,
@HeaderParam("Content-Length") Long contentLength,
@PayloadParam("payload") Payload payload,
InsertObjectOptions options);{code}
Content-MD5 header is not passed to the server side.
Regards,
Alexander
> Google InputStream blob upload ignores MD5
> ------------------------------------------
>
> Key: JCLOUDS-1547
> URL: https://issues.apache.org/jira/browse/JCLOUDS-1547
> Project: jclouds
> Issue Type: Bug
> Components: jclouds-blobstore
> Affects Versions: 2.2.0, 2.2.1
> Reporter: Alexander Chernavin
> Priority: Major
> Labels: google-cloud-storage, md5
>
> According to [GCS blob upload
> documentation|[https://cloud.google.com/storage/docs/xml-api/put-object-upload]],
> when Content-MD5 header is provided, Google uses it to verify data integrity
> of an uploaded blob. This feature is crucial for us. We have a file upload
> functionality that takes an input stream and uploads it to a cloud via
> JClouds. We want to be sure that file integrity is enforced.
>
> JClouds blob builder allows to specify content MD5, but this value is ignored
> with InputStream payload, it's simply is not propagated into Content-MD5
> header.
> Here is the code snippet to reproduce the issue:
> {code:java}
> BlobStoreContext context = ContextBuilder.newBuilder("google-cloud-storage")
> .credentials(clientEmail, privateKey)
> .buildView(BlobStoreContext.class);
> // generate MD5 hash for some bogus content
> MessageDigest md5 = MessageDigest.getInstance("MD5");
> md5.update("bogus".getBytes());
> InputStream inputStream = new ByteArrayInputStream("hi".getBytes());
> BlobStore blobStore = context.getBlobStore();
> blobStore.putBlob(myContainer,
> blobStore.blobBuilder("test.txt")
> .payload(inputStream)
> .contentLength(2)
> .contentType("text/plain")
> .contentMD5(HashCode.fromBytes(md5.digest()))
> .build()); {code}
> putBlob should have failed, because payload is "hi", but MD5 is calculated
> for "bogus" string.
>
--
This message was sent by Atlassian Jira
(v8.3.4#803005)