With Zuul I can easily define custom filters that are activated before or after the request is forwarded to the specific service.
Is there a way to block requests from being forwarded at a "pre" filter level, and send immediately the response to the client? I know something similar is doable with "static" filters, but I need to decide per request (based on the presence of certain parameters/headers in the request itself).
Routing is an integral part of a microservice architecture. For example, / may be mapped to your web application, /api/users is mapped to the user service and /api/shop is mapped to the shop service. Zuul is a JVM-based router and server-side load balancer from Netflix.
The Netflix Zuul service provides dynamic routing. Using Zuul in your app enables your services to use the information from the Eureka service directory to reach other services. Because both Eureka and Zuul are Java applications they can be implemented with Spring Boot, part of the Spring Framework for Java.
9.12 Providing Hystrix Fallbacks For Routes When a circuit for a given route in Zuul is tripped you can provide a fallback response by creating a bean of type ZuulFallbackProvider .
There are four types of standard filters in Zuul: pre for pre-routing filtering, route for routing to an origin, post for post-routing filters, and error for error handling. Zuul also supports a static type for static responses. Any filter type can be created or added and run by calling the method runFilters(type).
Here is an example of how I use zuul-filter to check for an API-key being authorized. If not, I send a 401 response to the client.
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String apiKey = request.getHeader("X-API-KEY");
if (!isAuthorized(apiKey)){
// blocks the request
ctx.setSendZuulResponse(false);
// response to client
ctx.setResponseBody("API key not authorized");
ctx.getResponse().setHeader("Content-Type", "text/plain;charset=UTF-8");
ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
return null;
}
Note that if the client's API key is not authorized, all other filters will still be run, but the request will still fail due to ctx.setSendZuulResponse(false)
.
When failing a response, it will by default be empty - that is, there is no headers such as Content-Type
etc. It is a good idea to set them yourself so a client's browser etc. knows how to parse the response body.
I use a pre
filter to check the authentication of the request, and if the request dose not authorized, then I return 401
and do not call the back end service any more. I do it in run()
function like this:
RequestContext ctx = getCurrentContext();
// do something to check the authentication
if(auth failed){
ctx.unset();
ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
ctx.unset()
tell the context to stop this request, and ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
set the http code to 401
I found the solution, just needed to add context.setSendZuulResponse(false);
in the run() method of my "pre" custom filter.
Other filters will still be called, but request won't be routed to destination.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With