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

Query params aren't proxied correctly (Service Fabric) #555

Closed
davidni opened this issue Aug 17, 2018 · 14 comments
Closed

Query params aren't proxied correctly (Service Fabric) #555

davidni opened this issue Aug 17, 2018 · 14 comments
Labels
bug Identified as a potential bug merged Issue has been merged to dev and is waiting for the next release question Initially seen a question could become a new feature or bug or closed ;) small effort Likely less than a day of development effort.

Comments

@davidni
Copy link
Contributor

davidni commented Aug 17, 2018

Expected Behavior

Query params should be proxied correctly.

Actual Behavior

When using Service Fabric, an incoming request to https://example.com/a?b=c ends up being sent to https://localhost:19081/a??b=c&cmd=instance. I suspect the duplicated ?? problem exists without Service Fabric too.

I'm surprised this hasn't been caught before since it seems very easy to encounter. Perhaps there's a way around this that I just haven't found yet (for now I have code on my side to patch up the DownstreamContext before making the request.

Steps to Reproduce the Problem

Use a dummy rule that proxies UpstreamPath "/{everything}" to DownstreamPath "/{everything}". Make a request that matches the rule, with or without query parameters.

Specifications

  • Version: 8.0.3 - 10.0.2
  • Platform: Windows 10, .NET Framework 4.6.2
@davidni
Copy link
Contributor Author

davidni commented Aug 17, 2018

  1. Root cause of the ?? issue: DownstreamRequest.ToHttpRequestMessage().
var uriBuilder = new UriBuilder
{
    Port = Port,
    Host = Host,
    Path = AbsolutePath,
    Query = Query,
    Scheme = Scheme
};

It probably shouldn't just assign to UriBuilder.Query, and should instead remove leading ? itself. MSDN docs have a not-very-obvious remark about this:

Do not append a string directly to this property. If the length of Query is greater than 1, retrieve the property value as a string, remove the leading question mark, append the new query string, and set the property with the combined string.

  1. Root cause of the cmd=instance query param: DownstreamUrlCreatorMiddleware.CreateServiceFabricUri. I don't know why this was added in the first place. Was there any doc describing this should be added? I have run tests without it and it works as expected.

@davidni davidni closed this as completed Aug 17, 2018
@davidni davidni reopened this Aug 17, 2018
@TomPallister
Copy link
Member

@davidni there is a similar issue with query string params on the "/{everything}" route. I guess there is a lack of tests here :/

With regards to cmd=instance are you asking why this is being added?

@TomPallister TomPallister added bug Identified as a potential bug question Initially seen a question could become a new feature or bug or closed ;) small effort Likely less than a day of development effort. labels Aug 17, 2018
@davidni
Copy link
Contributor Author

davidni commented Aug 17, 2018

With regards to cmd=instance are you asking why this is being added?

Indeed. Service Fabric Reverse Proxy doesn't seem to care about this query param, and it gets passed transparently all the way to the target service.

It is problematic because it means a service behind Ocelot cannot provide functionality that relies on a query param called cmd (since Ocelot hard-codes that). I was curious why this was added in the beginning, and I am suggesting that it be removed.

Makes sense?

@TomPallister
Copy link
Member

@davidni I think I added it because when originally making Ocelot work with SF I saw that the sf client was appending it for requests to instance services. I actually don't know SF that well so if you know we don't need it more than happy to remove!!

@davidni
Copy link
Contributor Author

davidni commented Aug 17, 2018

Yes, let's remove it. Documentation is here

A call to Reverse Proxy takes this shape:
http(s)://<Cluster FQDN | internal IP>:Port/<ServiceInstanceName>/<Suffix path>?PartitionKey=<key>&PartitionKind=<partitionkind>&ListenerName=<listenerName>&TargetReplicaSelector=<targetReplicaSelector>&Timeout=<timeout_in_seconds>

The query params shown have special meaning for Reverse Proxy. Everything else is proxied without change. cmd is not special in any way per the docs.

@davidni
Copy link
Contributor Author

davidni commented Aug 17, 2018

To summarize, there are 2 specific asks for this issue:

  1. Fix the double question mark ??
  2. Remove cmd=instance for Service Fabric.

You mentioned (1) might be a dupe of another issue. Do you recall which one?

@TomPallister
Copy link
Member

  1. Might be related to Issue with OData query options #548

@TomPallister
Copy link
Member

@davidni can you share your json config for this issue? I'm having trouble replicating the problem.

@TomPallister
Copy link
Member

If you can point me in the right direction with the commit above that could also help!

@davidni
Copy link
Contributor Author

davidni commented Aug 22, 2018

  1. I'll be out of office for a few days, and unfortunately I won't have time to look into this before I leave -- sorry.

  2. I briefly looked at your PR, seems reasonable and nothing stood out on initial review. I wonder if there could be a behavior change between .NET Core Vs. .NET Framework re. how System.Uri works. For reference, my repro was on .NET Framework 4.6.1

Thanks again for your efforts to always raise the bar and improve quality.

@TomPallister
Copy link
Member

No worries I’m away all weekend as well so won’t be too much movement. I will try on Windows classic .net and see what happens. I really hope that is not the case!

TomPallister pushed a commit that referenced this issue Aug 23, 2018
TomPallister pushed a commit that referenced this issue Aug 23, 2018
TomPallister added a commit that referenced this issue Aug 25, 2018
* #555 added some tests for this issue but struggling to replicate

* #555 removed cmd=instance from service fabric code as someone who knows service fabric says its not needed
I

* #555 renamed test
@TomPallister TomPallister reopened this Aug 25, 2018
@TomPallister TomPallister added the merged Issue has been merged to dev and is waiting for the next release label Aug 25, 2018
@TomPallister
Copy link
Member

Should be fixed in 10.0.4! Let me know if any problems.

@kdrummond
Copy link

I am experiencing the same behavior reported by @davidni wrt item 1, running Ocelot v12.0.1. I can see that the DownstreamRequest constructor sets Query = _request.RequestUri.Query, and ToHttpRequestMessage() and ToUri() both pass those values as-is to UriBuilder. The issue is that the value carries the '?' as the first character, and per the MSDN quote David referenced above, this must be manually stripped out.

I'm using very simple ReRoutes rules, such as this:

    {
      "DownstreamPathTemplate": "/routing/{catchAll}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 23651
        }
      ],
      "UpstreamPathTemplate": "/routing/{catchAll}",
      "UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ],
    },

...which is turning my routes from "https://localhost:5099/routing/services/ServerVersion?myparam=myvalue" into "https://localhost:23651/routing/services/ServerVersion??myparam=myvalue".

Replacing the Query statement in the DownstreamRequest constructor with this, for example, resolves the issue:

            Query = (!string.IsNullOrEmpty(_request.RequestUri.Query) && _request.RequestUri.Query[0].Equals('?'))
                ? _request.RequestUri.Query.Substring(1)
                : _request.RequestUri.Query;

I'm using Ocelot in a ASP.NET app targeting .NET Framework 4.6.1, on Win 10, VS 2017.

@raman-m
Copy link
Member

raman-m commented Mar 25, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Identified as a potential bug merged Issue has been merged to dev and is waiting for the next release question Initially seen a question could become a new feature or bug or closed ;) small effort Likely less than a day of development effort.
Projects
None yet
Development

No branches or pull requests

4 participants