REST de primavera com um proxy Zuul
1. Visão geral
Neste artigo, vamos explorar ocommunication between a front-end application and a REST API that are deployed separately.
O objetivo é contornar o CORS e a restrição da política de mesma origem do navegador e permitir que a IU chame a API, mesmo que eles não compartilhem a mesma origem.
Basicamente, criaremos dois aplicativos separados - um aplicativo de IU e uma API REST simples, e usaremosthe Zuul proxy no aplicativo de IU para chamadas de proxy para a API REST.
O Zuul é um roteador baseado em JVM e um balanceador de carga no lado do servidor da Netflix. E Spring Cloud tem uma boa integração com um proxy Zuul embutido - que é o que usaremos aqui.
Leitura adicional:
Um exemplo de balanceamento de carga com Zuul e Eureka
Veja como é o equilíbrio de carga com o Netflix Zuul.
Configurando o Swagger 2 com uma API REST do Spring
Aprenda a documentar uma API REST do Spring usando o Swagger 2.
Introdução ao Spring REST Docs
Este artigo apresenta o Spring REST Docs, um mecanismo controlado por teste para gerar documentação para serviços RESTful que é precisa e legível.
2. Configuração do Maven
Primeiro, precisamos adicionar uma dependência ao suporte zuul do Spring Cloud para opom.xml do nosso aplicativo de IU:
org.springframework.cloud
spring-cloud-starter-zuul
1.0.4.RELEASE
3. Propriedades Zuul
Em seguida, precisamos configurar o Zuul e, como estamos usando o Spring Boot, faremos isso noapplication.yml:
zuul:
routes:
foos:
path: /foos/**
url: http://localhost:8081/spring-zuul-foos-resource/foos
Observe que:
-
Estamos fazendo proxy para nosso servidor de recursosFoos.
-
Todas as solicitações da IU que começam com “/foos/” serão roteadas para nosso servidor de recursosFoos emhttp://loclahost:8081/spring-zuul-foos-resource/foos/
4. A API
Nosso aplicativo de API é um aplicativo simples de inicialização de primavera.
Neste artigo, vamos considerar a API implantada em um servidor executandoon port 8081.
Vamos primeiro definir o DTO básico para o recurso que usaremos:
public class Foo {
private long id;
private String name;
// standard getters and setters
}
E um controlador simples:
@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. O aplicativo UI
Nosso aplicativo de interface do usuário também é um aplicativo simples de inicialização de primavera.
Neste artigo, vamos considerar a API implantada em um servidor executandoon port 8080.
Vamos começar com oindex.html principal - usando um pouco de AngularJS:
O aspecto mais importante aqui é como estamos acessando a APIusing relative URLs!
Lembre-se de que o aplicativo API não é implantado no mesmo servidor que o aplicativo UI,so relative URLs shouldn’t work, e não funcionará sem o proxy.
Com o proxy, no entanto, estamos acessando os recursosFoo por meio do proxy Zuul, que é obviamente configurado para encaminhar essas solicitações para onde quer que a API esteja realmente implementada.
E, finalmente, o aplicativo realmente habilitado para inicialização:
@EnableZuulProxy
@SpringBootApplication
public class UiApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(UiApplication.class, args);
}
}
Além da simples anotação de inicialização, observe que estamos usando o estilo de anotação de ativação para o proxy Zuul também, que é muito legal, limpo e conciso.
6. Teste o roteamento
Agora - vamos testar nosso aplicativo de IU - da seguinte maneira:
@Test
public void whenSendRequestToFooResource_thenOK() {
Response response = RestAssured.get("http://localhost:8080/foos/1");
assertEquals(200, response.getStatusCode());
}
7. Um filtro Zuul personalizado
Existem váriosZuul filters disponíveis e também podemos criar o nosso próprio:
@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;
}
// ...
}
Este filtro simples apenas adiciona um cabeçalho chamado “Test” à solicitação - mas é claro, podemos ficar tão complexos quanto precisarmos para aumentar nossas solicitações.
8. Teste o filtro Zuul personalizado
Finalmente, vamos testar se nosso filtro personalizado está funcionando - primeiro vamos modificar nossoFooController no servidor de recursos 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));
}
}
Agora - vamos testar:
@Test
public void whenSendRequest_thenHeaderAdded() {
Response response = RestAssured.get("http://localhost:8080/foos/1");
assertEquals(200, response.getStatusCode());
assertEquals("TestSample", response.getHeader("Test"));
}
9. Conclusão
Neste artigo, nos concentramos em usar o Zuul para rotear solicitações de um aplicativo de interface do usuário para uma API REST. Trabalhamos com êxito em torno do CORS e da política de mesma origem e também conseguimos personalizar e aumentar a solicitação HTTP em trânsito.
Ofull implementation deste tutorial pode ser encontrado emthe GitHub project - este é um projeto baseado em Maven, portanto, deve ser fácil de importar e executar como está.