Frühlingsruhe mit einem Zuul-Proxy

1. Übersicht

In diesem Artikel untersuchen wir die Kommunikation zwischen einer Front-End-Anwendung und einer REST-API, die separat bereitgestellt werden .

Ziel ist es, CORS und die Richtlinienbeschränkung für denselben Ursprung des Browsers zu umgehen und der Benutzeroberfläche zu ermöglichen, die API aufzurufen, obwohl sie nicht denselben Ursprung haben.

Grundsätzlich erstellen wir zwei separate Anwendungen - eine UI-Anwendung und eine einfache REST-API, und wir verwenden den Zuul-Proxy in der UI-Anwendung, um Aufrufe an die REST-API zu proxy.

Zuul ist ein JVM-basierter Router und serverseitiger Load Balancer von Netflix. Und Spring Cloud hat eine schöne Integration mit einem eingebetteten Zuul-Proxy - was wir hier verwenden werden.

2. Maven-Konfiguration

Zuerst müssen wir eine Abhängigkeit der zuul Unterstützung von Spring Cloud unsere UI - Anwendung hinzuzufügen pom.xml :

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

Die neueste Version finden Sie hier.

3. Zuul Eigenschaften

Als nächstes müssen wir Zuul konfigurieren, und da wir Spring Boot verwenden, werden wir dies in der application.yml tun :

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

Beachten Sie, dass:

  • Wir stellen einen Proxy auf unseren Ressourcenserver Foos.
  • Alle Anfragen von der Benutzeroberfläche, die mit " / foos / " beginnen, werden an unseren Foos Resource Server unter // loclahost: 8081 / spring-zuul-foos-resource / foos / weitergeleitet.

4. Die API

Unsere API-Anwendung ist eine einfache Spring Boot-App.

In diesem Artikel werden wir die API betrachten, die auf einem Server bereitgestellt wird, der auf Port 8081 ausgeführt wird.

Definieren wir zunächst das grundlegende DTO für die Ressource, die wir verwenden werden:

public class Foo { private long id; private String name; // standard getters and setters }

Und eine einfache Steuerung:

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

5. Die UI-Anwendung

Unsere UI-Anwendung ist auch eine einfache Spring Boot-Anwendung.

In diesem Artikel werden wir die API betrachten, die auf einem Server bereitgestellt wird, der auf Port 8080 ausgeführt wird.

Beginnen wir mit dem Haupt index.html - ein bisschen AngularJS mit:

     var app = angular.module('myApp', ["ngResource"]); app.controller('mainCtrl', function($scope,$resource,$http) { $scope.foo = {id:0 , name:"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}} New Foo 

Der wichtigste Aspekt hierbei ist, wie wir über relative URLs auf die API zugreifen !

Beachten Sie, dass die API-Anwendung nicht auf demselben Server wie die UI-Anwendung bereitgestellt wird, sodass relative URLs nicht funktionieren sollten und ohne den Proxy nicht funktionieren.

Mit dem Proxy greifen wir jedoch über den Zuul-Proxy auf die Foo- Ressourcen zu, der natürlich so konfiguriert ist, dass diese Anforderungen an den Ort weitergeleitet werden, an dem die API tatsächlich bereitgestellt wird.

Und schließlich die tatsächlich bootfähige Anwendung:

@EnableZuulProxy @SpringBootApplication public class UiApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(UiApplication.class, args); } }

Beachten Sie, dass wir neben der einfachen Boot-Annotation auch den Enable-Stil der Annotation für den Zuul-Proxy verwenden, der ziemlich cool, sauber und prägnant ist.

6. Testen Sie das Routing

Testen Sie nun unsere UI-Anwendung wie folgt:

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

7. Ein benutzerdefinierter Zuul-Filter

Es stehen mehrere Zuul-Filter zur Verfügung, und wir können auch einen eigenen erstellen:

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

Dieser einfache Filter fügt der Anfrage nur einen Header mit dem Namen " Test " hinzu - aber natürlich können wir so komplex werden, wie wir es brauchen, um unsere Anfragen hier zu erweitern.

8. Testen Sie den benutzerdefinierten Zuul-Filter

Lassen Sie uns abschließend testen, ob unser benutzerdefinierter Filter funktioniert. Zuerst werden wir unseren FooController auf dem Foos-Ressourcenserver ändern :

@RestController public class FooController { @GetMapping("/foos/{id}") 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)); } }

Jetzt - probieren wir es aus:

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

9. Fazit

In diesem Artikel haben wir uns auf die Verwendung von Zuul konzentriert, um Anforderungen von einer UI-Anwendung an eine REST-API weiterzuleiten. Wir haben erfolgreich an CORS und der Richtlinie mit demselben Ursprung gearbeitet und es ist uns auch gelungen, die HTTP-Anforderung während der Übertragung anzupassen und zu erweitern.

Die vollständige Implementierung dieses Tutorials finden Sie im GitHub-Projekt - dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.