Spring REST met een Zuul Proxy

1. Overzicht

In dit artikel zullen we de communicatie tussen een front-end applicatie en een REST API die afzonderlijk worden geïmplementeerd.

Het doel is om CORS en de Same Origin Policy-beperking van de browser te omzeilen en de gebruikersinterface toe te staan ​​de API aan te roepen, ook al hebben ze niet dezelfde oorsprong.

We zullen in feite twee afzonderlijke applicaties maken - een UI-applicatie en een eenvoudige REST API, en we zullen deze gebruiken de volmacht van Zuul in de UI-applicatie om aanroepen naar de REST API te proxy.

Zuul is een JVM-gebaseerde router en server-side load balancer van Netflix. En Spring Cloud heeft een mooie integratie met een ingebouwde Zuul-proxy - dat is wat we hier zullen gebruiken.

2. Maven-configuratie

Ten eerste moeten we een afhankelijkheid toevoegen aan de zuul-ondersteuning van Spring Cloud naar onze UI-applicaties pom.xml:

 org.springframework.cloud spring-cloud-starter-netflix-zuul 2.2.0.RELEASE 

De laatste versie vind je hier.

3. Zuul-eigenschappen

Vervolgens moeten we Zuul configureren, en aangezien we Spring Boot gebruiken, gaan we dat doen in de application.yml:

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

Let daar op:

  • We doen een proxy naar onze bronserver Foos.
  • Alle verzoeken van de gebruikersinterface die beginnen met '/ foos /”Wordt doorgestuurd naar ons Foos Bronserver op // loclahost: 8081 / spring-zuul-foos-resource / foos /

4. De API

Onze API-applicatie is een eenvoudige Spring Boot-app.

In dit artikel gaan we kijken naar de API die is geïmplementeerd op een actieve server op poort 8081.

Laten we eerst de basis-DTO definiëren voor de resource die we gaan gebruiken:

openbare klasse Foo {lange privé-id; private String naam; // standaard getters en setters}

En een simpele controller:

@RestController openbare klasse FooController {@GetMapping ("/ foos / {id}") openbare Foo findById (@PathVariable lange id, HttpServletRequest req, HttpServletResponse res) {return new Foo (Long.parseLong (randomNumeric (2)), randomAlphabetic 4)); }}

5. De UI-applicatie

Onze UI-applicatie is ook een eenvoudige Spring Boot-applicatie.

In dit artikel gaan we kijken naar de API die is geïmplementeerd op een actieve server op poort 8080.

Laten we beginnen met het belangrijkste index.html - een beetje AngularJS gebruiken:

     var app = angular.module ('myApp', ["ngResource"]); app.controller ('mainCtrl', function ($ scope, $ resource, $ http) {$ scope.foo = {id: 0, naam: "sample foo"}; $ scope.foos = $ resource ("/ foos / : fooId ", {fooId: '@ id'}); $ scope.getFoo = function () {$ scope.foo = $ scope.foos.get ({fooId: $ scope.foo.id});}}) ; {{foo.id}} {{foo.name}} Nieuwe Foo 

Het belangrijkste aspect hier is hoe we toegang krijgen tot de API met behulp van relatieve URL's!

Houd er rekening mee dat de API-applicatie niet op dezelfde server is geïmplementeerd als de UI-applicatie, dus relatieve URL's zouden niet moeten werken, en zal niet werken zonder de proxy.

Met de proxy hebben we echter toegang tot het Foo resources via de Zuul-proxy, die natuurlijk is geconfigureerd om deze verzoeken door te sturen naar waar de API ook daadwerkelijk wordt geïmplementeerd.

En tot slot, de eigenlijk Boot-enabled applicatie:

@EnableZuulProxy @SpringBootApplication openbare klasse UiApplication breidt SpringBootServletInitializer uit {openbare statische leegte hoofd (String [] args) {SpringApplication.run (UiApplication.class, args); }}

Merk op dat we naast de eenvoudige Boot-annotatie ook de inschakelstijl van annotatie gebruiken voor de Zuul-proxy, die best gaaf, schoon en beknopt is.

6. Test de routing

Laten we nu onze UI-applicatie testen - als volgt:

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

7. Een op maat gemaakt Zuul-filter

Er zijn meerdere Zuul-filters beschikbaar en we kunnen ook onze eigen aangepaste filters maken:

@Component public class CustomZuulFilter breidt ZuulFilter uit {@Override public Object run () {RequestContext ctx = RequestContext.getCurrentContext (); ctx.addZuulRequestHeader ("Test", "TestSample"); null teruggeven; } @Override openbare boolean shouldFilter () {return true; } // ...}

Dit eenvoudige filter voegt gewoon een koptekst toe met de naam 'Test”Op het verzoek - maar we kunnen natuurlijk zo complex worden als nodig is om hier onze verzoeken uit te breiden.

8. Test het aangepaste Zuul-filter

Laten we tot slot testen of ons aangepaste filter werkt - eerst zullen we onze FooController op Foos resource server:

@RestController openbare klasse FooController {@GetMapping ("/ foos / {id}") openbare Foo findById (@PathVariable lange id, HttpServletRequest req, HttpServletResponse res) {if (req.getHeader ("Test")! = Null) {res .addHeader ("Test", req.getHeader ("Test")); } retourneer nieuwe Foo (Long.parseLong (randomNumeric (2)), randomAlphabetic (4)); }}

Laten we het nu eens testen:

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

9. Conclusie

In dit artikel hebben we ons gericht op het gebruik van Zuul om verzoeken van een UI-applicatie naar een REST API te sturen. We hebben met succes rond CORS en hetzelfde beleid gewerkt en we zijn er ook in geslaagd om het HTTP-verzoek tijdens de overdracht aan te passen en uit te breiden.

De volledige implementatie van deze tutorial is te vinden in het GitHub-project - dit is een op Maven gebaseerd project, dus het zou gemakkelijk te importeren en uit te voeren moeten zijn zoals het is.