Skip to content

Commit 6c68a75

Browse files
committed
Adding a private query parsing function and more validations
1 parent b946955 commit 6c68a75

File tree

1 file changed

+82
-25
lines changed

1 file changed

+82
-25
lines changed

src/GraphRequest.ts

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export interface URLComponents {
4949
path?: string;
5050
oDataQueryParams: KeyValuePairObjectStringNumber;
5151
otherURLQueryParams: KeyValuePairObjectStringNumber;
52+
otherURLQueryStrings: string[];
5253
}
5354

5455
/**
@@ -118,6 +119,7 @@ export class GraphRequest {
118119
version: this.config.defaultVersion,
119120
oDataQueryParams: {},
120121
otherURLQueryParams: {},
122+
otherURLQueryStrings: [],
121123
};
122124
this._headers = {};
123125
this._options = {};
@@ -170,7 +172,7 @@ export class GraphRequest {
170172
// Capture query string into oDataQueryParams and otherURLQueryParams
171173
const queryParams = path.substring(queryStrPos + 1, path.length).split("&");
172174
for (const queryParam of queryParams) {
173-
this.query(queryParam);
175+
this.parseQueryParameter(queryParam);
174176
}
175177
}
176178
};
@@ -237,9 +239,87 @@ export class GraphRequest {
237239
}
238240
}
239241
}
242+
243+
if (urlComponents.otherURLQueryStrings.length !== 0) {
244+
for (const str of urlComponents.otherURLQueryStrings) {
245+
query.push(str);
246+
}
247+
}
240248
return query.length > 0 ? "?" + query.join("&") : "";
241249
}
242250

251+
/**
252+
* @private
253+
* @param queryDictionaryOrString
254+
*/
255+
private parseQueryParameter(queryDictionaryOrString: string | KeyValuePairObjectStringNumber): GraphRequest {
256+
if (typeof queryDictionaryOrString === "string") {
257+
if (queryDictionaryOrString.charAt(0) === "?") {
258+
queryDictionaryOrString = queryDictionaryOrString.substring(1, queryDictionaryOrString.length);
259+
}
260+
261+
if (queryDictionaryOrString.indexOf("&") !== -1) {
262+
const queryParams = queryDictionaryOrString.split("&");
263+
for (const str of queryParams) {
264+
this.parseQueryParamenterString(str);
265+
}
266+
} else {
267+
this.parseQueryParamenterString(queryDictionaryOrString);
268+
}
269+
} else {
270+
for (const key in queryDictionaryOrString) {
271+
if (queryDictionaryOrString.hasOwnProperty(key)) {
272+
this.setURLComponentsQueryParamater(key, queryDictionaryOrString[key]);
273+
}
274+
}
275+
}
276+
277+
return this;
278+
}
279+
280+
/**
281+
* @private
282+
* @param query
283+
*/
284+
private parseQueryParamenterString(queryParameter: string): void {
285+
/* The query key-value pair must be split on the first equals sign to avoid errors in parsing nested query parameters.
286+
Example-> "/me?$expand=home($select=city)" */
287+
if (this.isValidQueryKeyValuePair(queryParameter)) {
288+
const indexOfFirstEquals = queryParameter.indexOf("=");
289+
const paramKey = queryParameter.substring(0, indexOfFirstEquals);
290+
const paramValue = queryParameter.substring(indexOfFirstEquals + 1, queryParameter.length);
291+
this.setURLComponentsQueryParamater(paramKey, paramValue);
292+
} else {
293+
this.urlComponents.otherURLQueryStrings.push(queryParameter);
294+
}
295+
}
296+
297+
/**
298+
* @private
299+
* @param query
300+
*/
301+
private setURLComponentsQueryParamater(paramKey: string, paramValue: string | number): void {
302+
if (oDataQueryNames.indexOf(paramKey) !== -1) {
303+
const currentValue = this.urlComponents.oDataQueryParams[paramKey];
304+
const isValueAppendable = currentValue && (paramKey === "$expand" || paramKey === "$select" || paramKey === "$orderby");
305+
this.urlComponents.oDataQueryParams[paramKey] = isValueAppendable ? currentValue + "," + paramValue : paramValue;
306+
} else {
307+
this.urlComponents.otherURLQueryParams[paramKey] = paramValue;
308+
}
309+
}
310+
311+
private isValidQueryKeyValuePair(queryDictionaryOrString: string): boolean {
312+
const indexofFirstEquals = queryDictionaryOrString.indexOf("=");
313+
if (indexofFirstEquals === -1) {
314+
return false;
315+
} else {
316+
const indexofOpeningParanthesis = queryDictionaryOrString.indexOf("(");
317+
if (indexofOpeningParanthesis !== -1 && queryDictionaryOrString.indexOf("(") < indexofFirstEquals) {
318+
return false;
319+
}
320+
}
321+
return true;
322+
}
243323
/**
244324
* @private
245325
* Updates the custom headers and options for a request
@@ -494,30 +574,7 @@ export class GraphRequest {
494574
* @returns The same GraphRequest instance that is being called with
495575
*/
496576
public query(queryDictionaryOrString: string | KeyValuePairObjectStringNumber): GraphRequest {
497-
let paramKey: string;
498-
let paramValue: string | number;
499-
if (typeof queryDictionaryOrString === "string") {
500-
/* The query key-value pair must be split on the first equals sign to avoid errors in parsing nested query parameters.
501-
Example-> "/me?$expand=home($select=city)" */
502-
const indexOfFirstEquals = queryDictionaryOrString.indexOf("=");
503-
paramKey = queryDictionaryOrString.substring(0, indexOfFirstEquals);
504-
paramValue = queryDictionaryOrString.substring(indexOfFirstEquals + 1, queryDictionaryOrString.length);
505-
} else {
506-
for (const key in queryDictionaryOrString) {
507-
if (queryDictionaryOrString.hasOwnProperty(key)) {
508-
paramKey = key;
509-
paramValue = queryDictionaryOrString[key];
510-
}
511-
}
512-
}
513-
if (oDataQueryNames.indexOf(paramKey) !== -1) {
514-
const currentValue = this.urlComponents.oDataQueryParams[paramKey];
515-
const isValueAppendable = currentValue && (paramKey === "$expand" || paramKey === "$select" || paramKey === "$orderby");
516-
this.urlComponents.oDataQueryParams[paramKey] = isValueAppendable ? currentValue + "," + paramValue : paramValue;
517-
} else {
518-
this.urlComponents.otherURLQueryParams[paramKey] = paramValue;
519-
}
520-
return this;
577+
return this.parseQueryParameter(queryDictionaryOrString);
521578
}
522579

523580
/**

0 commit comments

Comments
 (0)