I'm trying to forward all requests to my API to a single endpoint based upon some condition.
The Gateway
app runs on port 8080
I've created the following filter:
public class OutagePeriodFilter extends ZuulFilter {
@Override
public String filterType() {
return "route";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return isOutagePeriod();
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
// if outage - redirect everyone to http://localhost:8082/outage
try {
String url = UriComponentsBuilder.fromHttpUrl("http://localhost:8082").path("/outage").build()
.toUriString();
ctx.setRouteHost(new URL(url));
} catch(MalformedURLException mue) {
log.error("Cannot forward to outage period website");
}
return null;
}
private boolean isOutagePeriod() {
// returns true if outage
}
}
However after making a request to http://localhost:8080/alerts/public
my API logs show:
2017-03-03 16:11:30.735 EST 0037 DEBUG o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/outage/alerts/public'; against '/beans/'
For some reason it appends the original PATH to the redirect PATH resulting in a request to /outage/alerts/public
which doesn't exist. I want to make a request to just /outage
.
Putting a breakpoint in my filter just as the ctx.setRouteHost()
is called shows that correct URL (http://10.50.36.43:8082/outage/
).
My application.properties
:
zuul.routes.api.path=/api/**
zuul.routes.api.url=http://localhost:8082/
First, use PRE_TYPE instead of ROUTE_TYPE (aka "route")
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
Second, specify correct filterOrder
@Override
public int filterOrder() {
return FilterConstants.SEND_FORWARD_FILTER_ORDER;
}
Third, you need to remove URI containing "/alerts/public", which is appended to the routeHost by zuul
@Override
public Object run() {
ctx.set("requestURI", "");
// your code
return null;
}
Finally, override forwarding url in the code (//your code). And you have to specify at least one route (cause zuul filters don't work if there are no routes) to proxy "not outaged" requests to the same host 8080 like this
zuul.routes.api.path=/api/**
zuul.routes.api.url=http://localhost:8080/api
IMHO, zuul is not a very convenient way to do this.