Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Conversation

zhiyuanliang-ms
Copy link
Member

Why this PR?

Adds a new pipeline to update the query params to make sure they are all lowercase and in alphabetical order. This is required for support of Azure Front Door as a CDN.

@Copilot Copilot AI review requested due to automatic review settings October 10, 2025 02:45
@github-actions github-actions bot added the App Configuration Azure.ApplicationModel.Configuration label Oct 10, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds a new query parameter normalization pipeline policy to the Azure App Configuration SDK. The policy ensures query parameters are lowercase and sorted alphabetically to support Azure Front Door as a CDN.

  • Implements a new QueryParamPolicy that transforms query parameters to lowercase and sorts them alphabetically
  • Adds comprehensive test coverage for various query parameter scenarios including duplicates and encoded values
  • Removes the unused ApiVersionPolicy class as part of cleanup

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
QueryParamPolicy.cs New pipeline policy that normalizes query parameters by converting to lowercase and sorting alphabetically
QueryParamPolicyTests.cs Comprehensive test suite covering lowercase conversion, sorting, duplicate handling, and value preservation
ConfigurationClient.cs Integration of the new QueryParamPolicy into the HTTP pipeline
ApiVersionPolicy.cs Removal of unused ApiVersionPolicy class
assets.json Version tag update for the changes

queryString = queryString.Substring(1);
}

// Separate out any hash fragment so we can keep it verbatim
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 we should do queryString = Uri.Query + Uri.Fragment.
That saves us from parsing and reconstructing the fragment part.

Copy link
Member Author

@zhiyuanliang-ms zhiyuanliang-ms Oct 13, 2025

Choose a reason for hiding this comment

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

There is no Request.Uri.Fragment https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/RequestUriBuilder.cs

I need to convert it to Uri first:

Uri originalUrl = message.Request.Uri.ToUri();


string baseUrl = beforeHash.Substring(0, beforeHash.IndexOf('?'));

// We don't use HttpUtility.ParseQueryString as it will process the values
Copy link
Member

Choose a reason for hiding this comment

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

We can still use HttpUtility.ParseQueryString and access the duplicate query params by calling NameValueCollection.GetValues on the parsed values.
Eg:

var url = new Uri("https://www.contoso.com/kv?key=Foo&label=My#Label&tags=t2=v2&tags=t1=v1");
var queryString = url.Query + url.Fragment;

var paramsCollection = HttpUtility.ParseQueryString(queryString);

foreach (var key in paramsCollection.AllKeys)
{
    var values = paramsCollection.GetValues(key);
    foreach (var val in values)
    {
        Console.WriteLine($"{key} = {val}");
    }
}

Output:

key = Foo
label = My#Label
tags = t2=v2
tags = t1=v1

Copy link
Member Author

Choose a reason for hiding this comment

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

Should we distinguish these two cases ?key= and ?key? If yes, then we must parse the query by ourselves. Any url parsing tool will treat ?key as key: "", so when we reconstruct the query, we will add the =

{
public class QueryParamPolicyTests : SyncAsyncPolicyTestBase
{
public QueryParamPolicyTests(bool isAsync) : base(isAsync) { }
Copy link
Member

Choose a reason for hiding this comment

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

I like it - nice and simple tests. Can you add more test cases?
Mix and match with $select, null values, different endpoints (snapshot case), etc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

App Configuration Azure.ApplicationModel.Configuration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.