Spring REST dengan Zuul Proxy

1. Ikhtisar

Dalam artikel ini, kita akan mempelajari komunikasi antara aplikasi front-end dan REST API yang diterapkan secara terpisah .

Tujuannya adalah untuk mengatasi CORS dan pembatasan Kebijakan Asal yang Sama pada browser dan memungkinkan UI untuk memanggil API meskipun mereka tidak berbagi asal yang sama.

Pada dasarnya kami akan membuat dua aplikasi terpisah - aplikasi UI dan REST API sederhana, dan kami akan menggunakan proxy Zuul di aplikasi UI untuk panggilan proxy ke REST API.

Zuul adalah router berbasis JVM dan load balancer sisi server oleh Netflix. Dan Spring Cloud memiliki integrasi yang bagus dengan proxy Zuul yang disematkan - yang akan kami gunakan di sini.

2. Konfigurasi Maven

Pertama, kita perlu menambahkan ketergantungan ke dukungan zuul dari Spring Cloud ke pom.xml aplikasi UI kita :

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

Versi terbaru dapat ditemukan di sini.

3. Sifat Zuul

Selanjutnya - kita perlu mengkonfigurasi Zuul, dan karena kita menggunakan Spring Boot, kita akan melakukannya di application.yml :

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

Perhatikan bahwa:

  • Kami melakukan proxy ke server sumber daya kami, Foos.
  • Semua permintaan dari UI yang dimulai dengan “ / foos / ” akan diarahkan ke server Sumber Daya Foos kami di // loclahost: 8081 / spring-zuul-foos-resource / foos /

4. API

Aplikasi API kami adalah aplikasi Spring Boot sederhana.

Dalam artikel ini, kami akan mempertimbangkan API yang digunakan di server yang berjalan pada port 8081.

Mari pertama-tama tentukan DTO dasar untuk Resource yang akan kita gunakan:

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

Dan pengontrol sederhana:

@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. Aplikasi UI

Aplikasi UI kami juga merupakan aplikasi Spring Boot sederhana.

Dalam artikel ini, kami akan mempertimbangkan API yang digunakan di server yang berjalan pada port 8080.

Mari kita mulai dengan main index.html - menggunakan sedikit AngularJS:

     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 

Aspek terpenting di sini adalah bagaimana kami mengakses API menggunakan URL relatif!

Perlu diingat bahwa aplikasi API tidak diterapkan di server yang sama dengan aplikasi UI, jadi URL relatif tidak akan berfungsi , dan tidak akan berfungsi tanpa proxy.

Dengan proxy, bagaimanapun, kami mengakses sumber daya Foo melalui proxy Zuul, yang tentu saja dikonfigurasi untuk merutekan permintaan ini ke mana pun API sebenarnya diterapkan.

Dan akhirnya, aplikasi yang mengaktifkan Boot:

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

Selain anotasi Boot sederhana, perhatikan bahwa kami juga menggunakan anotasi gaya pengaktifan untuk proxy Zuul, yang cukup keren, bersih, dan ringkas.

6. Uji Routing

Sekarang - mari kita uji aplikasi UI kita - sebagai berikut:

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

7. Filter Zuul Kustom

Ada beberapa filter Zuul yang tersedia, dan kami juga dapat membuat filter khusus kami sendiri:

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

Filter sederhana ini hanya menambahkan header yang disebut " Test " ke permintaan - tapi tentu saja, kita bisa menjadi serumit yang kita butuhkan untuk menambah permintaan kita di sini.

8. Uji Filter Zuul Kustom

Terakhir, mari kita uji untuk memastikan filter kustom kita berfungsi - pertama kita akan memodifikasi FooController di server sumber daya Foos:

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

Sekarang - mari kita uji:

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

9. Kesimpulan

Dalam artikel ini, kami berfokus pada penggunaan Zuul untuk merutekan permintaan dari aplikasi UI ke REST API. Kami berhasil menangani CORS dan kebijakan asal yang sama dan kami juga berhasil menyesuaikan dan menambah permintaan HTTP saat transit.

The implementasi penuh dari tutorial ini dapat ditemukan dalam proyek GitHub - ini adalah proyek berbasis Maven, sehingga harus mudah untuk impor dan berjalan seperti itu.