-
Notifications
You must be signed in to change notification settings - Fork 1.4k
[core-client] Bugfixes for unblocking data-tables #12547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
95f2979
3d35c78
0dd0758
2f0220e
49b381c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,7 +34,7 @@ export function getRequestUrl( | |
| if (isAbsoluteUrl(path)) { | ||
| requestUrl = path; | ||
| } else { | ||
| requestUrl = appendPath(requestUrl, operationSpec.path); | ||
| requestUrl = appendPath(requestUrl, path); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -87,21 +87,27 @@ function isAbsoluteUrl(url: string): boolean { | |
| return url.includes("://"); | ||
| } | ||
|
|
||
| function appendPath(url: string, path?: string): string { | ||
| let result = url; | ||
| let toAppend = path; | ||
| if (toAppend) { | ||
| if (!result.endsWith("/")) { | ||
| result = `${result}/`; | ||
| } | ||
| function appendPath(url: string, pathToAppend?: string): string { | ||
| if (!pathToAppend) { | ||
| return url; | ||
| } | ||
|
|
||
| if (toAppend.startsWith("/")) { | ||
| toAppend = toAppend.substring(1); | ||
| } | ||
| const parsedUrl = new URL(url); | ||
| let newPath = parsedUrl.pathname; | ||
|
|
||
| result = result + toAppend; | ||
| if (!newPath.endsWith("/")) { | ||
| newPath = `${newPath}/`; | ||
| } | ||
| return result; | ||
|
|
||
| if (pathToAppend.startsWith("/")) { | ||
| pathToAppend = pathToAppend.substring(1); | ||
| } | ||
|
|
||
| newPath = newPath + pathToAppend; | ||
|
|
||
| parsedUrl.pathname = newPath; | ||
|
|
||
| return parsedUrl.toString(); | ||
| } | ||
|
|
||
| function calculateQueryParameters( | ||
|
|
@@ -176,17 +182,41 @@ function calculateQueryParameters( | |
| return result; | ||
| } | ||
|
|
||
| function simpleParseQueryParams(queryString: string): Array<[string, string]> { | ||
xirzec marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (!queryString || queryString[0] !== "?") { | ||
| return []; | ||
| } | ||
|
|
||
| // remove the leading ? | ||
| queryString = queryString.slice(1); | ||
|
|
||
| const pairs = queryString.split("&"); | ||
|
|
||
| return pairs.map((pair) => { | ||
| const [name, value] = pair.split("=", 2); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: this should be equivalent to return pairs.map((pair) => pari.split("=", 2))
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did it this way originally, but TS isn't smart enough to know the second parameter limits the size of the result and makes it into a 2 tuple, so it complains:
|
||
| return [name, value]; | ||
| }); | ||
| } | ||
|
|
||
| function appendQueryParams(url: string, queryParams: Map<string, string | string[]>): string { | ||
| if (queryParams.size === 0) { | ||
| return url; | ||
| } | ||
|
|
||
| const parsedUrl = new URL(url); | ||
|
|
||
| const combinedParams = new Map<string, string | string[]>(queryParams); | ||
| // QUIRK: parsedUrl.searchParams will have their name/value pairs decoded, which | ||
| // can change their meaning to the server, such as in the case of a SAS signature. | ||
| // To avoid accidentally un-encoding a query param, we parse the key/values ourselves | ||
| const existingParams = simpleParseQueryParams(parsedUrl.search); | ||
| const combinedParams = new Map<string, string | string[]>(existingParams); | ||
|
|
||
| for (const [name, value] of parsedUrl.searchParams) { | ||
| for (const [name, value] of queryParams) { | ||
| const existingValue = combinedParams.get(name); | ||
| if (Array.isArray(existingValue)) { | ||
| existingValue.push(value); | ||
| existingValue.push(...value); | ||
| } else if (existingValue) { | ||
| combinedParams.set(name, [existingValue, value]); | ||
| combinedParams.set(name, [existingValue, ...value]); | ||
| } else { | ||
| combinedParams.set(name, value); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT license. | ||
|
|
||
| import { assert } from "chai"; | ||
| import { getRequestUrl } from "../src/urlHelpers"; | ||
| import { OperationSpec, OperationURLParameter, createSerializer } from "../src"; | ||
|
|
||
| describe("getRequestUrl", function() { | ||
| const urlParameter: OperationURLParameter = { | ||
| parameterPath: "url", | ||
| mapper: { | ||
| serializedName: "url", | ||
| required: true, | ||
| xmlName: "url", | ||
| type: { | ||
| name: "String" | ||
| } | ||
| }, | ||
| skipEncoding: true | ||
| }; | ||
|
|
||
| const tableParameter: OperationURLParameter = { | ||
| parameterPath: "table", | ||
| mapper: { | ||
| serializedName: "table", | ||
| required: true, | ||
| xmlName: "table", | ||
| type: { | ||
| name: "String" | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| const serializer = createSerializer({}, false); | ||
|
|
||
| const operationSpec: OperationSpec = { | ||
| path: "/Tables('{table}')", | ||
| httpMethod: "DELETE", | ||
| responses: {}, | ||
| urlParameters: [urlParameter, tableParameter], | ||
| serializer | ||
| }; | ||
|
|
||
| it("should handle nested replacements", function() { | ||
| const result = getRequestUrl( | ||
| "{url}", | ||
| operationSpec, | ||
| { table: "TestTable" }, | ||
| { url: "https://test.com" } | ||
| ); | ||
| assert.strictEqual(result, "https://test.com/Tables('TestTable')"); | ||
| }); | ||
|
|
||
| it("should handle query parameters on the base url", function() { | ||
| const result = getRequestUrl( | ||
| "{url}", | ||
| operationSpec, | ||
| { table: "TestTable" }, | ||
| { url: "https://test.com?superSecretKey=awesome" } | ||
| ); | ||
| assert.strictEqual(result, "https://test.com/Tables('TestTable')?superSecretKey=awesome"); | ||
| }); | ||
|
|
||
| it("should not modify needlessly encoded query parameters", function() { | ||
| const specWithQueryParams: OperationSpec = { | ||
| ...operationSpec, | ||
| queryParameters: [ | ||
| { | ||
| parameterPath: "extraValue", | ||
| mapper: { type: { name: "String" }, serializedName: "extraValue", required: true }, | ||
| skipEncoding: true | ||
| } | ||
| ] | ||
| }; | ||
| const result = getRequestUrl( | ||
| "{url}", | ||
| specWithQueryParams, | ||
| { table: "TestTable", extraValue: "%27blah%27" }, | ||
| { url: "https://test.com?superSecretKey=Qai%2B4%2FIM%3D" } | ||
| ); | ||
| assert.strictEqual( | ||
| result, | ||
| "https://test.com/Tables('TestTable')?superSecretKey=Qai%2B4%2FIM%3D&extraValue=%27blah%27" | ||
| ); | ||
| }); | ||
| }); |
Uh oh!
There was an error while loading. Please reload this page.