[BAEL-3313] spring-cloud/spring-cloud-gateway | Writing custom Spring Cloud Gateway Filters (#8182)

* updated dependency management in spring-cloud-gateway pom.xml

* * renamed org package to com
* renamed spring.cloud package to springcloudgateway
* deleted SpringContextIntegrationTest, as per BAEL-14304
* updated spring Junit test to jupiter

* separated introduction-application properties from application.yml, fixing launch error due to file not found exception

* Added Service to use as Proxied Service

* Added global filters and debug logs for article

* fixed error in properties source, plus added GatewayFilter Factories

* implemented Modify Request example

* implemented Modify Response example

* implemented Chain Request example

* Added Tests:
* Live Test for gateway
* Integration tests for services
Fixed small issues

* renamed tests that were not following BDD naming
This commit is contained in:
Ger Roza
2019-11-22 23:42:56 -03:00
committed by maibin
parent b1971384e2
commit 7ee5019f7e
31 changed files with 805 additions and 83 deletions
@@ -0,0 +1,26 @@
package com.baeldung.secondservice;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.test.web.reactive.server.WebTestClient;
import com.baeldung.secondservice.web.SecondServiceRestController;
@WebFluxTest(SecondServiceRestController.class)
public class SecondServiceIntegrationTest {
@Autowired
private WebTestClient webClient;
@Test
public void whenResourceLanguageEndpointCalled_thenRetrievesSpanishLanguageString() throws Exception {
this.webClient.get()
.uri("/resource/language")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("es");
}
}
@@ -0,0 +1,12 @@
package com.baeldung.secondservice;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = SecondServiceApplication.class)
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}
@@ -0,0 +1,29 @@
package com.baeldung.service;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.http.HttpHeaders;
import org.springframework.test.web.reactive.server.WebTestClient;
import com.baeldung.service.web.ServiceRestController;
@WebFluxTest(ServiceRestController.class)
public class ServiceIntegrationTest {
@Autowired
private WebTestClient webClient;
@Test
public void whenResourceEndpointCalled_thenRetrievesResourceStringWithContentLanguageHeader() throws Exception {
this.webClient.get()
.uri("/resource")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals(HttpHeaders.CONTENT_LANGUAGE, "en")
.expectBody(String.class)
.isEqualTo("Service Resource");
}
}
@@ -0,0 +1,12 @@
package com.baeldung.service;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = ServiceApplication.class)
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}
@@ -0,0 +1,90 @@
package com.baeldung.springcloudgateway.customfilters;
import static org.assertj.core.api.Assertions.assertThat;
import org.assertj.core.api.Condition;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
import com.baeldung.springcloudgateway.customfilters.utils.LoggerListAppender;
import ch.qos.logback.classic.spi.ILoggingEvent;
/**
* This test requires:
* * the service in com.baeldung.service running
* * the 'second service' in com.baeldung.secondservice running
*
*/
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class CustomFiltersLiveTest {
@LocalServerPort
String port;
private WebTestClient client;
@BeforeEach
public void clearLogList() {
LoggerListAppender.clearEventList();
client = WebTestClient.bindToServer()
.baseUrl("http://localhost:" + port)
.build();
}
@Test
public void whenCallServiceThroughGateway_thenAllConfiguredFiltersGetExecuted() {
ResponseSpec response = client.get()
.uri("/service/resource")
.exchange();
response.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("Service Resource");
assertThat(LoggerListAppender.getEvents())
// Global Pre Filter
.haveAtLeastOne(eventContains("Global Pre Filter executed"))
// Global Post Filter
.haveAtLeastOne(eventContains("Global Post Filter executed"))
// Global Pre and Post Filter
.haveAtLeastOne(eventContains("First Pre Global Filter"))
.haveAtLeastOne(eventContains("Last Post Global Filter"))
// Logging Filter Factory
.haveAtLeastOne(eventContains("Pre GatewayFilter logging: My Custom Message"))
.haveAtLeastOne(eventContains("Post GatewayFilter logging: My Custom Message"))
// Modify Request
.haveAtLeastOne(eventContains("Modify Request output - Request contains Accept-Language header:"))
// Modify Response
.areNot(eventContains("Added custom header to Response"))
// Chain Request
.haveAtLeastOne(eventContains("Chain Request output - Request contains Accept-Language header:"));
}
@Test
public void givenRequestWithLocaleQueryParam_whenCallServiceThroughGateway_thenAllConfiguredFiltersGetExecuted() {
ResponseSpec response = client.get()
.uri("/service/resource?locale=en")
.exchange();
response.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("Service Resource");
assertThat(LoggerListAppender.getEvents())
// Modify Response
.haveAtLeastOne(eventContains("Added custom header to Response"));
}
private Condition<ILoggingEvent> eventContains(String substring) {
return new Condition<ILoggingEvent>(entry -> (substring == null || (entry.getFormattedMessage() != null && entry.getFormattedMessage()
.contains(substring))), String.format("entry with message '%s'", substring));
}
}
@@ -0,0 +1,25 @@
package com.baeldung.springcloudgateway.customfilters.utils;
import java.util.ArrayList;
import java.util.List;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
public class LoggerListAppender extends AppenderBase<ILoggingEvent> {
static private List<ILoggingEvent> events = new ArrayList<>();
@Override
protected void append(ILoggingEvent eventObject) {
events.add(eventObject);
}
public static List<ILoggingEvent> getEvents() {
return events;
}
public static void clearEventList() {
events.clear();
}
}
@@ -0,0 +1,15 @@
package com.baeldung.springcloudgateway.introduction;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import com.baeldung.springcloudgateway.introduction.IntroductionGatewayApplication;
@SpringBootTest(classes = IntroductionGatewayApplication.class)
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}