0

As the title suggests I want to change the url based on a given query parameter. So for example if I request:

  • http://api.company.com/path?service=A >> route to upstream A
  • http://api.company.com/path?service=B >> route to upstream B

I've tried multiple different versions based on this, this, this or that. None of these examples worked or provide a complete list environment (code + config files).

Current non working version:

application.yml:

zuul:
  ignoredServices: '*'
  routes:
    serviceA:
      path: /statistics/**
      url: http://localhost:3000/a
    serviceB:
      path: /statistics/**
      url: http://localhost:3000/b

PreFilter for Zuul

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

import java.net.URL;

import static com.netflix.zuul.context.RequestContext.getCurrentContext;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.*;


public class QueryParamServiceIdPreFilter extends ZuulFilter {

    public int filterOrder() {
        return PRE_DECORATION_FILTER_ORDER + 1;
    }

    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    public Object run() {
        RequestContext ctx = getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        // always null
        URL routeHost = getCurrentContext().getRouteHost();

        if ( "A".equals(request.getParameter("serviceUrl")) ) {
            ctx.put("serviceId", "serviceA");
        }

        if ( "B".equals(request.getParameter("serviceUrl")) ) {
            ctx.put("serviceId", "serviceB");
        }

        return null;
    }
}

Fake micro service:

var express = require('express');
var app = express();
app.get('/a', function (req, res) {
  res.send('Service A');
});

app.get('/b', function (req, res) {
  res.send('Service B');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

Result on call

$ curl "localhost:8071/statistics?serviceUrl=B" ;  echo; curl "localhost:8071/statistics?serviceUrl=A"
Service B
Service B⏎
Daniel Gerber
  • 3,226
  • 3
  • 25
  • 32
  • Can't you write a RouteFilter for that? https://cloud.spring.io/spring-cloud-netflix/multi/multi__router_and_filter_zuul.html#zuul-developer-guide-sample-route-filter – Jeff May 23 '19 at 14:47
  • If routing is based on query parameter, route filter would not help. – Milenko Jevremovic May 27 '19 at 13:20

1 Answers1

1

Your code looks good, thing you are missing is service discovery. You said:

ctx.put("serviceId", "serviceA");

but you do not have defined service id, instead you are using service url, here:

serviceA:
  path: /statistics/**
  url: http://localhost:3000/a

after you configure service discovery you will have:

serviceA:
  path: /statistics/**
  serviceId: serviceA

Check my answers here and here