From b3ddff24044fffabf0794e37a739724ca500aa80 Mon Sep 17 00:00:00 2001 From: Haibo Song Date: Tue, 19 Jul 2016 10:37:55 +0800 Subject: [PATCH] Added support for EndpointSuffix for all service constructors. --- ChangeLog.md | 1 + lib/common/services/storageserviceclient.js | 4 +- lib/common/services/storageservicesettings.js | 38 +++++++++++++------ lib/common/util/constants.js | 1 + lib/services/blob/blobservice.js | 5 ++- lib/services/file/fileservice.js | 5 ++- lib/services/queue/queueservice.js | 5 ++- lib/services/table/tableservice.js | 5 ++- test/common/storageservicesettingstests.js | 35 +++++++++++++++++ typings/azure-storage/azure-storage.d.ts | 12 ++++-- 10 files changed, 86 insertions(+), 25 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 3f797c8..2ae9ecb 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,6 +5,7 @@ be taken. This is a GA release and the changes described below indicate the chan ALL * Fixed the issue that metadata name will be converted to lower-case after retrieving back from the server. **Note** that this fix is only applicable for Node 0.12 or higher version. +* Added support for EndpointSuffix for all service constructors. BLOB * Fixed the issue that the service error message will be written to the destination stream if getting error when downloading the blob to a stream/file. diff --git a/lib/common/services/storageserviceclient.js b/lib/common/services/storageserviceclient.js index c2c9d5f..e45d162 100644 --- a/lib/common/services/storageserviceclient.js +++ b/lib/common/services/storageserviceclient.js @@ -840,14 +840,14 @@ StorageServiceClient._parseResponse = function (response, xml2jsSettings, option * * @return {StorageServiceSettings} */ -StorageServiceClient.getStorageSettings = function (storageAccountOrConnectionString, storageAccessKey, host, sasToken) { +StorageServiceClient.getStorageSettings = function (storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix) { var storageServiceSettings; if (storageAccountOrConnectionString && !storageAccessKey && !sasToken) { // If storageAccountOrConnectionString was passed and no accessKey was passed, assume connection string storageServiceSettings = StorageServiceSettings.createFromConnectionString(storageAccountOrConnectionString); } else if ((storageAccountOrConnectionString && storageAccessKey) || sasToken || host) { // Account and key or credentials or anonymous - storageServiceSettings = StorageServiceSettings.createExplicitly(storageAccountOrConnectionString, storageAccessKey, host, sasToken); + storageServiceSettings = StorageServiceSettings.createExplicitly(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix); } else { // Use environment variables storageServiceSettings = StorageServiceSettings.createFromEnvironment(); diff --git a/lib/common/services/storageservicesettings.js b/lib/common/services/storageservicesettings.js index 75acc9c..aec2947 100644 --- a/lib/common/services/storageservicesettings.js +++ b/lib/common/services/storageservicesettings.js @@ -54,6 +54,11 @@ var fileEndpointSetting = ServiceSettings.settingWithFunc( Validate.isValidHost ); +var endpointSuffixSetting = ServiceSettings.settingWithFunc( + ConnectionStringKeys.ENDPOINT_SUFFIX_NAME, + Validate.isValidHost +); + var validKeys = [ ConnectionStringKeys.USE_DEVELOPMENT_STORAGE_NAME, ConnectionStringKeys.DEVELOPMENT_STORAGE_PROXY_URI_NAME, @@ -64,7 +69,8 @@ var validKeys = [ ConnectionStringKeys.BLOB_ENDPOINT_NAME, ConnectionStringKeys.QUEUE_ENDPOINT_NAME, ConnectionStringKeys.TABLE_ENDPOINT_NAME, - ConnectionStringKeys.FILE_ENDPOINT_NAME + ConnectionStringKeys.FILE_ENDPOINT_NAME, + ConnectionStringKeys.ENDPOINT_SUFFIX_NAME ]; /** @@ -122,7 +128,7 @@ StorageServiceSettings.createFromConnectionString = function (connectionString) } }; -StorageServiceSettings.createExplicitly = function (storageAccount, storageAccessKey, host, sasToken) { +StorageServiceSettings.createExplicitly = function (storageAccount, storageAccessKey, host, sasToken, endpointSuffix) { var settings = {}; function addIfNotNullOrEmpty(key, value){ if(typeof value === 'string' && !util.stringIsEmpty(value)){ @@ -145,6 +151,7 @@ StorageServiceSettings.createExplicitly = function (storageAccount, storageAcces addIfNotNullOrEmpty('accountname', storageAccount); addIfNotNullOrEmpty('accountkey', storageAccessKey); addIfNotNullOrEmpty('sharedaccesssignature', sasToken); + addIfNotNullOrEmpty('endpointsuffix', endpointSuffix); return StorageServiceSettings.createFromSettings(settings); }; @@ -163,7 +170,7 @@ StorageServiceSettings.createFromEnvironment = function () { var storageAccount = process.env[StorageServiceClientConstants.EnvironmentVariables.AZURE_STORAGE_ACCOUNT]; var storageAccessKey = process.env[StorageServiceClientConstants.EnvironmentVariables.AZURE_STORAGE_ACCESS_KEY]; if(storageAccount && storageAccessKey){ - return StorageServiceSettings.createExplicitly(storageAccount, storageAccessKey, null, null); + return StorageServiceSettings.createExplicitly(storageAccount, storageAccessKey, null, null, null); } throw new Error(SR.NO_CREDENTIALS_PROVIDED); @@ -204,7 +211,8 @@ StorageServiceSettings.createFromSettings = function (settings) { blobEndpointSetting, queueEndpointSetting, tableEndpointSetting, - fileEndpointSetting + fileEndpointSetting, + endpointSuffixSetting ) ); @@ -223,7 +231,8 @@ StorageServiceSettings.createFromSettings = function (settings) { blobEndpointSetting, queueEndpointSetting, tableEndpointSetting, - fileEndpointSetting + fileEndpointSetting, + endpointSuffixSetting ) ); @@ -241,7 +250,8 @@ StorageServiceSettings.createFromSettings = function (settings) { blobEndpointSetting, queueEndpointSetting, tableEndpointSetting, - fileEndpointSetting + fileEndpointSetting, + endpointSuffixSetting ) ); @@ -259,7 +269,8 @@ StorageServiceSettings.createFromSettings = function (settings) { ServiceSettings.optional( fileEndpointSetting, queueEndpointSetting, - tableEndpointSetting + tableEndpointSetting, + endpointSuffixSetting ) ); @@ -363,29 +374,34 @@ StorageServiceSettings._createStorageServiceSettings = function (settings) { settings ); + var endpointSuffix = util.tryGetValueInsensitive( + ConnectionStringKeys.ENDPOINT_SUFFIX_NAME, + settings + ); + var blobEndpoint = standardizeHost( util.tryGetValueInsensitive(ConnectionStringKeys.BLOB_ENDPOINT_NAME, settings), accountName, scheme, - StorageServiceClientConstants.CLOUD_BLOB_HOST); + endpointSuffix ? 'blob.' + endpointSuffix : StorageServiceClientConstants.CLOUD_BLOB_HOST); var queueEndpoint = standardizeHost( util.tryGetValueInsensitive(ConnectionStringKeys.QUEUE_ENDPOINT_NAME, settings), accountName, scheme, - StorageServiceClientConstants.CLOUD_QUEUE_HOST); + endpointSuffix ? 'queue.' + endpointSuffix : StorageServiceClientConstants.CLOUD_QUEUE_HOST); var tableEndpoint = standardizeHost( util.tryGetValueInsensitive(ConnectionStringKeys.TABLE_ENDPOINT_NAME, settings), accountName, scheme, - StorageServiceClientConstants.CLOUD_TABLE_HOST); + endpointSuffix ? 'table.' + endpointSuffix : StorageServiceClientConstants.CLOUD_TABLE_HOST); var fileEndpoint = standardizeHost( util.tryGetValueInsensitive(ConnectionStringKeys.FILE_ENDPOINT_NAME, settings), accountName, scheme, - StorageServiceClientConstants.CLOUD_FILE_HOST); + endpointSuffix ? 'file.' + endpointSuffix : StorageServiceClientConstants.CLOUD_FILE_HOST); return new StorageServiceSettings( diff --git a/lib/common/util/constants.js b/lib/common/util/constants.js index 4ce35c5..7ab80d0 100644 --- a/lib/common/util/constants.js +++ b/lib/common/util/constants.js @@ -2338,6 +2338,7 @@ var Constants = { QUEUE_ENDPOINT_NAME: 'QueueEndpoint', TABLE_ENDPOINT_NAME: 'TableEndpoint', SHARED_ACCESS_SIGNATURE_NAME: 'SharedAccessSignature', + ENDPOINT_SUFFIX_NAME: 'EndpointSuffix', BLOB_BASE_DNS_NAME: 'blob.core.windows.net', FILE_BASE_DNS_NAME: 'file.core.windows.net', QUEUE_BASE_DNS_NAME: 'queue.core.windows.net', diff --git a/lib/services/blob/blobservice.js b/lib/services/blob/blobservice.js index 5963774..71b5ceb 100644 --- a/lib/services/blob/blobservice.js +++ b/lib/services/blob/blobservice.js @@ -93,9 +93,10 @@ var StorageError = errors.StorageError; * @param {string|object} [host] The host address. To define primary only, pass a string. * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host. * @param {string} [sasToken] The Shared Access Signature token. +* @param {string} [endpointSuffix] The endpoint suffix. */ -function BlobService(storageAccountOrConnectionString, storageAccessKey, host, sasToken) { - var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken); +function BlobService(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix) { + var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix); BlobService['super_'].call(this, storageServiceSettings._name, diff --git a/lib/services/file/fileservice.js b/lib/services/file/fileservice.js index 1ac5a27..c2475d2 100644 --- a/lib/services/file/fileservice.js +++ b/lib/services/file/fileservice.js @@ -83,9 +83,10 @@ var ArgumentNullError = errors.ArgumentNullError; * @param {string|object} [host] The host address. To define primary only, pass a string. * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host. * @param {string} [sasToken] The Shared Access Signature token. +* @param {string} [endpointSuffix] The endpoint suffix. */ -function FileService(storageAccountOrConnectionString, storageAccessKey, host, sasToken) { - var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken); +function FileService(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix) { + var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix); FileService['super_'].call(this, storageServiceSettings._name, diff --git a/lib/services/queue/queueservice.js b/lib/services/queue/queueservice.js index fead0d3..c7299f8 100644 --- a/lib/services/queue/queueservice.js +++ b/lib/services/queue/queueservice.js @@ -62,9 +62,10 @@ var ServiceStatsParser = azureCommon.ServiceStatsParser; * @param {string|object} [host] The host address. To define primary only, pass a string. * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host. * @param {string} [sasToken] The Shared Access Signature token. +* @param {string} [endpointSuffix] The endpoint suffix. */ -function QueueService(storageAccountOrConnectionString, storageAccessKey, host, sasToken) { - var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken); +function QueueService(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix) { + var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix); QueueService['super_'].call(this, storageServiceSettings._name, diff --git a/lib/services/table/tableservice.js b/lib/services/table/tableservice.js index 969cb62..0e13b74 100644 --- a/lib/services/table/tableservice.js +++ b/lib/services/table/tableservice.js @@ -68,9 +68,10 @@ var TableUtilities = require('./tableutilities'); * @param {string|object} [host] The host address. To define primary only, pass a string. * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host. * @param {string} [sasToken] The Shared Access Signature token. +* @param {string} [endpointSuffix] The endpoint suffix. */ -function TableService(storageAccountOrConnectionString, storageAccessKey, host, sasToken) { - var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken); +function TableService(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix) { + var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken, endpointSuffix); TableService['super_'].call(this, storageServiceSettings._name, diff --git a/test/common/storageservicesettingstests.js b/test/common/storageservicesettingstests.js index f75c4d0..f40b8cd 100644 --- a/test/common/storageservicesettingstests.js +++ b/test/common/storageservicesettingstests.js @@ -316,6 +316,41 @@ describe('StorageServiceSettingsTests', function(done) { done(); }); + it('testCreateFromConnectionStringWithEndpointSuffixSpecified', function(done) { + // Setup + var protocol = 'https'; + var endpointSuffix = 'core.chinacloudapi.cn'; + + var expectedName = 'mytestaccount'; + var expectedKey = 'AhlzsbLRkjfwObuqff3xrhB2yWJNh1EMptmcmxFJ6fvPTVX3PZXwrG2YtYWf5DPMVgNsteKStM5iBLlknYFVoA=='; + var expectedTableEndpoint = url.format({ protocol: protocol, host: expectedName + '.table.' + endpointSuffix }); + var expectedBlobEndpoint = url.format({ protocol: protocol, host: expectedName + '.blob.' + endpointSuffix }); + var expectedQueueEndpoint = url.format({ protocol: protocol, host: expectedName + '.queue.' + endpointSuffix }); + var expectedFileEndpoint = url.format({ protocol: protocol, host: expectedName + '.file.' + endpointSuffix }); + var expectedTableSecondaryEndpoint = url.format({ protocol: protocol, host: expectedName + '-secondary.table.' + endpointSuffix }); + var expectedBlobSecondaryEndpoint = url.format({ protocol: protocol, host: expectedName + '-secondary.blob.' + endpointSuffix }); + var expectedQueueSecondaryEndpoint = url.format({ protocol: protocol, host: expectedName + '-secondary.queue.' + endpointSuffix }); + var expectedFileSecondaryEndpoint = url.format({ protocol: protocol, host: expectedName + '-secondary.file.' + endpointSuffix }); + var connectionString = 'DefaultEndpointsProtocol=' + protocol + ';AccountName=' + expectedName + ';AccountKey=' + expectedKey + ';EndpointSuffix=' + endpointSuffix; + + // Test + var actual = StorageServiceSettings.createFromConnectionString(connectionString); + + // Assert + assert.strictEqual(actual._name, expectedName); + assert.strictEqual(actual._key, expectedKey); + assert.strictEqual(actual._blobEndpoint.primaryHost, expectedBlobEndpoint); + assert.strictEqual(actual._queueEndpoint.primaryHost, expectedQueueEndpoint); + assert.strictEqual(actual._tableEndpoint.primaryHost, expectedTableEndpoint); + assert.strictEqual(actual._fileEndpoint.primaryHost, expectedFileEndpoint); + assert.strictEqual(actual._blobEndpoint.secondaryHost, expectedBlobSecondaryEndpoint); + assert.strictEqual(actual._queueEndpoint.secondaryHost, expectedQueueSecondaryEndpoint); + assert.strictEqual(actual._tableEndpoint.secondaryHost, expectedTableSecondaryEndpoint); + assert.strictEqual(actual._fileEndpoint.secondaryHost, expectedFileSecondaryEndpoint); + assert.strictEqual(actual._usePathStyleUri, false); + done(); + }); + it('testCreateFromConnectionStringWithQueueEndpointSpecified', function(done) { // Setup var protocol = 'https'; diff --git a/typings/azure-storage/azure-storage.d.ts b/typings/azure-storage/azure-storage.d.ts index 6a300e2..ecbe0f7 100644 --- a/typings/azure-storage/azure-storage.d.ts +++ b/typings/azure-storage/azure-storage.d.ts @@ -94,8 +94,9 @@ declare module "azure-storage" { * @param {string|object} [host] The host address. To define primary only, pass a string. * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host. * @param {string} [sasToken] The Shared Access Signature token. + * @param {string} [endpointSuffix] The endpoint suffix. */ - constructor(storageAccountOrConnectionString: string, storageAccessKey?: string, host?: string|StorageHost, sasToken?: string); + constructor(storageAccountOrConnectionString: string, storageAccessKey?: string, host?: string|StorageHost, sasToken?: string, endpointSuffix?: string); /** * Associate a filtering operation with this BlobService. Filtering operations @@ -2817,8 +2818,9 @@ declare module "azure-storage" { * @param {string|object} [host] The host address. To define primary only, pass a string. * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host. * @param {string} [sasToken] The Shared Access Signature token. + * @param {string} [endpointSuffix] The endpoint suffix. */ - constructor(storageAccountOrConnectionString?: string, storageAccessKey?: string, host?: string|StorageHost, sasToken?: string); + constructor(storageAccountOrConnectionString?: string, storageAccessKey?: string, host?: string|StorageHost, sasToken?: string, endpointSuffix?: string); /** * Associate a filtering operation with this QueueService. Filtering operations @@ -5059,8 +5061,9 @@ declare module "azure-storage" { * @param {string|object} [host] The host address. To define primary only, pass a string. * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host. * @param {string} [sasToken] The Shared Access Signature token. + * @param {string} [endpointSuffix] The endpoint suffix. */ - new (storageAccountOrConnectionString?: string, storageAccessKey?: string, host?: string|StorageHost, sasToken?: string): TableService; + new (storageAccountOrConnectionString?: string, storageAccessKey?: string, host?: string|StorageHost, sasToken?: string, endpointSuffix?: string): TableService; } export module TableUtilities { @@ -7083,8 +7086,9 @@ declare module "azure-storage" { * @param {string|object} [host] The host address. To define primary only, pass a string. * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host. * @param {string} [sasToken] The Shared Access Signature token. + * @param {string} [endpointSuffix] The endpoint suffix. */ - new (storageAccountOrConnectionString?: string, storageAccessKey?: string, host?: string|StorageHost, sasToken?: string): FileService; + new (storageAccountOrConnectionString?: string, storageAccessKey?: string, host?: string|StorageHost, sasToken?: string, endpointSuffix?: string): FileService; } // ###########################