Redirecting HTTP Requests With Zuul in Spring Boot
Zuul is part of the Spring Cloud Netflix package and allows redirect REST requests to perform various types of filters.
In almost any project where we use microservices, it is desirable that all communications between those microservices go through a communal place so that the inputs and outputs are recorded and can implement security or redirect requests, depending on various parameters.
With Zuul, this is very easy to implement since it is perfectly integrated with Spring Boot.
As always you can see the sources on which this article is based on my GitHub page. So, let's get to it.
Creating the Project
If you have installed Eclipse with the plugin for Spring Boot (which I recommend), creating the project should be as easy as adding a new Spring Boot project type, including the Zuul Starter. To do some tests, we will also include the web starter, as seen in the image below:

We also have the option to create a Maven project from https://start.spring.io/. We will then import the necessary information from our preferred IDE.

Starting
Let’s assume that the program is listening on http://localhost: 8080/, and that we want that all the requests to the URL http://localhost: 8080/google to be redirected to https://www.google.com.
To do this we create the
application.yml
file in the resources
directory, as seen in the image below:
This file will include the following lines:
They specify that everything requested with the path /google/ and more (**) will be redirected to https://www.google.com/. If such a request is made to
http://localhost:8080/google/search?q=profesor_p
this will be redirected tohttps://www.google.com/search?q=profesor_p
. In other words, what we add after /google/ will be included in the redirection, due to the two asterisks added at the end of the path.In order for the program to work, it will only be necessary to add the annotation @EnableZuulProxy and the start class, in this case: ZuulSpringTestApplication
In order to demonstrate the various features of Zuul, http://localhost:8080/api will be listening to a REST service that is implemented in the
TestController
class of this project. This class simply returns in the body, the data of the received request.Filtering: Writing Logs
In this part, we will see how to create a filter so that a record of the requests made is left.
To do this, we will create the class
PreFilter.java
which should extend ZuulFilter
:In this class, we will overwrite the functions we see in the source. Le's explain each of these functions:
- public Object run() - This is run for each request received. Here we can see the contents of the request and handle it if necessary.
- public boolean shouldFilter() - If it returns true the
run
function will be executed. - public int filterOrder() - Returns when this filter is executed because usually there are different filters for each task. We must take into account that certain redirections or changes in the petition have to be done in a certain order, by the same logic used by Zuul when processing requests.
- public String Filtertype() - specifies when the filter is executed. If it returns “pre”, it is executed before they have made the redirect and therefore before it has been called the end server (to Google, in our example). If it returns “post”, is executed after the server has responded. In the
org.springframework.cloud.netflix.zuul.filters.support.FilterConstants
class, we have ve defined the types to be returned: PRE_TYPE, POST_TYPE, ERROR_TYPE or ROUTE_TYPE.
In the example class, we see that, before making a request to the server, some request data is recorded, leaving a log.
Finally, for Spring Boot to utilize this filter, we should add the following function in our class.
Zuul looks for beans to inherit from the class,
ZuulFilter
, and use them.In this example, Java's
PostFilter
class also implements another filter but only runs after making the request to the server. As I mentioned, this is achieved by returning “post” in the Filtertype()
function.For Zuul to use this class we will create another bean with a function like this:
Remember that there is also a filter for treating errors that need to be addressed just after redirection ( “route”), but this article only looks into the post and pre filter types.
I'd like to clarify that, although this article does not with it, Zuul can not only redirect to a static URL but also to services provided by the Eureka Server. It also integrates with Hystrix to have fault tolerance, so that if a server cannot reach you can specify what action to take.
Filtering and Implementing Security
Let us add a new file redirection to the application.yml file.
This redirection will take any request type from http: //localhost: 8080/private/foo to the page where this article (http://www.profesor-p.com) is hosted.
The line
sensitiveHeaders
will be explained later.In the
PreRewriteFilter
class, I have implemented another pre filter for dealing this redirection. How? Easy. Put this code in the shouldFilter()
function.Now, in the
run
function, we include the following code:This searches the headers of the request (headers) and, if the user header doesn’t exist, it does nothing and the request is redirected to
http://www.profesor-p.com
. In case there is a user header found that has the value profesorp
, and the variable key has the value profe
, the request is redirected to http://localhost:8080/api
. Otherwise, it returns an HTTP code, forbidden, returning the string "Invalid username and/or password"
in the body of the HTTP response. Moreover, the flow of the request is canceled because it calls ctx.setSendZuulResponse (false).Because the line
sensitiveHeaders
in the file application.yml I mentioned above has ‘user’ and ‘password’ headers, it not be passed into the flow of the request.It is very important that this filter is run after the PRE_DECORATION filter, because, otherwise, the call
ctx.setRouteHost()
will have no effect. Therefore, the filterOrder
function will have this code:So a call passing the user and the correct password, we will redirect to http://localhost: 8080/api.
If you put the wrong password the output will look like this:
Filtering: Dynamic Filter
Finally, we will include two new redirections in the file
applicaction.yml
In the first three lines, when we go to the URL
http://localhost:8080/local/XXXX
we will be redirected to http://localhost:8080/api/XXX
. I'll clarify that the label local
is arbitrary and we could put json:
so that this doesn't coincide with the path
that we want to redirect to.In the second three lines, when we go to the URL
http://localhost:8080/url/XXXX
we will be redirected tohttp://localhost:8080/api/XXXXX
The
RouteURLFilter
class will be responsible for carrying data to the URL filter. Remember that to use Zuul, the filters must create a corresponding bean.In the
shouldFilter
function of RouteURLFilter
, we have this code to only fulfill requests to /url.In the
run
function, we have the code that performs the magic. Once we have captured the URL target and the path, as I explain below, it is used in the setRouteHost()
function of RequestContext
to properly redirect our requests.It searches the variables
hostDestino
and pathDestino
in the header to make the new URL to which it must redirect.For example, suppose we have a request like this:
The call will be redirected to http: //localhost: 8080/api?q=profesor-p and displays the following output:
You can also receive the URL to redirect the request body. The JSON object received must have the format defined by the
GatewayRequest
class, which, in turn, contains a URIRequest
object.This is an example of putting the URL redirect destination in the body:
As the body is being dealt with, we send to the server only what is sent in the
body
parameter of the JSON request.As shown, Zuul has a lot of power and is an excellent tool for redirections. In this article, I’ve only scratched the main features of this fantastic tool, but I hope it has allowed you to see the possibilities.
This article was written originally in Spanish and you can find it here.
Comments
Post a Comment
Please Share Your Views