Весенний отдых с прокси 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.
Настройка Swagger 2 с помощью Spring REST API
Узнайте, как документировать Spring REST API с помощью Swagger 2.
Введение в Spring REST Docs
В этой статье представлен Spring REST Docs, механизм, управляемый тестами, для создания документации для сервисов RESTful, которая является точной и удобочитаемой.
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:
Самый важный аспект здесь - это то, как мы получаем доступ к 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, поэтому его должно быть легко импортировать и запускать как есть.