Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Zuul dynamic routing based on HTTP method and resolve target host by 'serviceId'?

How to make Zuul dynamic routing based on HTTP method (GET/POST/PUT...)? For example, when you need to route the POST request to the different host instead of the default one described in 'zuul.routes.*'...

zuul:
  routes:
    first-service:
      path: /first/**
      serviceId: first-service
      stripPrefix: false

    second-service:
      path: /second/**
      serviceId: second-service
      stripPrefix: false

I.e. when we request 'GET /first' then Zuul route the request to the 'first-service', but if we request 'POST /first' then Zuul route the request to the 'second-service'.

like image 243
Cepr0 Avatar asked Dec 17 '17 15:12

Cepr0


1 Answers

To implement dynamic routing based on HTTP method we can create a custom 'route' type ZuulFilter and resolve 'serviceId' through DiscoveryClient. Fore example:

@Component
public class PostFilter extends ZuulFilter {

    private static final String REQUEST_PATH = "/first";
    private static final String TARGET_SERVICE = "second-service";
    private static final String HTTP_METHOD = "POST";

    private final DiscoveryClient discoveryClient;

    public PostOrdersFilter(DiscoveryClient discoveryClient) {
        this.discoveryClient = discoveryClient;
    }

    @Override
    public String filterType() {
        return "route";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        String method = request.getMethod();
        String requestURI = request.getRequestURI();
        return HTTP_METHOD.equalsIgnoreCase(method) && requestURI.startsWith(REQUEST_PATH);
    }

    @Override
    public Object run() {

        RequestContext context = RequestContext.getCurrentContext();
        List<ServiceInstance> instances = discoveryClient.getInstances(TARGET_SERVICE);
        try {
            if (instances != null && instances.size() > 0) {
                context.setRouteHost(instances.get(0).getUri().toURL());
            } else {
                throw new IllegalStateException("Target service instance not found!");
            }
        } catch (Exception e) {
            throw new IllegalArgumentException("Couldn't get service URL!", e);
        }
        return null;
    }
}
like image 169
Cepr0 Avatar answered Nov 15 '22 08:11

Cepr0