Get started with Spring 5 and Spring Boot 2, through the reference Learn Spring 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.

Setting Up Swagger 2 with a Spring REST API

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

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.

2. Maven Configuration

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


The latest version can be found here.

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:

      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:

public class FooController {

    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:

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

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

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

    <h1>Foo Details</h1>
    <a href="#" ng-click="getFoo()">New Foo</a>

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:

public class UiApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {, 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:

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:

public class CustomZuulFilter extends ZuulFilter {

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

    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:

public class FooController {

    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 it out:

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.

REST bottom

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course :

Inline Feedbacks
View all comments
Comments are closed on this article!