question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Query params start with ??

See original GitHub issue

Expected Behavior / New Feature

Query params should not start with double question marks

Actual Behavior / Motivation for New Feature

The same bug (and a solution) is mentioned in this issue: https://github.com/ThreeMammals/Ocelot/issues/555#issuecomment-436063081

Now the downstream request contains an extra question mark, which causes unexpected behaviour on the backend server, because the first query parameter name contains a question mark.

https://github.com/ThreeMammals/Ocelot/blob/develop/src/Ocelot/Request/Middleware/DownstreamRequest.cs#L21

Here you can see that you should not assign a value to the UriBuilder.Query with a starting question mark: https://docs.microsoft.com/en-us/dotnet/api/system.uribuilder.query?view=netcore-2.1#examples

However the HttpRequestMessage.RequestUri is a Uri and getting it’s Query property will include a starting question mark: https://docs.microsoft.com/en-us/dotnet/api/system.uri.query?view=netcore-2.1#examples

It can be hotfixed with a DelegatingHandler, but that is not the best solution.

Steps to Reproduce the Problem

I am using very simple config:

{
  "ReRoutes": [
    {
      "DownstreamPathTemplate": "/api/{action}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5000
        }
      ],
      "UpstreamPathTemplate": "/{action}",
      "UpstreamHttpMethod": ["GET", "POST", "PUT", "DELETE"],
      "UpstreamHeaderTransform": {
        "Custom-Header": "SomeValue"
      }
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:4000"
  }
}

For example this request

http://localhost:4000/something?someparam=1

will look like this after the ocelot proxy

http://localhost:5000/api/something??someparam=1

Specifications

  • Version: 10.0.4, 12.0.1, 13.0.0
  • Platform: Windows 10, .NET Framework 4.6.1

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
nagybalint001commented, Dec 4, 2019

@SindelarPetr we used this delegating handler:

[Obsolete("Ocelot update solves this")]
public class QueryStringHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.Method == HttpMethod.Get && !string.IsNullOrEmpty(request.RequestUri.Query))
        {
            request.RequestUri = new UriBuilder()
            {
                Host = request.RequestUri.Host,
                Port = request.RequestUri.Port,
                Path = request.RequestUri.AbsolutePath,
                Query = request.RequestUri.Query.Substring(1),
                Scheme = request.RequestUri.Scheme,
            }.Uri;
        }

        return base.SendAsync(request, cancellationToken);
    }
}

you can add this message handler with this code snippet:

services.AddOcelot().AddDelegatingHandler<QueryStringHandler>(true)

Maybe it would be cleaner (and safer) to use the same logic that is part of the newer Ocelot nuget: https://github.com/ThreeMammals/Ocelot/pull/794/files

1reaction
nagybalint001commented, Jan 18, 2019

More info about the bug:

It seems to me that there is difference between the .NET Framework and .NET Standard/Core behavior.

If I host the application over .NET Framework, the UriBuilder will append an extra question mark, but over .NET Core this will not happen (if you remove the leading question mark from the query, it will also give the correct Uri, so in the .NET Core case the leading question mark maybe does not matter).

Maybe that’s why the “should_have_question_mark_with_question_mark_prefixed” test not fails.

If you try this modification (or something similar) in DownstreamRequest.cs:

public HttpRequestMessage ToHttpRequestMessage()
{
    var uriBuilder = new UriBuilder
    {
        Port = Port,
        Host = Host,
        Path = AbsolutePath,
        Query = (!string.IsNullOrEmpty(Query) && Query[0].Equals('?'))
            ? Query.Substring(1)
            : Query,
        Scheme = Scheme
    };

    _request.RequestUri = uriBuilder.Uri;
    return _request;
}
public string ToUri()
{
    var uriBuilder = new UriBuilder
    {
        Port = Port,
        Host = Host,
        Path = AbsolutePath,
        Query = (!string.IsNullOrEmpty(Query) && Query[0].Equals('?'))
            ? Query.Substring(1)
            : Query,
        Scheme = Scheme
    };

    return uriBuilder.Uri.AbsoluteUri;
}

tests will pass, and the proxy would work as expected over .NET Framework too.

Read more comments on GitHub >

github_iconTop Results From Across the Web

What Are Query Strings & Parameters - How to Optimize
A query string is a set of characters tacked onto the end of a URL. The query string begins after the question mark...
Read more >
A Beginner's Guide to URL Parameters
URL parameters (also known as query strings or URL query parameters) are elements inserted in your URLs to help you filter and organize...
Read more >
Query Parameters
Query parameters are a defined set of parameters attached to the end of a URL. They are extensions of the URL that are...
Read more >
Query Parameters - Routing - Ember Guides
Common use cases for query params include representing the current page number in a paginated collection, filter criteria, or sorting criteria. In web ......
Read more >
What are Query Parameters? Technical topics explained ...
Query parameters are parameters attached to the end of a URL and separated from the URL by a question mark (?). The section...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found