mirror of https://github.com/apache/jclouds.git
Issue 352: added transient blob signing
This commit is contained in:
parent
d9820c536a
commit
0e5823afad
|
@ -265,7 +265,7 @@ in another application. ex. curl"
|
||||||
(doto (.newBlob blobstore path)
|
(doto (.newBlob blobstore path)
|
||||||
(.setPayload (doto
|
(.setPayload (doto
|
||||||
;; until we pass content md5
|
;; until we pass content md5
|
||||||
(PhantomPayload. size nil)
|
(PhantomPayload. (long size) nil)
|
||||||
(.setContentType content-type)))))))
|
(.setContentType content-type)))))))
|
||||||
|
|
||||||
(defn sign-blob-request
|
(defn sign-blob-request
|
||||||
|
@ -284,7 +284,7 @@ in another application. ex. curl"
|
||||||
(.. blobstore getContext getSigner) container-name
|
(.. blobstore getContext getSigner) container-name
|
||||||
(doto (.newBlob blobstore path)
|
(doto (.newBlob blobstore path)
|
||||||
(.setPayload
|
(.setPayload
|
||||||
(doto (PhantomPayload. content-length content-md5)
|
(doto (PhantomPayload. (long content-length) content-md5)
|
||||||
(.setContentType content-type))))))))
|
(.setContentType content-type))))))))
|
||||||
|
|
||||||
(defn get-blob-stream
|
(defn get-blob-stream
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.blobstore;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.filters.BasicAuthentication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class TransientBlobRequestSigner implements BlobRequestSigner {
|
||||||
|
|
||||||
|
private final BasicAuthentication basicAuth;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public TransientBlobRequestSigner(BasicAuthentication basicAuth) {
|
||||||
|
this.basicAuth = checkNotNull(basicAuth, "basicAuth");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signGetBlob(String container, String name) {
|
||||||
|
HttpRequest request = new HttpRequest("GET", URI.create(String.format("http://localhost/%s/%s", container, name)));
|
||||||
|
basicAuth.filter(request);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signPutBlob(String container, Blob blob) {
|
||||||
|
HttpRequest request = new HttpRequest("PUT", URI.create(String.format("http://localhost/%s/%s", container, blob
|
||||||
|
.getMetadata().getName())));
|
||||||
|
if (blob.getPayload().getContentLength() != null)
|
||||||
|
request.getHeaders().put(HttpHeaders.CONTENT_LENGTH, blob.getPayload().getContentLength().toString());
|
||||||
|
if (blob.getPayload().getContentType() != null)
|
||||||
|
request.getHeaders().put(HttpHeaders.CONTENT_TYPE, blob.getPayload().getContentType());
|
||||||
|
if (blob.getPayload().getContentMD5() != null)
|
||||||
|
request.getHeaders().put("Content-MD5", CryptoStreams.base64(blob.getPayload().getContentMD5()));
|
||||||
|
request.setPayload(blob.getPayload());
|
||||||
|
basicAuth.filter(request);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest signRemoveBlob(String container, String name) {
|
||||||
|
HttpRequest request = new HttpRequest("DELETE", URI.create(String.format("http://localhost/%s/%s", container,
|
||||||
|
name)));
|
||||||
|
basicAuth.filter(request);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,9 +26,11 @@ import java.util.concurrent.ConcurrentMap;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.blobstore.AsyncBlobStore;
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
|
import org.jclouds.blobstore.BlobRequestSigner;
|
||||||
import org.jclouds.blobstore.BlobStore;
|
import org.jclouds.blobstore.BlobStore;
|
||||||
import org.jclouds.blobstore.BlobStoreContext;
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
import org.jclouds.blobstore.TransientAsyncBlobStore;
|
import org.jclouds.blobstore.TransientAsyncBlobStore;
|
||||||
|
import org.jclouds.blobstore.TransientBlobRequestSigner;
|
||||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
||||||
|
@ -68,6 +70,7 @@ public class TransientBlobStoreContextModule extends AbstractModule {
|
||||||
install(new BlobStoreObjectModule());
|
install(new BlobStoreObjectModule());
|
||||||
install(new BlobStoreMapModule());
|
install(new BlobStoreMapModule());
|
||||||
bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
|
bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
|
||||||
|
bind(BlobRequestSigner.class).to(TransientBlobRequestSigner.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
(download-blob container-name name data-file)))
|
(download-blob container-name name data-file)))
|
||||||
(finally (.delete data-file))))))
|
(finally (.delete data-file))))))
|
||||||
|
|
||||||
;; this will fail until transient provider handles signing
|
;; this will fail until somebody fixes it!
|
||||||
#_
|
#_
|
||||||
(deftest sing-put-blob-request-test
|
(deftest sing-put-blob-request-test
|
||||||
(let [request (sign-put-blob-request "container" "path" "text/plain" 10)]
|
(let [request (sign-put-blob-request "container" "path" "text/plain" 10)]
|
||||||
|
@ -117,7 +117,7 @@
|
||||||
(is (= "10" (get "Content-Length" (.getHeaders request))))
|
(is (= "10" (get "Content-Length" (.getHeaders request))))
|
||||||
(is (= "text/plain" (get "Content-Type" (.getHeaders request))))))
|
(is (= "text/plain" (get "Content-Type" (.getHeaders request))))))
|
||||||
|
|
||||||
;; this will fail until transient provider handles signing
|
;; this will fail until somebody fixes it!
|
||||||
#_
|
#_
|
||||||
(deftest sing-blob-request-test
|
(deftest sing-blob-request-test
|
||||||
(let [request (sign-blob-request "container" "path" {:method :delete})]
|
(let [request (sign-blob-request "container" "path" {:method :delete})]
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jclouds.blobstore;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
|
import org.jclouds.blobstore.domain.Blob.Factory;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.io.payloads.PhantomPayload;
|
||||||
|
import org.jclouds.rest.RestClientTest;
|
||||||
|
import org.jclouds.rest.RestContextFactory;
|
||||||
|
import org.jclouds.rest.RestContextFactory.ContextSpec;
|
||||||
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
@Test(groups = "unit", testName = "jclouds.TransientBlobRequestSignerTest")
|
||||||
|
public class TransientBlobRequestSignerTest extends RestClientTest<TransientAsyncBlobStore> {
|
||||||
|
|
||||||
|
private BlobRequestSigner signer;
|
||||||
|
private Factory blobFactory;
|
||||||
|
|
||||||
|
public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
HttpRequest request = signer.signGetBlob("container", "name");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "GET http://localhost/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "Authorization: Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==\n");
|
||||||
|
assertPayloadEquals(request, null, null, false);
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSignRemoveBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
HttpRequest request = signer.signRemoveBlob("container", "name");
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "DELETE http://localhost/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "Authorization: Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==\n");
|
||||||
|
assertPayloadEquals(request, null, null, false);
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSignPutBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException,
|
||||||
|
NoSuchMethodException, IOException {
|
||||||
|
Blob blob = blobFactory.create(null);
|
||||||
|
blob.getMetadata().setName("name");
|
||||||
|
blob.setPayload(new PhantomPayload(2l, new byte[] { 0, 2, 4, 8 }));
|
||||||
|
blob.getPayload().setContentType("text/plain");
|
||||||
|
|
||||||
|
HttpRequest request = signer.signPutBlob("container", blob);
|
||||||
|
|
||||||
|
assertRequestLineEquals(request, "PUT http://localhost/container/name HTTP/1.1");
|
||||||
|
assertNonPayloadHeadersEqual(request, "Authorization: Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==\nContent-Length: 2\nContent-MD5: AAIECA==\nContent-Type: text/plain\n");
|
||||||
|
assertContentHeadersEqual(request, "text/plain", (long) 2l, new byte[] { 0, 2, 4, 8 });
|
||||||
|
|
||||||
|
assertEquals(request.getFilters().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
protected void setupFactory() throws IOException {
|
||||||
|
super.setupFactory();
|
||||||
|
this.blobFactory = injector.getInstance(Blob.Factory.class);
|
||||||
|
this.signer = injector.getInstance(BlobRequestSigner.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void checkFilters(HttpRequest request) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContextSpec<?, ?> createContextSpec() {
|
||||||
|
return new RestContextFactory().createContextSpec("transient", "identity", "credential", new Properties());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TypeLiteral<RestAnnotationProcessor<TransientAsyncBlobStore>> createTypeLiteral() {
|
||||||
|
return new TypeLiteral<RestAnnotationProcessor<TransientAsyncBlobStore>>() {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue