Весенний ОТДЫХ с прокси Zuul

Весенний отдых с прокси Zuul

1. обзор

В этой статье мы исследуемcommunication between a front-end application and a REST API that are deployed separately.

Цель состоит в том, чтобы обойти ограничение CORS и одинаковой политики происхождения для браузера и позволить пользовательскому интерфейсу вызывать API, даже если они не имеют одного и того же происхождения.

По сути, мы создадим два отдельных приложения - приложение пользовательского интерфейса и простой REST API, и мы будем использоватьthe Zuul proxy в приложении пользовательского интерфейса для прокси-вызовов REST API.

Zuul - это основанный на JVM маршрутизатор и серверный балансировщик нагрузки от Netflix. А Spring Cloud имеет прекрасную интеграцию со встроенным прокси Zuul - что мы и будем здесь использовать.

Дальнейшее чтение:

Пример распределения нагрузки с помощью Zuul и Eureka

Посмотрите, как выглядит распределение нагрузки с Netflix Zuul.

Read more

Настройка Swagger 2 с помощью Spring REST API

Узнайте, как документировать Spring REST API с помощью Swagger 2.

Read more

Введение в Spring REST Docs

В этой статье представлен Spring REST Docs, механизм, управляемый тестами, для создания документации для сервисов RESTful, которая является точной и удобочитаемой.

Read more

2. Конфигурация Maven

Во-первых, нам нужно добавить зависимость от поддержки zuul из Spring Cloud вpom.xml нашего UI-приложения:


    org.springframework.cloud
    spring-cloud-starter-zuul
    1.0.4.RELEASE

3. Зуул Недвижимость

Затем нам нужно настроить Zuul, и поскольку мы используем Spring Boot, мы собираемся сделать это вapplication.yml:

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

Обратите внимание, что:

  • Мы проксируем на наш ресурсный серверFoos.

  • Все запросы от пользовательского интерфейса, который начинается с «/foos/», будут направляться на наш сервер ресурсовFoos вhttp://loclahost:8081/spring-zuul-foos-resource/foos/

4. API

Наше приложение API представляет собой простое приложение Spring Boot.

В этой статье мы рассмотрим API, развернутый на сервере сon port 8081.

Давайте сначала определим базовый DTO для ресурса, который мы собираемся использовать:

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

    // standard getters and setters
}

И простой контроллер:

@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. Приложение пользовательского интерфейса

Наше приложение пользовательского интерфейса также является простым приложением Spring Boot.

В этой статье мы рассмотрим API, развернутый на сервере сon port 8080.

Начнем с основногоindex.html - немного используя AngularJS:








Foo Details

{{foo.id}} {{foo.name}} New Foo

Самый важный аспект здесь - это то, как мы получаем доступ к APIusing relative URLs!

Помните, что приложение API не развертывается на том же сервере, что и приложение пользовательского интерфейса,so relative URLs shouldn’t work, и не будет работать без прокси.

Однако с прокси-сервером мы получаем доступ к ресурсамFoo через прокси-сервер Zuul, который, конечно же, настроен для маршрутизации этих запросов туда, где фактически развернут API.

И, наконец, собственно приложение с поддержкой Boot:

@EnableZuulProxy
@SpringBootApplication
public class UiApplication extends SpringBootServletInitializer {

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

Обратите внимание, что помимо простой аннотации Boot, мы также используем аннотацию в стиле enable для прокси Zuul, что довольно круто, чисто и лаконично.

6. Тестирование маршрутизации

Теперь давайте протестируем наше UI-приложение следующим образом:

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

    assertEquals(200, response.getStatusCode());
}

7. Пользовательский фильтр Zuul

Доступно несколькоZuul filters, и мы также можем создать свой собственный:

@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;
    }
    // ...
}

Этот простой фильтр просто добавляет к запросу заголовок с именем «Test», но, конечно, мы можем получить настолько сложный, насколько нам нужно, чтобы здесь дополнить наши запросы.

8. Проверить пользовательский фильтр Zuul

Наконец, давайте проверим, работает ли наш настраиваемый фильтр - сначала мы изменим нашFooController на сервере ресурсов Foos:

@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));
    }
}

А теперь давайте проверим это:

@Test
public void whenSendRequest_thenHeaderAdded() {
    Response response = RestAssured.get("http://localhost:8080/foos/1");

    assertEquals(200, response.getStatusCode());
    assertEquals("TestSample", response.getHeader("Test"));
}

9. Заключение

В этой статье мы сосредоточились на использовании Zuul для маршрутизации запросов от приложения пользовательского интерфейса к REST API. Мы успешно обошли CORS и политику одного и того же происхождения, и нам также удалось настроить и дополнить HTTP-запрос при передаче.

full implementation этого руководства можно найти вthe GitHub project - это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.