7

I have a spring cloud gateway application and what I want is like if there are two routes then on one route it should redirect to some external application but for other route it should forward the request to same app with a particular url.

-id: my_local_route
 predicates:
   - Path="/services/local"
 uri: "/mylocal/services/local" //can we do something like that

Please note I want to create my rest services in same app as in spring cloud gateway. I understand it is not correct approach but for my knowledge I wanted to know whether it is possible or not.

Naresh Bharadwaj
  • 192
  • 1
  • 12

2 Answers2

2

If you have some rest APIs within your spring-cloud-gateway project, you don't need to explicitly put the routes for it. So suppose you have following rest api in gateway project

@RestController
@RequestMapping("test")
class Controller{
    @GetMapping("hello")
    public String hello(){
        return "hello";
    }
}

and for external-url, you want to send some traffic to let's say https://httpbin.org. So in gateway application.yml could look something like this:

spring:
  cloud:
    gateway:
      routes:
        - id: httpbin-route
          uri: https://httpbin.org
          predicates:
            - Path=/status/**

With this request like

  • http://localhost:8080/test/hello will be resolved by your rest controller
  • http://localhost:8080/status/200 will be redirected to httpbin site

If for some reason you have the same root path for both cases, the controller will have precedence.

Dhananjay
  • 1,140
  • 1
  • 12
  • 28
  • Hey Dhananjay I am familiar about it. But the problem is I want the cloud gateway to check the request. I do have a custom predicate on the basis of that I wanna decide whether I can forward the request to external service or to internal controller. Is there any way we can achieve it? – Naresh Bharadwaj Jan 09 '22 at 14:58
  • Looks like you have the same base path for both your URL's (questions the design). In that case you have few choices: 1) Create a RouteLocator bean and handle the specific pattern accordingly. 2) Create a global filter(there are many ways to do it) and do the same. – Dhananjay Jan 09 '22 at 16:43
  • I have tried using RouteLocator but it is not working for me. If I have same endpoint in that case it will not go through the cloud gateway predicates, instead it directly reach to controller. Can you give me some ref or example how to do it? May be I am not trying it correctly? – Naresh Bharadwaj Jan 10 '22 at 03:46
  • @NareshBharadwaj see https://stackoverflow.com/a/73439944/5973816 – Poison Aug 22 '22 at 03:39
2

If you have the same endpoint in gateway predicates and controller, by default controller will take precedence over predicates, if you want predicates to take precedence over controller, just create a BeanPostProcessor to adjust the order:

@Component
public class RequestMappingHandlerMappingBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof RequestMappingHandlerMapping) {
            ((RequestMappingHandlerMapping) bean).setOrder(2); // After RoutePredicateHandlerMapping
        }
        return bean;
    }

}
Poison
  • 389
  • 2
  • 14