autorest.typescript icon indicating copy to clipboard operation
autorest.typescript copied to clipboard

Paginated operations don't work properly if query param names in nextLink are URL-encoded

Open peolivei2 opened this issue 2 years ago • 3 comments

Repro steps:

  • Generate client from spec that has a paginated operation with next link
  • Have the pagination operation have a dollar-prefixed query parameter, such as $top
  • Invoke the paginated operation, as in the example below:
  const it = await client.myResources.list({ top: 1 });
  const results = [];

  for await (const result of it) {
      results.push(result);
  }
  • While resolving the iterator, the lib will make a first call to the server containing the $top parameter: GET https://example.com/myResources?$top=1
  • The server will respond with something like the following, with $top having the $ encoded:
{
  "value": [{}]
  "nextLink": "https://example.com/myResources?%24top=1" 
}
  • The lib will then issue a next call, appending the original $top again at the end of the request, which causes a failure in the server because the $top parameter is being defined twice: GET https://example.com/myResources?%24top=1&$top=1

Note: if the server does not return the param name encoded, the lib is able to dedupe the params correctly and send only one value as expected. However, the URL search params standard mandated the names to be encoded (https://url.spec.whatwg.org/#urlsearchparams).

Examples:

  • Encoded parameters in the nextLink response will cause duplicate params: encoded

  • If the params are not encoded in the nextLink, the link works as expected: decoded

peolivei2 avatar Jul 20 '22 00:07 peolivei2

@xirzec Looks like this is a data plane SDK issue ?

qiaozha avatar Aug 31 '22 07:08 qiaozha

Looks related to https://github.com/Azure/azure-sdk-for-js/issues/20420

deyaaeldeen avatar Aug 31 '22 18:08 deyaaeldeen

We should avoid URLSearchParams when constructing query param strings as it formats them as application/x-www-form-urlencoded which is not the same as how query strings get encoded in normal URLs.

Interestingly, it seems like the server is doing the unnecessary encoding in this case. It doesn't appear that the URL constructor parses this by default:

image

So we'd have to reconstruct the query string by iterating over url.searchParams.entries ourselves and re-encode it correctly. My biggest concern is this might cause us to un-encode values that other services expect to not be unwrapped.

I think my position on this is the server shouldn't be sending us a nextLink it is not prepared to receive requested verbatim.

xirzec avatar Aug 31 '22 19:08 xirzec

@xirzec Does this PR https://github.com/Azure/autorest.typescript/pull/1661 fix the issue here ?

qiaozha avatar Nov 30 '22 07:11 qiaozha

@xirzec Does this PR #1661 fix the issue here ?

The PR I believe uses the original link as sent by the service, which is the expected behavior.

xirzec avatar Aug 03 '23 19:08 xirzec