Ocelot icon indicating copy to clipboard operation
Ocelot copied to clipboard

Match catch-all file extension in upstream path template

Open ChrisSwinchatt opened this issue 6 years ago • 4 comments

Expected Behavior

When using a reroute like the following:

{
   "DownstreamPathTemplate": "/{json}.json",
   "DownstreamScheme": "http",
   "DownstreamHostAndPorts": [
        {
            "Host": "foo.svc",
           "Port": 80
        }
    ],
    "UpstreamPathTemplate": "/foo/{json}.json",
    "UpstreamHttpMethod": [
        "Get"
    ],
    "Priority": 3
}

Ocelot should forward a request such as /foo/bar.json to foo.svc/bar.json

Actual Behavior

Ocelot forwards the request to foo.svc/bar.json.json

Log:

[09:35:30 DBG] message: ocelot pipeline started
[09:35:30 DBG] message: Upstream url path is /foo/bar.json
[09:35:30 DBG] message: downstream templates are /{bar}.json
[09:35:30 INF] message: EndpointRateLimiting is not enabled for /{bar}.json
[09:35:30 INF] message: No authentication needed for /foo/bar.json
[09:35:30 INF] message: /{bar}.json route does not require user to be authorised
[09:35:30 DBG] message: Downstream url is http://foo.svc/bar.json.json
[09:35:30 DBG] message: setting http response message
[09:35:30 DBG] message: no pipeline errors, setting and returning completed response
[09:35:30 DBG] message: ocelot pipeline finished

Steps to Reproduce the Problem

  1. Have a reroute like /foo/{bar}.json
  2. Try to access it
  3. Get a 400 and the downstream service logs a message like GET /foo/swagger/v1/swagger.json.json returned 400

Specifications

  • Version: 13.0.0
  • Platform: ASP.Net Core 2.1

ChrisSwinchatt avatar Jan 16 '19 10:01 ChrisSwinchatt

Going to try to fix this myself.

Here is a test proving the bug (UrlPathPlaceholderNameAndValueFinderTests.cs):

[Fact]
public void can_match_down_stream_url_with_file_extension()
{
    var expectedTemplates = new List<PlaceholderNameAndValue>
    {
        new PlaceholderNameAndValue("{file}", "foo")
    };

    this.Given(x => x.GivenIHaveAUpstreamPath("/foo.ext"))
        .And(x => x.GivenIHaveAnUpstreamUrlTemplate("/{file}.ext"))
        .When(x => x.WhenIFindTheUrlVariableNamesAndValues())
        .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
        .BDDfy();
}

The placeholder should be "foo" because the ".ext" should match ".ext" in "{file}.ext".

ChrisSwinchatt avatar Jan 16 '19 10:01 ChrisSwinchatt

@ChrisSwinchatt I believe my in progress work on #737 already resolves this. I will add this test before merge to verify before I merge it in.

philproctor avatar Jan 16 '19 14:01 philproctor

Alright, I did some work on it today and wrote a few more tests. I’ll add the rest of them because there are some gotchas that my first attempt didn’t handle.

ChrisSwinchatt avatar Jan 16 '19 19:01 ChrisSwinchatt

@ChrisSwinchatt commented on Jan 16, 2019:

I did some work on it today and wrote a few more tests.

Which ones?

raman-m avatar Jan 07 '24 18:01 raman-m

@ChrisSwinchatt Your route must be Catch All one!

{
   "DownstreamPathTemplate": "/{all}",
    "UpstreamPathTemplate": "/foo/{all}",
}

raman-m avatar Jun 15 '24 12:06 raman-m