Skip to content

Commit 96fe07e

Browse files
authored
[Tables] Fix docs and case-insensitive ConnectionString (Azure#13954)
* Fix docs and case-insensitive CS * Hide top query option * Keep default empty object * address feedback * Fix connection string * test cs with = in value
1 parent 0941b23 commit 96fe07e

File tree

3 files changed

+54
-14
lines changed

3 files changed

+54
-14
lines changed

sdk/tables/data-tables/src/TableClient.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ export class TableClient {
272272
return this;
273273
},
274274
byPage: (settings) => {
275-
const pageOptions = {
275+
const pageOptions: InternalListTableEntitiesOptions = {
276276
...options,
277277
queryOptions: { ...options.queryOptions, top: settings?.maxPageSize }
278278
};
@@ -570,10 +570,11 @@ export class TableClient {
570570
}
571571
}
572572

573+
type InternalQueryOptions = TableEntityQueryOptions & { top?: number };
574+
interface InternalListTableEntitiesOptions extends ListTableEntitiesOptions {
575+
queryOptions?: InternalQueryOptions;
576+
}
577+
573578
function isInternalClientOptions(options: any): options is InternalBatchClientOptions {
574579
return Boolean(options.innerBatchRequest);
575580
}
576-
577-
type InternalListTableEntitiesOptions = ListTableEntitiesOptions & {
578-
queryOptions?: TableEntityQueryOptions & { top?: number };
579-
};

sdk/tables/data-tables/src/utils/connectionString.ts

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,7 @@ export function extractConnectionStringParts(connectionString: string): Connecti
5454
// (The methods that use `extractConnectionStringParts` expect the url to not have `/` at the end)
5555
tableEndpoint = tableEndpoint.endsWith("/") ? tableEndpoint.slice(0, -1) : tableEndpoint;
5656

57-
const isAccountConnectionString =
58-
connectionString.search("DefaultEndpointsProtocol=") !== -1 &&
59-
connectionString.search("AccountKey=") !== -1;
60-
61-
if (isAccountConnectionString) {
57+
if (isAccountConnectionString(connectionString)) {
6258
return getAccountConnectionString(
6359
getValueInConnString(connectionString, "AccountName"),
6460
getValueInConnString(connectionString, "AccountKey"),
@@ -71,6 +67,17 @@ export function extractConnectionStringParts(connectionString: string): Connecti
7167
}
7268
}
7369

70+
/**
71+
* Checks whether a connection string is an Account Connection string or not
72+
*/
73+
function isAccountConnectionString(connectionString: string) {
74+
const lowercaseConnectionString = connectionString.toLowerCase();
75+
return (
76+
lowercaseConnectionString.search("defaultendpointsprotocol=") !== -1 &&
77+
lowercaseConnectionString.search("accountkey=") !== -1
78+
);
79+
}
80+
7481
function getSASConnectionString(connectionString: string, tableEndpoint: string): ConnectionString {
7582
const accountName = getAccountNameFromUrl(tableEndpoint);
7683
const accountSas = getValueInConnString(connectionString, "SharedAccessSignature");
@@ -95,15 +102,32 @@ function getValueInConnString(
95102
| "EndpointSuffix"
96103
| "SharedAccessSignature"
97104
): string {
105+
const searchKey = argument.toLowerCase();
98106
const elements = connectionString.split(";");
99107
for (const element of elements) {
100-
if (element.trim().startsWith(argument)) {
101-
return element.trim().match(argument + "=(.*)")![1];
108+
const trimmedElement = element.trim();
109+
const [elementKey, value] = getValuePair(trimmedElement);
110+
const key = elementKey.toLowerCase();
111+
if (key === searchKey) {
112+
return value;
102113
}
103114
}
104115
return "";
105116
}
106117

118+
function getValuePair(kvp: string): string[] {
119+
// If the string is not in kvp format <key>=<valye> return an empty array
120+
if (!kvp || kvp.indexOf("=") === -1) {
121+
return [];
122+
}
123+
// Get the substring before the first '='
124+
const key = kvp.substr(0, kvp.indexOf("="));
125+
// Get the substring after the first '='
126+
const value = kvp.substr(kvp.indexOf("=") + 1);
127+
128+
return [key, value];
129+
}
130+
107131
/**
108132
* Extracts account name from the url
109133
* @param url - URL to extract the account name from

sdk/tables/data-tables/test/unit/utils.spec.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ describe("Utility Helpers", () => {
2929
});
3030
});
3131

32+
it("should handle case-insensitive string without TableEndpoint", () => {
33+
const validConnectionString =
34+
"deFaultEndpointsPROTOcol=https;accoUNTNAme=testaccount;ACCOUNTkey=REDACTED;endPOintSuffiX=core.windows.net";
35+
const result = extractConnectionStringParts(validConnectionString);
36+
assert.deepEqual(result, {
37+
accountName: "testaccount",
38+
accountKey: Buffer.from([68, 64, 192, 9, 49, 3]),
39+
kind: "AccountConnString",
40+
url: "https://testaccount.table.core.windows.net"
41+
});
42+
});
43+
3244
it("should handle connection string with TableEndpoint", () => {
3345
const validConnectionString =
3446
"DefaultEndpointsProtocol=https;AccountName=testaccount;AccountKey=REDACTED;EndpointSuffix=core.windows.net;TableEndpoint=https://myAccount.table.core.windows.net/";
@@ -66,9 +78,12 @@ describe("Utility Helpers", () => {
6678

6779
it("should handle format 'protocol://accountName.table.endpointSuffix'", () => {
6880
const validSAS =
69-
"BlobEndpoint=https://teststorageaccount.blob.core.windows.net/;QueueEndpoint=https://teststorageaccount.queue.core.windows.net/;FileEndpoint=https://teststorageaccount.file.core.windows.net/;TableEndpoint=https://teststorageaccount.table.core.windows.net/;SharedAccessSignature=REDACTED";
81+
"BlobEndpoint=https://teststorageaccount.blob.core.windows.net/;QueueEndpoint=https://teststorageaccount.queue.core.windows.net/;FileEndpoint=https://teststorageaccount.file.core.windows.net/;TableEndpoint=https://teststorageaccount.table.core.windows.net/;SharedAccessSignature=sv=2020-02-10&ss=bfqt";
7082
const connectionStringParts = extractConnectionStringParts(validSAS);
71-
assert.deepEqual(connectionStringParts, expectedConenctionStringParts);
83+
assert.deepEqual(connectionStringParts, {
84+
...expectedConenctionStringParts,
85+
accountSas: "sv=2020-02-10&ss=bfqt"
86+
});
7287
});
7388

7489
it("should handle IPv4/6 format ", () => {

0 commit comments

Comments
 (0)