Search code examples
javaopenstackopenstack-swiftjclouds

Generating temporary URI for object using BlobStore


I am trying to implement a generation of a temporary GET URIs for objects stored in the OpenStack Swift container using jClouds BlobStore features.

However I am getting these errors:

java.lang.IllegalStateException: Suppliers.memoizeWithExpiration(get().getTemporaryUrlKey() using {annotationParser={caller=SwiftApi.accountApiInRegion[RegionOne]}}, 60000000000, NANOS) returned a null temporaryUrlKey!
    at com.google.common.base.Preconditions.checkState(Preconditions.java:177)
    at org.jclouds.openstack.swift.v1.TemporaryUrlSigner.hmacSHA1(TemporaryUrlSigner.java:63)
    at org.jclouds.openstack.swift.v1.TemporaryUrlSigner.sign(TemporaryUrlSigner.java:57)
    at org.jclouds.openstack.swift.v1.blobstore.RegionScopedTemporaryUrlBlobSigner.sign(RegionScopedTemporaryUrlBlobSigner.java:100)
    at org.jclouds.openstack.swift.v1.blobstore.RegionScopedTemporaryUrlBlobSigner.signGetBlob(RegionScopedTemporaryUrlBlobSigner.java:73)

Here comes a code sample:

public class BlobStoreObjectSignerService implements ObjectSignerService {

    @Autowired
    private BlobRequestSigner blobRequestSigner;

    @Value("${blobStore.private.container}")
    String privateContainerName;

    /**
    * Generates signed request With GET Method to access allocated object.
    *   
    * @param objectName         name of the stored file
    * @param principalName      name of the principal (user) which is putted the file
    * @param temporary          defines if file should be available for a limited time
    * @param timeToLive         time in seconds file will be available for fetching
    */
    public HttpRequest generateGetRequestForObject( String objectName, 
                                                    String principalName, 
                                                    boolean temporary, 
                                                    long timeToLive ) {
        if (temporary) {
            return this.generateTemporaryGetRequestForObject(objectName,  principalName, timeToLive);
        } else {
            return this.generatePermanentGetRequestForObject(objectName,  principalName);
        }
    }

    public HttpRequest generatePermanentGetRequestForObject( String objectName, 
                                                             String principalName ) {
        return this.generatePermanentGetRequestForObject( privateContainerName,
                                                          String.format( "/%s/%s", principalName, objectName ) );
    }

    public HttpRequest generateTemporaryGetRequestForObject( String objectName, 
                                                             String principalName,
                                                             long timeToLive ) {
        return this.generateTemporaryGetRequestForObject( privateContainerName,
                                                          String.format( "/%s/%s", principalName, objectName ),
                                                          timeToLive );
    }

    public HttpRequest generatePermanentGetRequestForObject(String containerName, String objectName) {
        return this.blobRequestSigner.signGetBlob(containerName, objectName);
    }

    public HttpRequest generateTemporaryGetRequestForObject(String containerName, String objectName, long timeToLive) {
        return this.blobRequestSigner.signGetBlob(containerName, objectName, timeToLive);
    }

}

As for public containers i can still get object links by fetching header/metadata, and it is kind of sideway, but i am still in need of signed URIs to publish objects stored in private containers.

Putting files into container using BlobStore is working just fine. All pushed are normally dislayed by OpenStack Dashboard.

I am using Java 7 and DevStack configurated for Swift only in dev environment. jClouds version is 1.7.2.


Solution

  • Based on the exception, it looks like you don't have a temporary URL Key set on the Account. You can update the key to a new value via the AccountApi like this:

    SwiftApi swiftApi = ContextBuilder.newBuilder(PROVIDER)
               .credentials("{username}", "{apiKey}")
               .buildApi(SwiftApi.class);
    
    // Access the accountApi
    AccountApi accountApi = swiftApi.getAccountApiForRegion("{regionId");
    accountApi.updateTemporaryUrlKey("{newKey}");
    
    // Access the key
    String tempUrlKey;
    if (accountApi.getTemporaryUrlKey().isPresent()) {
       tempUrlKey = accountApi.get().getTemporaryUrlKey().get();
    }
    

    Hope that helps!