Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Adding connection string parser. #376

Merged
merged 27 commits into from

2 participants

@andrerod

No description provided.

lib/services/core/connectionstringparser.js
((12 lines not shown))
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+var util = require('../../util/util');
+
+// Expose 'ConnectionStringParser'.
+exports = module.exports = ConnectionStringParser;
+
+/**
+* Parses a connection string.
+*
+* @param {number} connectionString The connection string to be parsed.
+* @return {object} The query string object.
+*/
+ConnectionStringParser.parse = function (connectionString) {

I know it works, but it feels really weird to see assignment to a property of a variable before that variable has been defined. Could you move the definition of the constructor function up above the definitions of the methods?

Looking at this some more, I don't see any reason for this to be a "static member" of ConnectionStringParser - just make it a top level function in the module.

There's 1 reason... styling. Makes it more coherent with other languages and modules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
test/services/core/connectionstringparser-tests.js
((37 lines not shown))
+ assert.equal(JSON.stringify(parsedConnectionString), '{}');
+
+ // Empty with spaces
+ var parsedConnectionString = ConnectionStringParser.parse(' ');
+ assert.equal(JSON.stringify(parsedConnectionString), '{}');
+
+ done();
+ });
+
+ test('parseInvalidAssignment', function (done) {
+ // no assignment
+ assert.throws(
+ function() {
+ var parsedConnectionString = ConnectionStringParser.parse('Endpoint');
+ },
+ Error

Can we add some assertions here on the type of error and message? Parsers with crap error messages are a recipe for frustrated uses when they can't figure out what's wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
test/services/core/connectionstringparser-tests.js
((62 lines not shown))
+ },
+ Error
+ );
+
+ assert.throws(
+ function() {
+ var parsedConnectionString = ConnectionStringParser.parse(' =value');
+ },
+ Error
+ );
+
+ done();
+ });
+
+ test('parseQuotedValues', function (done) {
+ var parsedConnectionString = ConnectionStringParser.parse('"test"=\'value\'');

Add a second word in the value and some spaces - that's what quotes are for, right? So do "test"=\'value of test\'" or something like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/services/core/connectionstringparser.js
((4 lines not shown))
+* 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.
+*/
+
+var util = require('../../util/util');
+
+// Expose 'ConnectionStringParser'.
+exports = module.exports = ConnectionStringParser;

The ConnectionStringParser function will never be used standalone, correct? If so, there's no reason to expose it. Instead, do:

exports = module.exports = { ConnectionStringParser: { parse: ConnectionStringParser.parse } }

Fair enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@christav

Is there a bug# for this work?

lib/services/core/connectionstringparser.js
((34 lines not shown))
+*
+* @constructor
+* @param {number} connectionString The connection string to be parsed.
+*/
+function ConnectionStringParser(connectionString) {
+ this._connectionString = connectionString;
+}
+
+/**
+* Parses a connection string into an object.
+*
+* @return {object} The query string object.
+*/
+ConnectionStringParser.prototype._parse = function () {
+ var self = this;
+ var parts = this._connectionString.split(';');

What if there's an escaped ';' or one inside a quoted block? Is this possible? If so, you'll need to handle this differently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/services/core/connectionstringparser.js
((41 lines not shown))
+
+/**
+* Parses a connection string into an object.
+*
+* @return {object} The query string object.
+*/
+ConnectionStringParser.prototype._parse = function () {
+ var self = this;
+ var parts = this._connectionString.split(';');
+ var parsedConnectionString = { };
+
+ parts.forEach(function (part) {
+ part = part.trim();
+
+ if (part) {
+ var currentKVP = part.split('=');

What if there's an escaped '=' or one inside quotes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/services/core/connectionstringparser.js
((147 lines not shown))
+ // Runaway string.
+ throw new Error('Invalid string');
+ }
+
+ return this._value.substring(firstPos, this._pos++);
+};
+
+/**
+* Skips specified operator.
+*
+* @param {string} operatorChar The oeprator to skip.
+*/
+ConnectionStringParser.prototype._skipOperator = function (operatorChar) {
+ if (this._value[this._pos] != operatorChar) {
+ // Character was expected.
+ throw new Error('Character not expected ' + operatorChar);

Tweak error message to "expecting " + operatorChar + " but instead got " + currentChar + " at position " + this._pos.toString()

Or something like that. Please give more information about what's wrong and where it's wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/services/core/connectionstringparser.js
((133 lines not shown))
+/**
+* Extracts the string until the given quotation mark.
+*
+* @param {string} quote Quotation mark terminating the string.
+* @return {string} string.
+*/
+ConnectionStringParser.prototype._extractString = function (quote) {
+ var firstPos = this._pos;
+ while (this._pos < this._value.length && this._value[this._pos] !== quote)
+ {
+ this._pos++;
+ }
+
+ if (this._pos === this._value.length) {
+ // Runaway string.
+ throw new Error('Invalid string');

Include information about why the string is invalid - this should probably read "unterminated string starting at position..." instead of just "invalid"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@christav christav commented on the diff
lib/services/core/connectionstringparser.js
((126 lines not shown))
+ // Empty key name.
+ throw new Error('Empty key name');
+ }
+
+ return key;
+};
+
+/**
+* Extracts the string until the given quotation mark.
+*
+* @param {string} quote Quotation mark terminating the string.
+* @return {string} string.
+*/
+ConnectionStringParser.prototype._extractString = function (quote) {
+ var firstPos = this._pos;
+ while (this._pos < this._value.length && this._value[this._pos] !== quote)

Is there a way to escape quotes within a quoted string? If so then this needs to be a little more complex to handle that case. If not, you're good.

nop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@andrerod

Updated.

@christav christav commented on the diff
test/services/core/connectionstringparser-tests.js
((77 lines not shown))
+ function() {
+ var parsedConnectionString = ConnectionStringParser.parse(' =value');
+ },
+ function(err) {
+ if ((err instanceof Error) && err.message === 'Missing key') {
+ return true;
+ }
+ },
+ "unexpected error"
+ );
+
+ done();
+ });
+
+ test('parseQuotedValues', function (done) {
+ var parsedConnectionString = ConnectionStringParser.parse('"test key"=\'value of test\'');

Nice update on the test cases here and below.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@christav christav commented on the diff
lib/services/core/connectionstringparser.js
((147 lines not shown))
+ // Runaway string.
+ throw new Error('Unterminated string starting at position ' + firstPos);
+ }
+
+ return this._value.substring(firstPos, this._pos++);
+};
+
+/**
+* Skips specified operator.
+*
+* @param {string} operatorChar The oeprator to skip.
+*/
+ConnectionStringParser.prototype._skipOperator = function (operatorChar) {
+ if (this._value[this._pos] != operatorChar) {
+ // Character was expected.
+ throw new Error('expecting ' + operatorChar + ' but instead got ' + currentChar + ' at position ' + this._pos);

There's no currentChar variable - you should probably define one, or replace with the full expression.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@andrerod andrerod merged commit a6830e1 into Azure:dev
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 8, 2012
  1. @andrerod
Commits on Oct 10, 2012
  1. @andrerod
  2. @andrerod

    Handling quotes.

    andrerod authored
  3. @andrerod

    Adding comments.

    andrerod authored
  4. @andrerod
  5. @andrerod

    Fixing undeclared variable.

    andrerod authored
  6. @andrerod

    Simplifying condition.

    andrerod authored
  7. @andrerod
  8. @andrerod
  9. @andrerod
  10. @andrerod

    Adding more UT.

    andrerod authored
  11. @andrerod
  12. @andrerod

    Updating parser.

    andrerod authored
  13. @andrerod

    Applying code review.

    andrerod authored
  14. @andrerod

    Adding more UT.

    andrerod authored
  15. @andrerod

    Merge pull request #3 from andrerod/connect

    andrerod authored
    Connect
  16. @andrerod
  17. @andrerod
  18. @andrerod
  19. @andrerod
  20. @andrerod

    Removing CLI tests.

    andrerod authored
  21. @andrerod

    Updating error messages.

    andrerod authored
  22. @andrerod
  23. @andrerod

    Adding protocol check.

    andrerod authored
  24. @andrerod

    Applying review comments.

    andrerod authored
  25. @andrerod

    Merge pull request #5 from andrerod/storageconnect

    andrerod authored
    Storageconnect
  26. @andrerod

    Uncomment UT.

    andrerod authored
This page is out of date. Refresh to see the latest.
View
53 lib/azure.js
@@ -26,13 +26,13 @@ exports.TableService = TableService;
* Creates a new TableService object.
* If no storageaccount or storageaccesskey are provided, the AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY environment variables will be used.
*
-* @param {string} [storageAccount] The storage account.
-* @param {string} [storageAccessKey] The storage access key.
-* @param {string} [host] The host address.
-* @param {object} [authenticationProvider] The authentication provider.
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string} [host] The host address.
+* @param {object} [authenticationProvider] The authentication provider.
*/
-exports.createTableService = function (storageAccount, storageAccessKey, host, authenticationProvider) {
- return new TableService(storageAccount, storageAccessKey, host, authenticationProvider);
+exports.createTableService = function (storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider) {
+ return new TableService(storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider);
};
/**
@@ -46,13 +46,13 @@ exports.BlobService = BlobService;
* Creates a new BlobService object.
* If no storageaccount or storageaccesskey are provided, the AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY environment variables will be used.
*
-* @param {string} [storageAccount] The storage account.
-* @param {string} [storageAccessKey] The storage access key.
-* @param {string} [host] The host address.
-* @param {object} [authenticationProvider] The authentication provider.
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string} [host] The host address.
+* @param {object} [authenticationProvider] The authentication provider.
*/
-exports.createBlobService = function (storageAccount, storageAccessKey, host, authenticationProvider) {
- return new BlobService(storageAccount, storageAccessKey, host, authenticationProvider);
+exports.createBlobService = function (storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider) {
+ return new BlobService(storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider);
};
/**
@@ -67,13 +67,13 @@ exports.QueueService = QueueService;
* If no storageAccount or storageAccessKey are provided, the AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY
* environment variables will be used.
*
-* @param {string} [storageAccount] The storage account.
-* @param {string} [storageAccessKey] The storage access key.
-* @param {string} [host] The host address.
-* @param {object} [authenticationProvider] The authentication provider.
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string} [host] The host address.
+* @param {object} [authenticationProvider] The authentication provider.
*/
-exports.createQueueService = function (storageAccount, storageAccessKey, host, authenticationProvider) {
- return new QueueService(storageAccount, storageAccessKey, host, authenticationProvider);
+exports.createQueueService = function (storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider) {
+ return new QueueService(storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider);
};
/**
@@ -86,15 +86,15 @@ exports.ServiceBusService = ServiceBusService;
/**
* Creates a new ServiceBusService object.
*
-* @param {string} [namespace] The service bus namespace.
-* @param {string} [accessKey] The password.
-* @param {string} [issuer] The issuer.
-* @param {string} [acsNamespace] The acs namespace. Usually the same as the sb namespace with "-sb" suffix.
-* @param {string} [host] The host address.
-* @param {object} [authenticationProvider] The authentication provider.
+* @param {string} [namespaceOrConnectionString] The service bus namespace.
+* @param {string} [accessKey] The password.
+* @param {string} [issuer] The issuer.
+* @param {string} [acsNamespace] The acs namespace. Usually the same as the sb namespace with "-sb" suffix.
+* @param {string} [host] The host address.
+* @param {object} [authenticationProvider] The authentication provider.
*/
-exports.createServiceBusService = function (namespace, accessKey, issuer, acsNamespace, host, authenticationProvider) {
- return new ServiceBusService(namespace, accessKey, issuer, acsNamespace, host, authenticationProvider);
+exports.createServiceBusService = function (namespaceOrConnectionString, accessKey, issuer, acsNamespace, host, authenticationProvider) {
+ return new ServiceBusService(namespaceOrConnectionString, accessKey, issuer, acsNamespace, host, authenticationProvider);
};
/**
@@ -149,6 +149,7 @@ exports.SharedKeyTable = require('./services/table/sharedkeytable');
exports.SharedKeyLiteTable = require('./services/table/sharedkeylitetable');
exports.ISO8061Date = require('./util/iso8061date');
exports.Logger = require('./diagnostics/logger');
+exports.ConnectionStringParser = require('./services/core/connectionstringparser');
/*
* Convenience functions.
View
12 lib/services/blob/blobservice.js
@@ -70,12 +70,12 @@ BlobService.incorrectEndByteOffsetErr = 'End byte offset must be a modulus of 51
* @constructor
* @extends {ServiceClient}
*
-* @param {string} [storageAccount] The storage account.
-* @param {string} [storageAccessKey] The storage access key.
-* @param {string} [host] The host address.
-* @param {object} [authenticationProvider] The authentication provider.
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string} [host] The host address.
+* @param {object} [authenticationProvider] The authentication provider.
*/
-function BlobService(storageAccount, storageAccessKey, host, authenticationProvider) {
+function BlobService(storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider) {
if (!host) {
if (ServiceClient.isEmulated()) {
host = ServiceClient.DEVSTORE_BLOB_HOST;
@@ -84,7 +84,7 @@ function BlobService(storageAccount, storageAccessKey, host, authenticationProvi
}
}
- BlobService.super_.call(this, host, storageAccount, storageAccessKey, authenticationProvider);
+ BlobService.super_.call(this, storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider);
if (!this.authenticationProvider) {
this.authenticationProvider = new SharedKey(this.storageAccount, this.storageAccessKey, this.usePathStyleUri);
View
217 lib/services/core/connectionstringparser.js
@@ -0,0 +1,217 @@
+/**
+* Copyright (c) Microsoft. All rights reserved.
+*
+* 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.
+*/
+
+var util = require('../../util/util');
+
+// Expose 'ConnectionStringParser'.
+exports = module.exports;
+
+/**
+* Creates a new 'ConnectionString' instance.
+*
+* @constructor
+* @param {string} connectionString The connection string to be parsed.
+*/
+function ConnectionStringParser(connectionString) {
+ this._value = connectionString;
+ this._pos = 0;
+ this._state = 'ExpectKey';
+}
+
+/**
+* Parses a connection string into an object.
+*
+* @return {object} The query string object.
+*/
+ConnectionStringParser.prototype._parse = function () {
+ var key = null;
+ var value = null;
+ var parsedConnectionString = { };
+
+ for (; ;) {
+ this._skipWhitespaces();
+
+ if (this._pos === this._value.length && this._state !== 'ExpectValue')
+ {
+ // Not stopping after the end has been reached and a value is expected
+ // results in creating an empty value, which we expect.
+ break;
+ }
+
+ switch (this._state) {
+ case 'ExpectKey':
+ key = this._extractKey();
+ this._state = 'ExpectAssignment';
+ break;
+
+ case 'ExpectAssignment':
+ this._skipOperator('=');
+ this._state = 'ExpectValue';
+ break;
+
+ case 'ExpectValue':
+ value = this._extractValue();
+ this._state = 'ExpectSeparator';
+ parsedConnectionString[key.toLowerCase()] = value;
+ key = null;
+ value = null;
+ break;
+
+ default:
+ this._skipOperator(';');
+ this._state = 'ExpectKey';
+ break;
+ }
+ }
+
+ if (this._state === 'ExpectAssignment') {
+ // Must end parsing in the valid state (expected key or separator)
+ throw new Error('Missing character "="');
+ }
+
+ return parsedConnectionString;
+};
+
+
+/**
+* Skips whitespaces at the current position.
+*/
+ConnectionStringParser.prototype._skipWhitespaces = function () {
+ while (this._pos < this._value.length && this._value[this._pos] === ' ')
+ {
+ this._pos++;
+ }
+};
+
+/**
+* Extracts key at the current position.
+*
+* @return {string} Key.
+*/
+ConnectionStringParser.prototype._extractKey = function () {
+ var key = null;
+ var firstPos = this._pos;
+ var ch = this._value[this._pos++];
+
+ if (ch === '"' || ch === '\'') {
+ key = this._extractString(ch);
+ } else if (ch === ';' || ch === '=') {
+ // Key name was expected.
+ throw new Error('Missing key');
+ } else {
+ while (this._pos < this._value.length) {
+ ch = this._value[this._pos];
+ if (ch === '=') {
+ break;
+ }
+ this._pos++;
+ }
+
+ key = this._value.substring(firstPos, this._pos);
+ }
+
+ if (key.length === 0) {
+ // Empty key name.
+ throw new Error('Empty key name');
+ }
+
+ return key;
+};
+
+/**
+* Extracts the string until the given quotation mark.
+*
+* @param {string} quote Quotation mark terminating the string.
+* @return {string} string.
+*/
+ConnectionStringParser.prototype._extractString = function (quote) {
+ var firstPos = this._pos;
+ while (this._pos < this._value.length && this._value[this._pos] !== quote)

Is there a way to escape quotes within a quoted string? If so then this needs to be a little more complex to handle that case. If not, you're good.

nop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ {
+ this._pos++;
+ }
+
+ if (this._pos === this._value.length) {
+ // Runaway string.
+ throw new Error('Unterminated string starting at position ' + firstPos);
+ }
+
+ return this._value.substring(firstPos, this._pos++);
+};
+
+/**
+* Skips specified operator.
+*
+* @param {string} operatorChar The oeprator to skip.
+*/
+ConnectionStringParser.prototype._skipOperator = function (operatorChar) {
+ if (this._value[this._pos] != operatorChar) {
+ // Character was expected.
+ throw new Error('expecting ' + operatorChar + ' but instead got ' + currentChar + ' at position ' + this._pos);

There's no currentChar variable - you should probably define one, or replace with the full expression.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ }
+
+ this._pos++;
+};
+
+/**
+* Extracts key's value.
+*
+* @return {string} The key value.
+*/
+ConnectionStringParser.prototype._extractValue = function () {
+ var value = '';
+
+ if (this._pos < this._value.length) {
+ var ch = this._value[this._pos];
+
+ if (ch === '\'' || ch === '"') {
+ this._pos++;
+ value = this._extractString(ch);
+ } else {
+ var firstPos = this._pos;
+ var isFound = false;
+
+ while (this._pos < this._value.length && !isFound) {
+ ch = this._value[this._pos];
+
+ switch (ch) {
+ case ';':
+ isFound = true;
+ break;
+
+
+ default:
+ this._pos++;
+ break;
+ }
+ }
+
+ value = this._value.substring(firstPos, this._pos);
+ }
+ }
+
+ return value;
+};
+
+/**
+* Parses a connection string.
+*
+* @param {number} connectionString The connection string to be parsed.
+* @return {object} The query string object.
+*/
+exports.parse = function (connectionString) {
+ var connectionStringParser = new ConnectionStringParser(connectionString);
+ return connectionStringParser._parse();
+};
View
3  lib/services/core/servicebusserviceclient.js
@@ -33,12 +33,11 @@ exports = module.exports = ServiceBusServiceClient;
* Creates a new ServiceBusServiceClient object.
*
* @constructor
-* @param {string} host The host for the service.
+* @param {string} host The host for the service.
* @param {string} [namespace] The service bus namespace.
* @param {string} [accessKey] The password.
* @param {string} [issuer] The issuer.
* @param {string} [acsNamespace] The acs namespace. Usually the same as the sb namespace with "-sb" suffix.
-* @param {string} [host] The host address.
* @param {object} [authenticationProvider] The authentication provider.
*/
function ServiceBusServiceClient(host, namespace, accessKey, issuer, acsNamespace, authenticationProvider) {
View
6 lib/services/core/serviceclient.js
@@ -109,9 +109,11 @@ function ServiceClient(host, authenticationProvider) {
var parsedHost = this._parseHost(host);
this.host = parsedHost.hostname;
this.port = parsedHost.port;
- this.protocol = parsedHost.protocol + '//';
+ if (!this.protocol) {
+ this.protocol = parsedHost.protocol + '//';
+ }
}
- else {
+ else if (!this.protocol) {
this.protocol = ServiceClient.DEFAULT_PROTOCOL;
}
View
35 lib/services/core/storageserviceclient.js
@@ -23,6 +23,8 @@ var xml2js = require('xml2js');
var azureutil = require('../../util/util');
+var ConnectionStringParser = require('../core/connectionstringparser');
+
var ServiceClient = require('./serviceclient');
var Constants = require('../../util/constants');
var HeaderConstants = Constants.HeaderConstants;
@@ -41,12 +43,35 @@ StorageServiceClient.incorrectStorageAccessKeyErr = 'AccessKey must be a non emp
* Creates a new ServiceClient object.
*
* @constructor
-* @param {string} host The host for the service.
-* @param {string} storageAccount The storage account.
-* @param {string} storageAccessKey The storage access key.
-* @param {object} authenticationProvider The authentication provider object (e.g. sharedkey / sharedkeytable / sharedaccesssignature).
+* @param {string} storageAccountOrConnectionString The storage account or connection string.
+* @param {string} storageAccessKey The storage access key.
+* @param {string} host The host for the service.
+* @param {object} authenticationProvider The authentication provider object (e.g. sharedkey / sharedkeytable / sharedaccesssignature).
*/
-function StorageServiceClient(host, storageAccount, storageAccessKey, authenticationProvider) {
+function StorageServiceClient(storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider) {
+ var storageAccount = storageAccountOrConnectionString;
+
+ if (storageAccountOrConnectionString && !storageAccessKey) {
+ // If namespaceOrConnectionString was passed and no accessKey was passed, assume connection string
+ var connectionString = ConnectionStringParser.parse(storageAccountOrConnectionString);
+ if (connectionString['accountname']) {
+ storageAccount = connectionString['accountname'];
+ }
+
+ if (connectionString['accountkey']) {
+ storageAccessKey = connectionString['accountkey'];
+ }
+
+ if (connectionString['defaultendpointsprotocol']) {
+ if (connectionString['defaultendpointsprotocol'] !== 'http' &&
+ connectionString['defaultendpointsprotocol'] !== 'https') {
+ throw new Error('Invalid protocol ' + connectionString['defaultendpointsprotocol']);
+ }
+
+ this.protocol = connectionString['defaultendpointsprotocol'] + '://';
+ }
+ }
+
this._setAccountCredentials(storageAccount, storageAccessKey);
this.apiVersion = HeaderConstants.TARGET_STORAGE_VERSION;
this.usePathStyleUri = ServiceClient.isEmulated(host);
View
12 lib/services/queue/queueservice.js
@@ -44,12 +44,12 @@ exports = module.exports = QueueService;
* @constructor
* @augments {ServiceClient}
*
-* @param {string} [storageAccount] The storage account.
-* @param {string} [storageAccessKey] The storage access key.
-* @param {string} [host] The host address.
-* @param {object} [authenticationProvider] The authentication provider.
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string} [host] The host address.
+* @param {object} [authenticationProvider] The authentication provider.
*/
-function QueueService(storageAccount, storageAccessKey, host, authenticationProvider) {
+function QueueService(storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider) {
if (!host) {
if (ServiceClient.isEmulated()) {
host = ServiceClient.DEVSTORE_QUEUE_HOST;
@@ -58,7 +58,7 @@ function QueueService(storageAccount, storageAccessKey, host, authenticationProv
}
}
- QueueService.super_.call(this, host, storageAccount, storageAccessKey, authenticationProvider);
+ QueueService.super_.call(this, storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider);
if (!this.authenticationProvider) {
this.authenticationProvider = new SharedKey(this.storageAccount, this.storageAccessKey, this.usePathStyleUri);
View
41 lib/services/serviceBus/servicebusservice.js
@@ -15,6 +15,7 @@
// Module dependencies.
var util = require('util');
+var url = require('url');
var azureutil = require('../../util/util');
var RFC1123 = require('../../util/rfc1123date');
@@ -28,6 +29,8 @@ var QueryStringConstants = Constants.QueryStringConstants;
var HttpConstants = Constants.HttpConstants;
var HeaderConstants = Constants.HeaderConstants;
+var ConnectionStringParser = require('../core/connectionstringparser');
+
var QueueResult = require('./models/queueresult');
var QueueMessageResult = require('./models/queuemessageresult');
var TopicResult = require('./models/topicresult');
@@ -43,18 +46,42 @@ exports = module.exports = ServiceBusService;
* @constructor
* @augments {ServiceClient}
*
-* @param {string} [namespace] The service bus namespace.
-* @param {string} [accessKey] The password.
-* @param {string} [issuer] The issuer.
-* @param {string} [acsNamespace] The acs namespace. Usually the same as the sb namespace with "-sb" suffix.
-* @param {string} [host] The host address.
-* @param {object} [authenticationProvider] The authentication provider.
+* @param {string} [namespaceOrConnectionString] The service bus namespace or the connection string.
+* @param {string} [accessKey] The password.
+* @param {string} [issuer] The issuer.
+* @param {string} [acsNamespace] The acs namespace. Usually the same as the sb namespace with "-sb" suffix.
+* @param {string} [host] The host address.
+* @param {object} [authenticationProvider] The authentication provider.
*/
-function ServiceBusService(namespace, accessKey, issuer, acsNamespace, host, authenticationProvider) {
+function ServiceBusService(namespaceOrConnectionString, accessKey, issuer, acsNamespace, host, authenticationProvider) {
if (!host) {
host = ServiceClient.CLOUD_SERVICEBUS_HOST;
}
+ var namespace = namespaceOrConnectionString;
+ if (namespaceOrConnectionString && !accessKey) {
+ // If namespaceOrConnectionString was passed and no accessKey was passed, assume connection string
+ var connectionString = ConnectionStringParser.parse(namespaceOrConnectionString);
+ if (connectionString['endpoint']) {
+ var endpoint = url.parse(connectionString['endpoint']);
+ namespace = endpoint.host.split('.')[0];
+ host = endpoint.host.substring(namespace.length + 1);
+ }
+
+ if (connectionString['sharedsecretissuer']) {
+ issuer = connectionString['sharedsecretissuer'];
+ }
+
+ if (connectionString['sharedsecretvalue']) {
+ accessKey = connectionString['sharedsecretvalue'];
+ }
+
+ if (connectionString['stsendpoint']) {
+ var endpoint = url.parse(connectionString['stsendpoint']);
+ acsNamespace = endpoint.host.split('.')[0];
+ }
+ }
+
ServiceBusService.super_.call(this, host, namespace, accessKey, issuer, acsNamespace, authenticationProvider);
}
View
32 lib/services/serviceManagement/servicemanagementservice.js
@@ -31,24 +31,24 @@ exports = module.exports = ServiceManagementService;
* Creates a new ServiceManagementService object.
*
* @constructor
-* @param {string} subscriptionId The subscription ID for the account.
-* @param {string} authentication The authentication object for the client.
-* {
-* keyfile: 'path to .pem',
-* certfile: 'path to .pem',
-* keyvalue: privatekey value,
-* certvalue: public cert value
-* }
-* @param {string} hostOptions The host options to override defaults.
-* {
-* host: 'management.core.windows.net',
-* apiversion: '2012-03-01',
-* serializetype: 'XML'
-* }
+* @param {string} subscriptionIdOrConnectionString The subscription ID for the account or the connectionString.
+* @param {string} authentication The authentication object for the client.
+* {
+* keyfile: 'path to .pem',
+* certfile: 'path to .pem',
+* keyvalue: privatekey value,
+* certvalue: public cert value
+* }
+* @param {string} hostOptions The host options to override defaults.
+* {
+* host: 'management.core.windows.net',
+* apiversion: '2012-03-01',
+* serializetype: 'XML'
+* }
*/
-function ServiceManagementService(subscriptionId, authentication, hostOptions) {
+function ServiceManagementService(subscriptionIdOrConnectionString, authentication, hostOptions) {
if (typeof subscriptionId != 'string' || subscriptionId.length === 0) {
- throw new Error('SubscriptionId is required');
+ throw new Error('A subscriptionId or a connection string is required');
}
ServiceManagementService.super_.call(this, authentication, hostOptions);
View
12 lib/services/table/tableservice.js
@@ -54,12 +54,12 @@ TableService.incorrectPartitionErr = 'PartitionKey and RowKey must be specified
* @constructor
* @extends {ServiceClient}
*
-* @param {string} [storageAccount] The storage account.
-* @param {string} [storageAccessKey] The storage access key.
-* @param {string} [host] The host address.
-* @param {object} [authenticationProvider] The authentication provider.
+* @param {string} [storageAccountOrConnectionString] The storage account or the connection string.
+* @param {string} [storageAccessKey] The storage access key.
+* @param {string} [host] The host address.
+* @param {object} [authenticationProvider] The authentication provider.
*/
-function TableService(storageAccount, storageAccessKey, host, authenticationProvider) {
+function TableService(storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider) {
if (!host) {
if (ServiceClient.isEmulated()) {
host = ServiceClient.DEVSTORE_TABLE_HOST;
@@ -68,7 +68,7 @@ function TableService(storageAccount, storageAccessKey, host, authenticationProv
}
}
- TableService.super_.call(this, host, storageAccount, storageAccessKey, authenticationProvider);
+ TableService.super_.call(this, storageAccountOrConnectionString, storageAccessKey, host, authenticationProvider);
if (!this.authenticationProvider) {
this.authenticationProvider = new SharedKeyTable(this.storageAccount, this.storageAccessKey, this.usePathStyleUri);
View
20 test/cli/commands/cli.account-tests.js
@@ -18,19 +18,15 @@ var cli = require('../cli');
var capture = require('../util').capture;
suite('cli', function(){
- suite('account', function() {
-
- suite('import', function() {
-
- test('should launch browser when there is no file name', function(done) {
+ suite('account', function() {
+ suite('import', function() {
+ test('should launch browser when there is no file name', function(done) {
+ capture(function() {
+ cli.parse('node cli.js account import data/account-credentials.publishsettings'.split(' '));
+ }, function (result) {
- var result = capture(function() {
- cli.parse('node cli.js account import'.split(' '));
- });
-
- done();
- });
-
+ done();
+ });
});
});
});
View
34 test/cli/commands/cli.site-tests.js
@@ -0,0 +1,34 @@
+/**
+* Copyright 2012 Microsoft Corporation
+*
+* 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.
+*/
+
+require('should');
+var cli = require('../cli');
+var capture = require('../util').capture;
+
+suite('cli', function(){
+ suite('site', function() {
+ suite('list', function() {
+ test('should list no sites', function(done) {
+ capture(function() {
+ cli.parse('node cli.js site list --json'.split(' '));
+ }, function (result) {
+ done();
+ });
+ });
+ });
+ });
+});
+
+
View
11 test/cli/data/account-credentials.publishsettings
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PublishData>
+ <PublishProfile
+ PublishMethod="AzureServiceManagementAPI"
+ Url="https://management.core.windows.net/"
+ ManagementCertificate="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">
+ <Subscription
+ Id="db1ab6f0-4769-4b27-930e-01e2ef9c123c"
+ Name="Account" />
+ </PublishProfile>
+</PublishData>
View
8 test/cli/util.js
@@ -17,7 +17,7 @@ exports = module.exports = {
capture: capture,
};
-function capture(action) {
+function capture(action, cb) {
var result = {
text: '',
}
@@ -26,11 +26,12 @@ function capture(action) {
var processExit = process.exit
process.stdout.write = function(data, encoding, fd) {
- result.text = result.text + data;
+ result.text += data;
};
process.exit = function(status) {
result.exitStatus = status;
- throw new Error('process exit');
+
+ return cb(result);
};
try {
@@ -41,5 +42,4 @@ function capture(action) {
}
process.stdout.write = processStdoutWrite;
process.exit = processExit;
- return result;
}
View
12 test/services/blob/blobservice-tests.js
@@ -1272,6 +1272,18 @@ suite('blobservice-tests', function () {
});
});
});
+
+ test('storageConnectionStrings', function (done) {
+ var connectionString = 'DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=mykey';
+ var blobService = azure.createBlobService(connectionString);
+
+ assert.equal(blobService.storageAccount, 'myaccount');
+ assert.equal(blobService.storageAccessKey, 'mykey');
+ assert.equal(blobService.protocol, 'https://');
+ assert.equal(blobService.host, 'blob.core.windows.net');
+
+ done();
+ });
});
function repeat(s, n) {
View
112 test/services/core/connectionstringparser-tests.js
@@ -0,0 +1,112 @@
+/**
+* Copyright (c) Microsoft. All rights reserved.
+*
+* 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.
+*/
+
+var assert = require('assert');
+
+// Test includes
+var testutil = require('../../util/util');
+
+var azure = testutil.libRequire('azure');
+var ConnectionStringParser = azure.ConnectionStringParser;
+
+suite('connectionstringparser-tests', function () {
+ test('parseValid', function (done) {
+ var parsedConnectionString = ConnectionStringParser.parse('Endpoint=sb://ablal-martvue.servicebus.windows.net/;SharedSecretIssuer=owner;SharedSecretValue=value');
+ assert.equal(parsedConnectionString['endpoint'], 'sb://ablal-martvue.servicebus.windows.net/');
+ assert.equal(parsedConnectionString['sharedsecretissuer'], 'owner');
+ assert.equal(parsedConnectionString['sharedsecretvalue'], 'value');
+
+ done();
+ });
+
+ test('parseEmpty', function (done) {
+ // actual empty
+ var parsedConnectionString = ConnectionStringParser.parse('');
+ assert.equal(JSON.stringify(parsedConnectionString), '{}');
+
+ // Empty with spaces
+ var parsedConnectionString = ConnectionStringParser.parse(' ');
+ assert.equal(JSON.stringify(parsedConnectionString), '{}');
+
+ done();
+ });
+
+ test('parseInvalidAssignment', function (done) {
+ // no assignment
+ assert.throws(
+ function() {
+ var parsedConnectionString = ConnectionStringParser.parse('Endpoint');
+ },
+ function(err) {
+ if ((err instanceof Error) && err.message === 'Missing character "="') {
+ return true;
+ }
+ },
+ "unexpected error"
+ );
+
+ done();
+ });
+
+ test('parseInvalidKey', function (done) {
+ assert.throws(
+ function() {
+ var parsedConnectionString = ConnectionStringParser.parse('=value');
+ },
+ function(err) {
+ if ((err instanceof Error) && err.message === 'Missing key') {
+ return true;
+ }
+ },
+ "unexpected error"
+ );
+
+ assert.throws(
+ function() {
+ var parsedConnectionString = ConnectionStringParser.parse(' =value');
+ },
+ function(err) {
+ if ((err instanceof Error) && err.message === 'Missing key') {
+ return true;
+ }
+ },
+ "unexpected error"
+ );
+
+ done();
+ });
+
+ test('parseQuotedValues', function (done) {
+ var parsedConnectionString = ConnectionStringParser.parse('"test key"=\'value of test\'');

Nice update on the test cases here and below.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ assert.equal(parsedConnectionString['test key'], 'value of test');
+
+ var parsedConnectionString = ConnectionStringParser.parse('\'test\'="value"');
+ assert.equal(parsedConnectionString['test'], 'value');
+
+ done();
+ });
+
+ test('connectionStringWithSpecialCharacters', function (done) {
+ var parsedConnectionString = ConnectionStringParser.parse('key1=qwdwdqdw=@#!@;key2=value2');
+ assert.equal(parsedConnectionString['key1'], 'qwdwdqdw=@#!@');
+ assert.equal(parsedConnectionString['key2'], 'value2');
+
+ var parsedConnectionString = ConnectionStringParser.parse('key1="qwd;wdqdw=@#!@";key2=value2');
+ assert.equal(parsedConnectionString['key1'], 'qwd;wdqdw=@#!@');
+ assert.equal(parsedConnectionString['key2'], 'value2');
+
+ done();
+ });
+});
View
11 test/services/queue/queueservice-tests.js
@@ -450,4 +450,15 @@ suite('queueservice-tests', function () {
done();
});
});
+
+ test('storageConnectionStrings', function (done) {
+ var connectionString = 'DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=mykey';
+ var queueService = azure.createQueueService(connectionString);
+
+ assert.equal(queueService.storageAccount, 'myaccount');
+ assert.equal(queueService.storageAccessKey, 'mykey');
+ assert.equal(queueService.protocol, 'https://');
+
+ done();
+ });
});
View
13 test/services/serviceBus/servicebusservice-tests.js
@@ -1606,4 +1606,17 @@ suite('servicebusservice-tests', function () {
});
});
});
+
+ test('connectionStrings', function (done) {
+ var connectionString = 'Endpoint=sb://ablal-martvue.servicebus.windows.net/;StsEndpoint=https://ablal-martvue-sb.accesscontrol.windows.net;SharedSecretIssuer=owner;SharedSecretValue=value';
+
+ var serviceBusService = azure.createServiceBusService(connectionString);
+ assert.equal(serviceBusService.host, 'servicebus.windows.net');
+ assert.equal(serviceBusService.namespace, 'ablal-martvue');
+ assert.equal(serviceBusService.issuer, 'owner');
+ assert.equal(serviceBusService.accessKey, 'value');
+ assert.equal(serviceBusService.acsNamespace, 'ablal-martvue-sb');
+
+ done();
+ });
});
View
11 test/services/table/tableservice-tests.js
@@ -766,4 +766,15 @@ suite('tableservice-tests', function () {
});
});
});
+
+ test('storageConnectionStrings', function (done) {
+ var connectionString = 'DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=mykey';
+ var tableService = azure.createTableService(connectionString);
+
+ assert.equal(tableService.storageAccount, 'myaccount');
+ assert.equal(tableService.storageAccessKey, 'mykey');
+ assert.equal(tableService.protocol, 'https://');
+
+ done();
+ });
});
View
1  test/testlist.txt
@@ -7,6 +7,7 @@ services/blob/sharedaccesssignature-tests.js
services/blob/sharedkey-tests.js
services/blob/sharedkeylite-tests.js
services/blob/filters-tests.js
+services/core/connectionstringparser-tests.js
services/core/serviceclient-tests.js
services/core/exponentialretrypolicyfilter-tests.js
services/core/linearretrypolicyfilter-tests.js
Something went wrong with that request. Please try again.