Open NadChel opened 4 months ago
It's not right
That is subjective. The Route
class is low level. It needs to be public for use across packages. It is not documented anywhere to do things as you have described.
I'm not sure how SecurityWebFiltersOrder
would help.
Well, it's now part of public API, whether intentionally or not. Generally speaking, it means we have to properly maintain it (forever)
SecurityWebFiltersOrder
is used in Spring Security as an alternative for hard-coded order ints. It ties filters to certain "phases" rather than specific ints that are liable to change. We too have a few implicit phases (though it's not as complex), but we don't yet recognize it on a programmatic level. I don't exactly insist on a similar abstraction, but it's something that deserves consideration, imo
P.S.: It's off-topic, but my PR has been sitting for a week, do you believe someone on the team could give it a look?
I came across this problem a few months ago when writing my Dynamic Gateway project. Since I was dynamically building
Route
s in runtime, I chose to forgoRouteLocatorBuilder
and instead assembled eachRoute
by calling methods onRoute.AsyncBuilder
Then I noticed something unusual: while the filters were definitely added to my route builders, my routes still didn't work as expected. Everything was fine once I wrapped the filters in
OrderedGatewayFilter
instances with the order of zeroToday, as I begin my journey as an open-source contributor, I took time to investigate the problem. I found it and wrote a small MRE. Here it is:
Here's what I get when I hit
http://localhost:8080/dog-fact
. It's the API's 404:The reason I get a 404 is because the API server received
GET https://dog-api.kinduff.com:443/dog-fact
, and there's no such endpointIt seems like my filter never got applied, but that's not exactly the case. Here's a picture from the IntelliJ debugger:
My path rewriting filter is on the list of
GatewayFilter
s, but since all of them, except mine, are ordered, the rewritig filter comes last – importantly, afterNettyRoutingFilter
that already built the responseFlux
So when my it's my filter's turn, the fact that it sets the right value for
GATEWAY_REQUEST_URL_ATTR
attribute doesn't matter anymore, the attribute has already been readIt's also important to put it ahead of
RouteToRequestUrlFilter
. It sets the sameGATEWAY_REQUEST_URL_ATTR
attribute with a request URI in which Gateway's host and port,localhost:8080
in my case, are replaced with theRoute
'sgetUri()
. We don't want the rewrite path filter to set it back tolocalhost:8080
(which it will do if it has a lower precedence)So to get it working, you have to wrap the filter in an
OrderedGatewayFilter
instance with the right order which should beNettyRoutingFilter
(Integer.MAX_VALUE
)RouteToRequestUrlFilter
(10 000)@Configuration public class MyRoutingConfig { @Bean public RouteLocator routeLocator() { Route dogRoute = Route.async() .id(UUID.randomUUID().toString()) .predicate(new PathRoutePredicateFactory() .apply(config -> config.setPatterns(List.of("/dog-fact")))) .filter(wrapInOrderedGatewayFilter( new RewritePathGatewayFilterFactory() .apply(config -> config.setRegexp("/dog-fact").setReplacement("/api/facts")))) .uri("https://dog-api.kinduff.com") .build(); return () -> Flux.just(dogRoute); }
}
Very straighforwardly:
To recap:
Route
class and allows a direct creation ofRoute
sRoute
with a mutating custom filter without manually setting a correct orderIt's not right
In case you recognize this problem, I want to solve it myself. For example, we could move this logic ("if it's not already wrapped, wrap in a reasonably ordered
OrderedGatewayFilter
"):from
GatewayFilterSpec
toRoute
itselfI also believe we should move away from those magic ints. For instance, we can take a leaf out of Spring Security's book with its
SecurityWebFiltersOrder
I'm ready to discuss it further