Merge pull request #14564 from anastasiosioannidis/JAVA-13321
JAVA-13321 Added new gateway module to existing microservices e-book
This commit is contained in:
commit
bc83cc6616
@ -0,0 +1,7 @@
|
|||||||
|
## Spring Cloud Gateway
|
||||||
|
|
||||||
|
This module contains articles about Spring Cloud Gateway
|
||||||
|
|
||||||
|
### Relevant Articles:
|
||||||
|
|
||||||
|
- [Exploring the New Spring Cloud Gateway](http://www.baeldung.com/spring-cloud-gateway)
|
@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>gateway-2</artifactId>
|
||||||
|
<name>gateway-2</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-2</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../../parent-boot-2</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit</groupId>
|
||||||
|
<artifactId>junit-bom</artifactId>
|
||||||
|
<version>${junit-jupiter.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud-dependencies.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<spring-cloud-dependencies.version>2021.0.3</spring-cloud-dependencies.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.baeldung.springcloudgateway.custompredicates;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class CustomPredicatesApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new SpringApplicationBuilder(CustomPredicatesApplication.class)
|
||||||
|
.profiles("customroutes")
|
||||||
|
.run(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.baeldung.springcloudgateway.custompredicates.config;
|
||||||
|
|
||||||
|
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||||
|
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import com.baeldung.springcloudgateway.custompredicates.factories.GoldenCustomerRoutePredicateFactory;
|
||||||
|
import com.baeldung.springcloudgateway.custompredicates.factories.GoldenCustomerRoutePredicateFactory.Config;
|
||||||
|
import com.baeldung.springcloudgateway.custompredicates.service.GoldenCustomerService;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class CustomPredicatesConfig {
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public GoldenCustomerRoutePredicateFactory goldenCustomer(GoldenCustomerService goldenCustomerService) {
|
||||||
|
return new GoldenCustomerRoutePredicateFactory(goldenCustomerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//@Bean
|
||||||
|
public RouteLocator routes(RouteLocatorBuilder builder, GoldenCustomerRoutePredicateFactory gf ) {
|
||||||
|
|
||||||
|
return builder.routes()
|
||||||
|
.route("dsl_golden_route", r ->
|
||||||
|
r.predicate(gf.apply(new Config(true, "customerId")))
|
||||||
|
.and()
|
||||||
|
.path("/dsl_api/**")
|
||||||
|
.filters(f -> f.stripPrefix(1))
|
||||||
|
.uri("https://httpbin.org")
|
||||||
|
)
|
||||||
|
.route("dsl_common_route", r ->
|
||||||
|
r.predicate(gf.apply(new Config(false, "customerId")))
|
||||||
|
.and()
|
||||||
|
.path("/dsl_api/**")
|
||||||
|
.filters(f -> f.stripPrefix(1))
|
||||||
|
.uri("https://httpbin.org")
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.baeldung.springcloudgateway.custompredicates.factories;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
|
||||||
|
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
|
||||||
|
import org.springframework.http.HttpCookie;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
import com.baeldung.springcloudgateway.custompredicates.service.GoldenCustomerService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Philippe
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class GoldenCustomerRoutePredicateFactory extends AbstractRoutePredicateFactory<GoldenCustomerRoutePredicateFactory.Config> {
|
||||||
|
|
||||||
|
private final GoldenCustomerService goldenCustomerService;
|
||||||
|
|
||||||
|
public GoldenCustomerRoutePredicateFactory(GoldenCustomerService goldenCustomerService ) {
|
||||||
|
super(Config.class);
|
||||||
|
this.goldenCustomerService = goldenCustomerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> shortcutFieldOrder() {
|
||||||
|
return Arrays.asList("isGolden","customerIdCookie");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<ServerWebExchange> apply(Config config) {
|
||||||
|
|
||||||
|
return (ServerWebExchange t) -> {
|
||||||
|
List<HttpCookie> cookies = t.getRequest()
|
||||||
|
.getCookies()
|
||||||
|
.get(config.getCustomerIdCookie());
|
||||||
|
|
||||||
|
boolean isGolden;
|
||||||
|
if ( cookies == null || cookies.isEmpty()) {
|
||||||
|
isGolden = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String customerId = cookies.get(0).getValue();
|
||||||
|
isGolden = goldenCustomerService.isGoldenCustomer(customerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.isGolden()?isGolden:!isGolden;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Validated
|
||||||
|
public static class Config {
|
||||||
|
boolean isGolden = true;
|
||||||
|
|
||||||
|
@NotEmpty
|
||||||
|
String customerIdCookie = "customerId";
|
||||||
|
|
||||||
|
|
||||||
|
public Config() {}
|
||||||
|
|
||||||
|
public Config( boolean isGolden, String customerIdCookie) {
|
||||||
|
this.isGolden = isGolden;
|
||||||
|
this.customerIdCookie = customerIdCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGolden() {
|
||||||
|
return isGolden;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGolden(boolean value) {
|
||||||
|
this.isGolden = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the customerIdCookie
|
||||||
|
*/
|
||||||
|
public String getCustomerIdCookie() {
|
||||||
|
return customerIdCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param customerIdCookie the customerIdCookie to set
|
||||||
|
*/
|
||||||
|
public void setCustomerIdCookie(String customerIdCookie) {
|
||||||
|
this.customerIdCookie = customerIdCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.baeldung.springcloudgateway.custompredicates.service;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Philippe
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class GoldenCustomerService {
|
||||||
|
|
||||||
|
public boolean isGoldenCustomer(String customerId) {
|
||||||
|
|
||||||
|
// TODO: Add some AI logic to check is this customer deserves a "golden" status ;^)
|
||||||
|
if ( "baeldung".equalsIgnoreCase(customerId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.baeldung.springcloudgateway.introduction;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.PropertySource;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@PropertySource("classpath:introduction-application.properties")
|
||||||
|
public class IntroductionGatewayApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(IntroductionGatewayApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
spring:
|
||||||
|
cloud:
|
||||||
|
gateway:
|
||||||
|
routes:
|
||||||
|
- id: golden_route
|
||||||
|
uri: https://httpbin.org
|
||||||
|
predicates:
|
||||||
|
- Path=/api/**
|
||||||
|
- GoldenCustomer=true
|
||||||
|
filters:
|
||||||
|
- StripPrefix=1
|
||||||
|
- AddRequestHeader=GoldenCustomer,true
|
||||||
|
- id: common_route
|
||||||
|
uri: https://httpbin.org
|
||||||
|
predicates:
|
||||||
|
- Path=/api/**
|
||||||
|
- name: GoldenCustomer
|
||||||
|
args:
|
||||||
|
golden: false
|
||||||
|
customerIdCookie: customerId
|
||||||
|
filters:
|
||||||
|
- StripPrefix=1
|
||||||
|
- AddRequestHeader=GoldenCustomer,false
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
|||||||
|
logging:
|
||||||
|
level:
|
||||||
|
org.springframework.cloud.gateway: DEBUG
|
||||||
|
reactor.netty.http.client: DEBUG
|
@ -0,0 +1,7 @@
|
|||||||
|
spring.cloud.gateway.routes[0].id=baeldung_route
|
||||||
|
spring.cloud.gateway.routes[0].uri=http://www.baeldung.com
|
||||||
|
spring.cloud.gateway.routes[0].predicates[0]=Path=/baeldung
|
||||||
|
|
||||||
|
management.endpoints.web.exposure.include=*
|
||||||
|
|
||||||
|
server.port=80
|
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||||
|
</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
@ -0,0 +1,67 @@
|
|||||||
|
package com.baeldung.springcloudgateway.custompredicates;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.json.JSONTokener;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.boot.web.server.LocalServerPort;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.RequestEntity;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test requires
|
||||||
|
*/
|
||||||
|
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||||
|
@ActiveProfiles("customroutes")
|
||||||
|
public class CustomPredicatesApplicationLiveTest {
|
||||||
|
|
||||||
|
@LocalServerPort
|
||||||
|
String serverPort;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TestRestTemplate restTemplate;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenNormalCustomer_whenCallHeadersApi_thenResponseForNormalCustomer() throws JSONException {
|
||||||
|
|
||||||
|
String url = "http://localhost:" + serverPort + "/api/headers";
|
||||||
|
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
|
||||||
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
|
||||||
|
JSONObject json = new JSONObject(response.getBody());
|
||||||
|
JSONObject headers = json.getJSONObject("headers");
|
||||||
|
assertThat(headers.getString("Goldencustomer")).isEqualTo("false");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenGoldenCustomer_whenCallHeadersApi_thenResponseForGoldenCustomer() throws JSONException {
|
||||||
|
|
||||||
|
String url = "http://localhost:" + serverPort + "/api/headers";
|
||||||
|
RequestEntity<Void> request = RequestEntity
|
||||||
|
.get(URI.create(url))
|
||||||
|
.header("Cookie", "customerId=baeldung")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ResponseEntity<String> response = restTemplate.exchange(request, String.class);
|
||||||
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
|
||||||
|
JSONObject json = new JSONObject(response.getBody());
|
||||||
|
JSONObject headers = json.getJSONObject("headers");
|
||||||
|
assertThat(headers.getString("Goldencustomer")).isEqualTo("true");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.baeldung.springcloudgateway.introduction;
|
||||||
|
|
||||||
|
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() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appender name="LISTAPPENDER"
|
||||||
|
class="com.baeldung.springcloudgateway.introduction.LoggerListAppender">
|
||||||
|
</appender>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<root level="info">
|
||||||
|
<appender-ref ref="LISTAPPENDER" />
|
||||||
|
</root>
|
||||||
|
<root level="info">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
@ -18,6 +18,7 @@
|
|||||||
<module>config</module>
|
<module>config</module>
|
||||||
<module>discovery</module>
|
<module>discovery</module>
|
||||||
<module>gateway</module>
|
<module>gateway</module>
|
||||||
|
<module>gateway-2</module>
|
||||||
<module>svc-book</module>
|
<module>svc-book</module>
|
||||||
<module>svc-rating</module>
|
<module>svc-rating</module>
|
||||||
<module>customer-service</module>
|
<module>customer-service</module>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user