Skip to content

QueryStringEnumerable API #33910

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

Merged
11 commits merged into from
Jun 29, 2021
Merged

QueryStringEnumerable API #33910

11 commits merged into from
Jun 29, 2021

Conversation

SteveSandersonMS
Copy link
Member

@SteveSandersonMS SteveSandersonMS commented Jun 28, 2021

Implements #33840, hopefully covering the suggestions already raised there.

Fixing an inconsistency (or not?)

There was a weird inconsistency in the parsing behavior regarding whitespace.

  • QueryHelpers.ParseQuery previously trimmed any leading char.IsWhiteSpace characters from the key (but not any trailing ones from the key, and not either leading or trailing ones from the value)
  • QueryFeature's querystring parser did not do that (it retained whitespace at both ends of key and value)

The behavior in QueryHelpers.ParseQuery doesn't really make sense to me. Why only trim leading and not trailing? Why do none of the unit tests cover this? Why didn't QueryFeature have the same behavior? Also note that it was done at the cost of stepping through a potentially 8kb-long string character-by-character.

To clean this up, and since the logic in QueryFeature looks newer, I've standardized on the don't-trim behavior in the new common logic.

Does anyone know why the weird sometimes-trimming behavior existed before? Apparently it's been there for 7 years and is too far back to even see the original commit by following normal GitHub links. I'm happy to put it back if there's a reason, or if this raises a serious concern about breaking. If we are putting it back, do we want to retain the inconsistency between QueryHelpers and QueryFeature, or should QueryFeature also get this odd behavior? Or should we regard the change as breaking and do an announcement?

Previously, the logic would trim leading whitespace from keys, but only for keys with a value. I don't know why we did this, why we didn't trim trailing whitespace, and why we didn't do it for keys with empty value. Also it was inconsistent - we did it in QueryHelper, but not in QueryFeature.
@@ -13,6 +13,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="$(SharedSourceRoot)QueryStringEnumerable.cs" />
Copy link
Member Author

Choose a reason for hiding this comment

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

The reason for shared-source is that, in a PR coming very soon to a repo near you, I'll be using QueryStringEnumerable as an internal API inside Microsoft.AspNetCore.Components. That package does not have a dependency on WebUtilities, and doesn't want to have one, since it's not web-specific and most of the baggage brought with WebUtilities would not be applicable.

@Tratcher
Copy link
Member

A query string shouldn't have any white space in it prior to un-escaping keys and values.

This code goes all the way back to Katana where the same parser was shared across a few similar formats like query, form, etc.:
https://github.com/aspnet/AspNetKatana/blob/fae38fae683bb0977bcaf7c3ffce244aced82135/src/Microsoft.Owin/Infrastructure/OwinHelpers.cs#L557

We've since split each of those up into their own parsers, but apparently there were leftovers.

@SteveSandersonMS
Copy link
Member Author

A query string shouldn't have any white space in it prior to un-escaping keys and values.

Can you clarify this point? Are you saying the scenario is not applicable so we don't need to care about it? Or are you saying we must trim whitespace (and if so, why is it OK not to trim trailing whitespace, and why doesn't the QueryFeature code do that?)

I'm guessing you mean the scenario isn't applicable, presumably because HTTP doesn't have a way to represent unencoded whitespace in the request line. Is that right?

Copy link
Member

@Tratcher Tratcher left a comment

Choose a reason for hiding this comment

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

Any thoughts on adding a new (extension?) method to QueryString that exposed this new enumerator? QueryString.GetEnumerator()?

@Tratcher
Copy link
Member

A query string shouldn't have any white space in it prior to un-escaping keys and values.

Can you clarify this point? Are you saying the scenario is not applicable so we don't need to care about it? Or are you saying we must trim whitespace (and if so, why is it OK not to trim trailing whitespace, and why doesn't the QueryFeature code do that?)

I'm guessing you mean the scenario isn't applicable, presumably because HTTP doesn't have a way to represent unencoded whitespace in the request line. Is that right?

It's not applicable an can be ignored because a well formed URI does not allow whitespace anywhere, they must be escaped. This isn't even an HTTP specific requirement.

@SteveSandersonMS SteveSandersonMS added the api-ready-for-review API is ready for formal API review - https://github.com/dotnet/apireviews label Jun 28, 2021
@ghost
Copy link

ghost commented Jun 28, 2021

Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:

  • The PR contains changes to the reference-assembly that describe the API change. Or, you have included a snippet of reference-assembly-style code that illustrates the API change.
  • The PR describes the impact to users, both positive (useful new APIs) and negative (breaking changes).
  • Someone is assigned to "champion" this change in the meeting, and they understand the impact and design of the change.

@pranavkm
Copy link
Contributor

  • We think DecodeName / DecodeValue are useful APIs to have. With DecodeName we can optimize for the common cases where the name does not need decoding and return the encoded value as is. For DecodeValue it's less useful in the common case, but could help in the event if the value need to be parsed (e.g. int.TryParse).

  • If we do need to share this publicly in the future, we can consider creating a M.Extensions.HttpHelperUtility package.

@pranavkm pranavkm added api-approved API was approved in API review, it can be implemented and removed api-ready-for-review API is ready for formal API review - https://github.com/dotnet/apireviews labels Jun 28, 2021
@SteveSandersonMS
Copy link
Member Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@ghost
Copy link

ghost commented Jun 29, 2021

Hello @SteveSandersonMS!

Because this pull request has the auto-merge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit 28e9223 into main Jun 29, 2021
@ghost ghost deleted the stevesa/querystringenumerable branch June 29, 2021 14:15
@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Aug 24, 2023
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-approved API was approved in API review, it can be implemented area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants