Skip to content
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

Check is value is undefined in appendQueryParams #18621

Merged
merged 5 commits into from
Nov 11, 2021

Conversation

sarangan12
Copy link
Member

@qiaozha has recently reported that during the testing of beginCreateOrUpdateAndWait operation in the @azure/arm-iothub library. During the testing, the code is erroring out with the message:

(node:17412) UnhandledPromiseRejectionWarning: TypeError: value is not iterable
    at appendQueryParams (C:\Users\sarajama\Projects\temp\node_modules\@azure\core-client\dist\index.js:1343:40)

On analysis, I found that the value is undefined which is causing the error. Adding a check resolves the issue.

@xirzec Could you please review and approve the PR? TIA

// QUIRK: If we get an array of values, include multiple key/value pairs
for (const subValue of value) {
searchPieces.push(`${name}=${subValue}`);
if (value) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type for value is either string | string[] so I think the function is correct in handling it as such only. Could you check which caller puts an undefined in a map that is supposed to hold string | string[] only?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@deyaaeldeen If you look at the combinedParams object it will look as:

{
  'api-version' => '2021-07-01-preview',
  'operationSource' => 'other',
  'asyncinfo' => undefined
}

As you can see, the asyncinfo is undefined which is causing this issue. The URL looks like https://management.azure.com/subscriptions/3755ce94-6c61-4b5c-b0b1-b2ce86fc540f/providers/Microsoft.Devices/locations/eastus/operationResults/aWQ9b3NfaWhfNWZiNWU3OTEtZGJmOS00ZjFiLThkY2EtYzBiOTJmMTI2MjIxO3JlZ2lvbj1lYXN0dXM=?api-version=2021-07-01-preview&operationSource=other&asyncinfo

Copy link
Member

@deyaaeldeen deyaaeldeen Nov 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ops sorry, I was confused. I thought the value came from queryParams map not from combinedParams. Ok, I looked at combinedParams type and it is Map<string, string | string[]> which should not still include undefined in it. Since simpleParseQueryParams is the one that produces it, so it is the one that needs to be updated. It splits each param on = as follows: const [name, value] = pair.split("=", 2); without validating that value is actually defined even though the type does not allow for undefined. There're two options here, either relax the type to allow for undefined or validate value to always be defined. I think the former option makes sense here because we would like to preserve whatever is in the URL but I could be wrong.

@xirzec any thoughts on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the value is undefined, shouldn't we just push ${name}=?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little torn. I want to say "of course nobody would want a query param with no value!" but as soon as I say that I worry some service of ours indeed would expect that.

I'm leaning towards doing Jeremy's suggestion, but in that case to Deya's point we should update the map to include | undefined as one of the possible values.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the value is undefined, shouldn't we just push ${name}=?

The original URL in Sarangan's example does not have the = sign, so I think we will have to preserve this which means distinguishing between value being undefined and being an empty string.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I have changed the code to include undefined as a possible return value during parsing and changed the code

Copy link
Member

@xirzec xirzec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work finding this one!

sdk/core/core-client/src/urlHelpers.ts Outdated Show resolved Hide resolved
// QUIRK: If we get an array of values, include multiple key/value pairs
for (const subValue of value) {
searchPieces.push(`${name}=${subValue}`);
if (value) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little torn. I want to say "of course nobody would want a query param with no value!" but as soon as I say that I worry some service of ours indeed would expect that.

I'm leaning towards doing Jeremy's suggestion, but in that case to Deya's point we should update the map to include | undefined as one of the possible values.

Copy link
Member

@xirzec xirzec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update! One remark on the new behavior and I would love if we could add a test or two. 👍

Comment on lines +299 to +300
} else {
searchPieces.push(`${name}=${value}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this will cause undefined to show up as name=undefined in the query string, which seems to match how URLSearchParams handles this:

image

I'm fine with it, but can we test this change on the service that was impacted by the linked issue before merging?

Copy link
Member

@deyaaeldeen deyaaeldeen Nov 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the service did not like this, I think we will need to do:

Suggested change
} else {
searchPieces.push(`${name}=${value}`);
} else if (value === undefined) {
searchPieces.push(name);
} else {
searchPieces.push(`${name}=${value}`);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last else should be unreachable, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right, we could just throw an error there just in case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this will cause undefined to show up as name=undefined in the query string, which seems to match how URLSearchParams handles this:

image

I'm fine with it, but can we test this change on the service that was impacted by the linked issue before merging?

Yes. I have tested the changes with the actual iothub service that was causing this issue. It works fine. Thanks

@sarangan12 sarangan12 merged commit 0cc6b97 into Azure:main Nov 11, 2021
@ramya-rao-a
Copy link
Contributor

@sarangan12 Please create a PR with the changelog entry for the changes in this PR. We will be releasing core-client this week
cc @deyaaeldeen

@sarangan12
Copy link
Member Author

@sarangan12 Please create a PR with the changelog entry for the changes in this PR. We will be releasing core-client this week cc @deyaaeldeen

Done. #18851

deyaaeldeen pushed a commit to deyaaeldeen/azure-sdk-for-js that referenced this pull request Nov 29, 2021
* Check is value is undefined in appendQueryParams

* Minor change

* Response to PR comments

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

Co-authored-by: Jeff Fisher <xirzec@xirzec.com>

* Minor refactor

Co-authored-by: Jeff Fisher <xirzec@xirzec.com>
deyaaeldeen added a commit that referenced this pull request Dec 2, 2021
* Check is value is undefined in appendQueryParams (#18621)

* Check is value is undefined in appendQueryParams

* Minor change

* Response to PR comments

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

Co-authored-by: Jeff Fisher <xirzec@xirzec.com>

* Minor refactor

Co-authored-by: Jeff Fisher <xirzec@xirzec.com>

* Post release automated changes for core releases (#18358)

Post release automated changes for azure-core-client

* Remove the word experimental in readmes (#18773)

We have the word "Experimental" in the titles in the readme files for our core packages.

My guess is that we started with this when we were working on core v2, forgot to remove it when core v2 went GA and all our newer core packages from them did a copy/paste :)

@xirzec, @joheredi Am I missing something?

* Update Changelog to include query param check (#18851)

* Update Changelog to include query param check

* Update sdk/core/core-client/CHANGELOG.md

Co-authored-by: Deyaaeldeen Almahallawi <dealmaha@microsoft.com>

Co-authored-by: Deyaaeldeen Almahallawi <dealmaha@microsoft.com>

* fix reinstall native dependency (#18582)

* Generate absolute path for symlink to reinstall native dependency

Co-authored-by: Sarangan Rajamanickam <sarajama@microsoft.com>
Co-authored-by: Jeff Fisher <xirzec@xirzec.com>
Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com>
Co-authored-by: Ramya Rao <ramya.rao.a@outlook.com>
Co-authored-by: praveenkuttappan <55455725+praveenkuttappan@users.noreply.github.com>
deyaaeldeen added a commit that referenced this pull request Dec 2, 2021
…) (#18925)

* Check is value is undefined in appendQueryParams (#18621)

* Check is value is undefined in appendQueryParams

* Minor change

* Response to PR comments

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

Co-authored-by: Jeff Fisher <xirzec@xirzec.com>

* Minor refactor

Co-authored-by: Jeff Fisher <xirzec@xirzec.com>

* Post release automated changes for core releases (#18358)

Post release automated changes for azure-core-client

* Remove the word experimental in readmes (#18773)

We have the word "Experimental" in the titles in the readme files for our core packages.

My guess is that we started with this when we were working on core v2, forgot to remove it when core v2 went GA and all our newer core packages from them did a copy/paste :)

@xirzec, @joheredi Am I missing something?

* Update Changelog to include query param check (#18851)

* Update Changelog to include query param check

* Update sdk/core/core-client/CHANGELOG.md

Co-authored-by: Deyaaeldeen Almahallawi <dealmaha@microsoft.com>

Co-authored-by: Deyaaeldeen Almahallawi <dealmaha@microsoft.com>

* fix reinstall native dependency (#18582)

* Generate absolute path for symlink to reinstall native dependency

Co-authored-by: Sarangan Rajamanickam <sarajama@microsoft.com>
Co-authored-by: Jeff Fisher <xirzec@xirzec.com>
Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com>
Co-authored-by: Ramya Rao <ramya.rao.a@outlook.com>
Co-authored-by: praveenkuttappan <55455725+praveenkuttappan@users.noreply.github.com>

Co-authored-by: Sarangan Rajamanickam <sarajama@microsoft.com>
Co-authored-by: Jeff Fisher <xirzec@xirzec.com>
Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com>
Co-authored-by: Ramya Rao <ramya.rao.a@outlook.com>
Co-authored-by: praveenkuttappan <55455725+praveenkuttappan@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants