1
votes

I am trying to get SAS access URL for a blob in azure blob-storage from a custom api in my azure-mobile-services. For this I am using the azure-storage node module, using this how-to guide. I have the required AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY env variables set in my mobile-serivces config. Below is the snippet of the code I have for this. From logs I can see that the 'blobService.generateSharedAccessSignature' successfully returns the sasQueryUrl object, The logger code-line

 logger.info('sasQueryUrl=', sasQueryUrl);

returns -

sasQueryUrl="st=2015-02-22T03%3A28%3A25Z&se=2015-02-22T03%3A48%3A25Z&sp=w&sv=2014-02-14&sr=b&sig=MUG7LT4Fe%2BGLu5lAa%2FgIXQM33AKtBDNrnEOV9H9FzBE%3D" st=2015-02-22T03%3A28%3B45Q&se=2015-02-22T03%3A48%3A25Z&sp=w&sv=2014-02-14&sr=b&sig=MEU7DE4Fe%2BGLu5lAa%2FgIAQTM33AKtBDNrnEOV9H9FzBE%3D [object Object])

but the below logger code-line

logger.info('sasQueryUrl.queryString = ' + qs.stringify(sasQueryUrl.queryString));

logs -

sasQueryUrl.queryString = [object Object],

so qs is not stringifying sasQueryUrl.queryString. Because of this I am not able to build the SAS URL for the blob.

Below is the my function code -

function getImageBlobSASURL(item, callback){
    var iM = 'api.images.getImageBlobSASURL -";
    try {
        var azureStrg = require('azure-storage');
        var qs = require('querystring');
        var retryOperationFilter = new azureStrg.ExponentialRetryPolicyFilter();
        var blobService = azureStrg.createBlobService().withFilter(retryOperationFilter);

        var containerName = item.image.container.toLowerCase();
        blobService.createContainerIfNotExists(containerName, function(err, containerCreatedResultFlag, response) {
            if (err) {
                throw new Error(iM + "couldn't create container-" + containerName + ".Error=" + err);
            }

            //Create SAS for the BLOB with write access to the container for the next 10 mins.
            var startDate = new Date();
            var expiryDate = new Date(startDate);
            expiryDate.setMinutes(startDate.getMinutes() + 10);
            startDate.setMinutes(startDate.getMinutes() - 10);

            var sharedAccessPolicy = {
                AccessPolicy: {
                    Permissions: azureStrg.BlobUtilities.SharedAccessPermissions.WRITE,
                    Start: startDate,
                    Expiry: expiryDate
                }
            };

            var sasQueryUrl = blobService.generateSharedAccessSignature(containerName, '' , sharedAccessPolicy);

            logger.info(iM + 'sasQueryUrl=', sasQueryUrl);

            logger.info(iM + 'sasQueryUrl.queryString =' + qs.stringify(sasQueryUrl.queryString));
            item.image.sas.qstr = qs.stringify(sasQueryUrl.queryString); //Set the query string.

            //Set the full path on the new new item, which is used for data binding on the client.
            item.image.url = sasQueryUrl.baseUrl + sasQueryUrl.path + '/' + item.image.resourceName;

            logger.info(iM + 'Received sas URI for the resource=', item.image);
            callback.success(containerCreatedResultFlag, item);
        }
    }
    catch(err){
        logger.error( iM + 'error - ' + err);
        callback.error(err);
        return false;
    }

}

anyone has any idea whats going wrong here? any pointers are greatly appreciated

1

1 Answers

2
votes

blobService.generateSharedAccessSignature itself serializes the query string and returns it as a string rather than an object. So the library already calls qs.stringify on the query string object before returning it. This makes it simple for users to use it when they want to perform an operation using the SAS token as the blob service create APIs directly take the string form of the query string as shown below -

var sharedAccessSignatureToken = blobService.generateSharedAccessSignature(container, blob, sharedAccessPolicy);

var sharedBlobService = azure.createBlobServiceWithSas(blobService.host, sharedAccessSignatureToken);

// Download the blob properties by using the shared access signature URL. 
sharedBlobService.getBlobProperties(container, blob, function (error) {
if (error) {
  console.log(error);
} 
}

If you want to work with a SAS token as an object, please use qs.parse to create the query string object.

If you would rather work with the Uri generated using the SAS token, please build the Uri as follows -

uri = blobService.host.primaryHost + '/' + container + '?' + sharedAccessSignatureToken