spring-cloud-gateway icon indicating copy to clipboard operation
spring-cloud-gateway copied to clipboard

More flexible path matching (such as file extensions and logical or)

Open aftersss opened this issue 7 years ago • 13 comments

Bug report

spring-cloud-version: Finchley.SR2

I has a requirement that route www.example.com/**/*.html to lb://serviceNodeJs, and route www.example.com/** to lb://serviceJava, so I wrote the following yaml file:

spring:
  cloud:
    gateway:
      routes:
      - id: test1
        uri: lb://serviceNodeJs
        predicates:
        - Host=www.example.com
        - Path=/**/*.html
      - id: test2
        uri: lb://serviceJava
        predicates:
        - Host=www.example.com
        - Path=/**

But when I browse http://www.example.com/index.html, it is routed to lb://serviceJava, my idea is that all the requests with the .html postfix being routed to lb://serviceNodeJs, and all the others being routed to lb://serviceJava, And I have also read the source code PathRoutePredicateFactory, I found that it use a new class PathPattern to test if it matches. If I use AntPathMatcher, it can support my requirement. so can PathPattern changed to meet this requirement?

aftersss avatar Nov 22 '18 07:11 aftersss

Maybe we need something like an extension filter? The path filter probably doesnt take into account the file extension.

@spencergibb thoughts?

ryanjbaxter avatar Nov 26 '18 15:11 ryanjbaxter

PathPatternParser was made to be efficient and fast where AnyPathMatcher is not. I don't think I want to change this to use AntPathMatcher because of that.

You could use the JavaDSL to or two path predicates, or with the yaml, create two routes, one for root html, the other non-root html.

I've reached out to the framework team to see if that is correct behavior.

spencergibb avatar Nov 26 '18 22:11 spencergibb

Here are the javadocs for the matcher. https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/util/pattern/PathPattern.html

It's examples use file extensions, but not the two together.

spencergibb avatar Nov 26 '18 22:11 spencergibb

See https://jira.spring.io/browse/SPR-14544 for the reasoning.

spencergibb avatar Nov 26 '18 22:11 spencergibb

I'd prefer not to have a specific suffix filter. Maybe an option to use AntPathMatcher subject to the performance implications.

spencergibb avatar Nov 26 '18 22:11 spencergibb

Similar suggestions have come from @acidelk over gitter - to allow more elastic ways to match paths than what PathPattern allows for, for example to allow any endpoint from a group of defined endpoints to match the predicate like so:

predicates:
        - Path=/users/(find|status)

or like so:

predicates:
        - Path=/users/find
        - Path=/users/status

OlgaMaciaszek avatar Nov 29 '18 15:11 OlgaMaciaszek

You can currently repeat predicates, but it means a logical AND

predicates:
  - Path=/users/find
  - Path=/users/status

spencergibb avatar Dec 03 '18 19:12 spencergibb

What is the good of it? :)

acidelk avatar Dec 03 '18 19:12 acidelk

It's good in many other situations. I'm just stating that repeating them is already possible, but it means something else.

spencergibb avatar Dec 03 '18 19:12 spencergibb

Multiple paths were added in 7a5502fd7ae57e254151e38fe619b596b212b7e5.

I think an AntPathRoutePredicateFactory is the way forward here. Being aware that its performance will not match the PathPatternParser one.

Common functionality could be extracted to a base class.

spencergibb avatar Dec 10 '18 22:12 spencergibb

AntPathRoutePredicateFactory, I think is much needed for path predicates with ** within the pattern. Are there any plans to implement the same?

htejwani avatar Mar 03 '23 11:03 htejwani

Not currently

spencergibb avatar Mar 03 '23 17:03 spencergibb

I am trying to migrate from zuul for spring cloud gateway - I had configuration similar to this on Zuul which is using ant_path_matcher

api-with-specific-path:
      path: /api/v1/**/collection
      service-id: service1
api-with-less-restrictive-path:
      path: /api/v1/**
      service-id: service2

Is there any workaround I can utilize to support such configuration? This is what I was trying

 - id: api-with-specific-path
          uri: s://service1
          predicates:
            - Path=/api/v1/**/collection
          filters:
            - RewritePath=/api/v1//?(?<segment>.*), /v1-api/$\{segment}

I received following error - No more pattern data allowed after {*...} or ** pattern element. I used spring.mvc.pathmatch.matching-strategy=ant_path_matcher but that didn't help.

rahul-mishra-sp avatar Jan 26 '24 19:01 rahul-mishra-sp