ThreeMammals / Ocelot

.NET API Gateway
https://www.nuget.org/packages/Ocelot
MIT License
8.36k stars 1.64k forks source link

Routing not working with special character in UpstreamPathTemplate #2143

Open amorelIM opened 2 months ago

amorelIM commented 2 months ago

Hi,

we're using ocelot as an API gateway for a service using OData. In OData, one feature is to have a route with $query in the name. For example: /v3/Orders/$query

Here is the documentation for that specific thing : https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_PassingQueryOptionsintheRequestBody

Expected Behavior / New Feature

Having the next route exposed in Ocelot and being able to call the $query route on the underlying service.

{
  "UpstreamPathTemplate": "/v3/Orders/$query",
  "DownstreamPathTemplate": "/v1/Orders/$query"
}

Actual Behavior / Motivation for New Feature

A 404 is returned with those warnings in the logs:

[13:10:56 WRN] requestId: , previousRequestId: No PreviousRequestId, message: 'DownstreamRouteFinderMiddleware setting pipeline errors. IDownstreamRouteFinder returned Error Code: UnableToFindDownstreamRouteError Message: Failed to match Route configuration for upstream path: /v3/orders/$query, verb: POST.'
[13:10:56 WRN] requestId: , previousRequestId: No PreviousRequestId, message: 'Error Code: UnableToFindDownstreamRouteError Message: Failed to match Route configuration for upstream path: /v3/orders/$query, verb: POST. errors found in ResponderMiddleware. Setting error response for request path:/v3/orders/$query, request method: POST'

Steps to Reproduce the Problem

See previous sections. Using the '$' character in the upstream route.

Workaround

Remove the $ character from the upstreamPathTemplate, but it won't respect the OData protocol.

{
  "UpstreamPathTemplate": "/v3/Orders/query",
  "DownstreamPathTemplate": "/v1/Orders/$query"
}

Specifications

raman-m commented 2 months ago

Alexis, thanks for reporting this!

This bug is probably related to

but I'm not sure

raman-m commented 2 months ago

Having the next route exposed in Ocelot and being able to call the $query route on the underlying service.

{
  "UpstreamPathTemplate": "/v3/Orders/$query",
  "DownstreamPathTemplate": "/v1/Orders/$query"
}

I concur that all static routes with special characters should be functional and forwarded. However, I'm curious about the rationale for defining a static route.

Why not utilize placeholders and convert templates instead?

{
  "UpstreamPathTemplate": "/v3/Orders/{query}",
  "DownstreamPathTemplate": "/v1/Orders/{query}"
}

or even more short version?

{
  "UpstreamPathTemplate": "/v3/{everything}",
  "DownstreamPathTemplate": "/v1/{everything}"
}

Why don't you utilize placeholders?

raman-m commented 2 months ago

OData query is supported via using placeholders, see examples in code & docs My old answers in discussions with the same problem.

raman-m commented 2 months ago

Duplicate of #859

amorelIM commented 2 months ago

Thank you, it worked.

raman-m commented 1 month ago

Reopen to address triple: