I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this article, we’ll explore the communication between a front-end application and a REST API that are deployed separately.

The goal is to work around CORS and the Same Origin Policy restriction of the browser and allow the UI to call the API even though they don’t share the same origin.

We’ll basically create two separate applications – a UI application and a simple REST API, and we’ll use the Zuul proxy in the UI application to proxy calls to the REST API.

Zuul is a JVM based router and server side load balancer by Netflix. And Spring Cloud has a nice integration with an embedded Zuul proxy – which is what we’ll use here.

Further reading:

An Example of Load Balancing with Zuul and Eureka

See how load-balancing with Netflix Zuul looks like.

Read more

Setting Up Swagger 2 with a Spring REST API

Learn how to document a Spring REST API using Swagger 2.

Read more

Introduction to Spring REST Docs

This article introduces Spring REST Docs, a test-driven mechanism to generate documentation for RESTful services that is both accurate and readable.

Read more

2. Maven Configuration

First, we need to add a dependency to the zuul support from Spring Cloud to our UI application’s pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
    <version>1.0.4.RELEASE</version>
</dependency>

3. Zuul Properties

Next – we need to configure Zuul, and since we’re using Spring Boot, we’re going to do that in the application.yml:

zuul:
  routes:
    foos:
      path: /foos/**
      url: http://localhost:8081/spring-zuul-foos-resource/foos

Note that:

  • We are proxying to our resource server Foos.
  • All requests from the UI that starts with “/foos/” will be routed to our Foos Resource server at http://loclahost:8081/spring-zuul-foos-resource/foos/

4. The API

Our API application is a simple Spring Boot app.

Within this article, we’re going to consider the API deployed in a server running on port 8081.

Let’s first define the basic DTO for the Resource we’re going to be using:

public class Foo {
    private long id;
    private String name;

    // standard getters and setters
}

And a simple controller:

@Controller
public class FooController {

    @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}")
    @ResponseBody
    public Foo findById(
      @PathVariable long id, HttpServletRequest req, HttpServletResponse res) {
        return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4));
    }
}

5. The UI Application

Our UI application is also a simple Spring Boot application.

Within this article, we’re going to consider the API deployed in a server running on port 8080.

Let’s start with the main index.html – using a bit of AngularJS:

<html>
<body ng-app="myApp" ng-controller="mainCtrl">
<script src="angular.min.js"></script>
<script src="angular-resource.min.js"></script>

<script>
var app = angular.module('myApp', ["ngResource"]);

app.controller('mainCtrl', function($scope,$resource,$http) {
    $scope.foo = {id:0 , name:"sample foo"};
    $scope.foos = $resource("/foos/:fooId",{fooId:'@id'});
    
    $scope.getFoo = function(){
        $scope.foo = $scope.foos.get({fooId:$scope.foo.id});
    }  
});
</script>

<div>
    <h1>Foo Details</h1>
    <span>{{foo.id}}</span>
    <span>{{foo.name}}</span>
    <a href="#" ng-click="getFoo()">New Foo</a>
</div>
</body>
</html>

The most important aspect here is how we’re accessing the API using relative URLs!

Keep in mind that the API application isn’t deployed on the same server as the UI application, so relative URLs shouldn’t work, and won’t work without the proxy.

With the proxy, however, we’re accessing the Foo resources through the Zuul proxy, which is of course configured to route these requests to wherever the API is actually deployed.

And finally, the actually Boot enabled application:

@EnableZuulProxy
@SpringBootApplication
public class UiApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(UiApplication.class, args);
    }
}

Beyond the simple Boot annotation, notice that we’re using the enable-style of annotation for the Zuul proxy as well, which is pretty cool, clean and concise.

6. Test The Routing

Now – let’s test our UI application – as follows:

@Test
public void whenSendRequestToFooResource_thenOK() {
    Response response = RestAssured.get("http://localhost:8080/foos/1");
 
    assertEquals(200, response.getStatusCode());
}

7. A Custom Zuul Filter

There are multiple Zuul filters available, and we can also create our own custom one:

@Component
public class CustomZuulFilter extends ZuulFilter {

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.addZuulRequestHeader("Test", "TestSample");
        return null;
    }

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

This simple filter just adds a header called “Test” to the request – but of course, we can get as complex as we need to here augment our requests.

8. Test Custom Zuul Filter

Finally, let’s test make sure our custom filter is working – first we will modify our FooController at Foos resource server:

@Controller
public class FooController {

    @GetMapping("/foos/{id}")
    @ResponseBody
    public Foo findById(
      @PathVariable long id, HttpServletRequest req, HttpServletResponse res) {
        if (req.getHeader("Test") != null) {
            res.addHeader("Test", req.getHeader("Test"));
        }
        return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4));
    }
}

Now – let’s test our it out:

@Test
public void whenSendRequest_thenHeaderAdded() {
    Response response = RestAssured.get("http://localhost:8080/foos/1");
 
    assertEquals(200, response.getStatusCode());
    assertEquals("TestSample", response.getHeader("Test"));
}

9. Conclusion

In this write-up, we focused on using Zuul to route requests from a UI application to a REST API. We successfully worked around CORS and the same-origin policy and we also managed to customize and augment the HTTP request in transit.

The full implementation of this tutorial can be found in the GitHub project – this is a Maven-based project, so it should be easy to import and run as it is.

I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE LESSONS

newest oldest most voted
Notify of
B SRIDHAR
Guest
B SRIDHAR

Hi, I found your article interesting and useful for what I am currently working. I have some queries as below. I currently perform authentication using AUTH service based on spring security oauth2 and generate tokens. Each of the micro services have the @enableResourceServer annotation and so they are protected and decode the tokens using the AUTH service. Also, within every micro service I also do the url check to check if the the user has the required authorities for a specific url pattern using spring security for http. I also have another custom service which I used for Access Control… Read more »

Eugen Paraschiv
Guest

You can certainly do that, yes – but I’m sure you know it’s not going to be a trivial implementation. You’ll need to run Spring Security in the app that’s running the proxy, and then you’ll have to move the ACL implementation there as well.
Also – the ACL entries are one thing, but these tie into your actual domain entities, so these will need to be accessible from this edge service as well.
Best of luck with the implementation – it sounds like it would indeed simplify the way you approach security by doing some consolidation. Cheers,
Eugen.

antony raja
Guest
antony raja

Hi
It is possible to have the Zul with Hystrix , Ribbon and proxy as Stadalone instead of Embedded proxy

Grzegorz Piwowarek
Guest
Grzegorz Piwowarek

It was not possible some time ago but there was an issue raise which seems to be closed for now so there is a huge chance that yes. https://github.com/spring-cloud/spring-cloud-netflix/issues/14

Rudy Bonefas
Guest
Rudy Bonefas

Eugen,

Searched the web but can’t figure out the following. Given a pre filter how do I block certain requests to my proxy and possibly send a response with a specific status and response body? I’m guessing throwing an exception in run() would block the request, but I would like to return a specific error response.

reddynr
Guest
reddynr

Hi,

Excellent example for proxcy implementation. I have implemented. But my current requirement required to support multiple countries like below configurations. Please advice any sample example.

zuul:
routes:
foos:
path: /foos/**
url: http://localhost:8081/spring-zuul-foos-resource/CountryCode/foos

Eugen Paraschiv
Guest

OK, that’s pretty similar to the example here. What’s the issue you’re running into?
Cheers,
Eugen.

Shah Faisal
Guest
Shah Faisal

Hi Mr. Baeldung, Is it possible to send data in RequestBody while I’m using zuul proxy? I’m trying to send some data as json i.e. $http({ method: ‘POST’, url: ‘xyz/prod’, headers : headers, data : requestData }).success(function(data) { console.log(data); }); But it seems zuul is removing request InputStream. Looking forward for your suggestion

Eugen Paraschiv
Guest

Zuul is perfectly fine to handle an HTTP body, sure. That being said – there may be other reasons why the data is not being forwarded – it’s hard to say without looking at the code.

My suggestion is to isolate whatever is happening into a failing test and then post the question on StackOverflow. Feel free to followup with the link and I’d be happy to have a look as well.
Cheers,
Eugen.