Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a00a662

Browse files
authored
[core-client] Skip parameter overwriting if the path is absolute (Azure#18310)
* Skip parameter overwriting if the path is absolute * add a comment * update changelog * update TA recordings * address feedback
1 parent f26bb90 commit a00a662

File tree

5 files changed

+280
-137
lines changed

5 files changed

+280
-137
lines changed

sdk/core/core-client/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
### Bugs Fixed
1010

11+
- Skip query parameter replacement for absolute URLs. [PR #18310](https://github.com/Azure/azure-sdk-for-js/pull/18310)
12+
1113
### Other Changes
1214

1315
## 1.3.1 (2021-09-30)

sdk/core/core-client/src/urlHelpers.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ export function getRequestUrl(
2424
fallbackObject
2525
);
2626

27+
let isAbsolutePath = false;
28+
2729
let requestUrl = replaceAll(baseUri, urlReplacements);
2830
if (operationSpec.path) {
2931
const path = replaceAll(operationSpec.path, urlReplacements);
@@ -32,6 +34,7 @@ export function getRequestUrl(
3234
// ignore the baseUri.
3335
if (isAbsoluteUrl(path)) {
3436
requestUrl = path;
37+
isAbsolutePath = true;
3538
} else {
3639
requestUrl = appendPath(requestUrl, path);
3740
}
@@ -42,7 +45,13 @@ export function getRequestUrl(
4245
operationArguments,
4346
fallbackObject
4447
);
45-
requestUrl = appendQueryParams(requestUrl, queryParams, sequenceParams);
48+
/**
49+
* Notice that this call sets the `noOverwrite` parameter to true if the `requestUrl`
50+
* is an absolute path. This ensures that existing query parameter values in `requestUrl`
51+
* do not get overwritten. On the other hand when `requestUrl` is not absolute path, it
52+
* is still being built so there is nothing to overwrite.
53+
*/
54+
requestUrl = appendQueryParams(requestUrl, queryParams, sequenceParams, isAbsolutePath);
4655

4756
return requestUrl;
4857
}
@@ -237,7 +246,8 @@ function simpleParseQueryParams(queryString: string): Map<string, string | strin
237246
export function appendQueryParams(
238247
url: string,
239248
queryParams: Map<string, string | string[]>,
240-
sequenceParams: Set<string>
249+
sequenceParams: Set<string>,
250+
noOverwrite: boolean = false
241251
): string {
242252
if (queryParams.size === 0) {
243253
return url;
@@ -261,13 +271,14 @@ export function appendQueryParams(
261271
existingValue.push(value);
262272
}
263273
} else if (existingValue) {
264-
let newValue = value;
265274
if (Array.isArray(value)) {
266275
value.unshift(existingValue);
267276
} else if (sequenceParams.has(name)) {
268-
newValue = [existingValue, value];
277+
combinedParams.set(name, [existingValue, value]);
278+
}
279+
if (!noOverwrite) {
280+
combinedParams.set(name, value);
269281
}
270-
combinedParams.set(name, newValue);
271282
} else {
272283
combinedParams.set(name, value);
273284
}

sdk/core/core-client/test/serviceClient.spec.ts

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ import {
1515
CompositeMapper,
1616
OperationSpec,
1717
serializationPolicy,
18-
FullOperationResponse
18+
FullOperationResponse,
19+
OperationQueryParameter
1920
} from "../src";
2021
import {
2122
createHttpHeaders,
2223
createEmptyPipeline,
2324
HttpClient,
24-
createPipelineRequest
25+
createPipelineRequest,
26+
PipelineRequest
2527
} from "@azure/core-rest-pipeline";
2628

2729
import {
@@ -1362,6 +1364,65 @@ describe("ServiceClient", function() {
13621364
assert.include(error.message, "cannot be null or undefined");
13631365
}
13641366
});
1367+
1368+
it("should not replace existing queries in request URLs", async function() {
1369+
let request: PipelineRequest;
1370+
const topQueryParam: OperationQueryParameter = {
1371+
parameterPath: ["options", "top"],
1372+
mapper: {
1373+
defaultValue: 20,
1374+
constraints: {
1375+
InclusiveMaximum: 50,
1376+
InclusiveMinimum: 1
1377+
},
1378+
serializedName: "$top",
1379+
type: {
1380+
name: "Number"
1381+
}
1382+
}
1383+
};
1384+
const skipQueryParam: OperationQueryParameter = {
1385+
parameterPath: ["options", "skip"],
1386+
mapper: {
1387+
defaultValue: 0,
1388+
constraints: {
1389+
InclusiveMinimum: 0
1390+
},
1391+
serializedName: "$skip",
1392+
type: {
1393+
name: "Number"
1394+
}
1395+
}
1396+
};
1397+
const operationSpec: OperationSpec = {
1398+
path: "https://example.com/path?$skip=10",
1399+
queryParameters: [topQueryParam, skipQueryParam],
1400+
httpMethod: "GET",
1401+
responses: {
1402+
200: {
1403+
bodyMapper: { type: { name: "String" } }
1404+
}
1405+
},
1406+
baseUrl: "http://example.com",
1407+
serializer: createSerializer()
1408+
};
1409+
1410+
const client = new ServiceClient({
1411+
httpClient: {
1412+
sendRequest: (req) => {
1413+
request = req;
1414+
return Promise.resolve({
1415+
request: req,
1416+
status: 200,
1417+
headers: createHttpHeaders(),
1418+
bodyAsText: `"dummy string"`
1419+
});
1420+
}
1421+
}
1422+
});
1423+
await client.sendOperationRequest<string>({ options: { top: 10 } as any }, operationSpec);
1424+
assert.equal(request!.url, "https://example.com/path?$skip=10&$top=10");
1425+
});
13651426
});
13661427

13671428
async function testSendOperationRequest(

0 commit comments

Comments
 (0)