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

* Addressed comments:
* Removed Global filter bean with @Order annotation, now using class that implements Ordered
* Added logic to actually mutate the request entity (and the exchange) for the Modify Request example
* changed endpoint for languageServiceEndpoint in the chain requests example

* removed order from first simple global filter, since well be covering that with other global filter
This commit is contained in:
Ger Roza 2019-11-25 16:55:02 -03:00 committed by maibin
parent 2b256270fe
commit 0b49d2ad6b
8 changed files with 83 additions and 39 deletions

View File

@ -28,14 +28,14 @@ public class ChainRequestGatewayFilterFactory extends AbstractGatewayFilterFacto
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("endpoint", "defaultLanguage");
return Arrays.asList("languageServiceEndpoint", "defaultLanguage");
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
return client.get()
.uri(config.getEndpoint())
.uri(config.getLanguageServiceEndpoint())
.exchange()
.flatMap(response -> {
return (response.statusCode()
@ -45,8 +45,7 @@ public class ChainRequestGatewayFilterFactory extends AbstractGatewayFilterFacto
.map(range -> {
exchange.getRequest()
.mutate()
.headers(h -> h.setAcceptLanguage(range))
.build();
.headers(h -> h.setAcceptLanguage(range));
String allOutgoingRequestLanguages = exchange.getRequest()
.getHeaders()
@ -65,18 +64,18 @@ public class ChainRequestGatewayFilterFactory extends AbstractGatewayFilterFacto
}
public static class Config {
private String endpoint;
private String languageServiceEndpoint;
private String defaultLanguage;
public Config() {
}
public String getEndpoint() {
return endpoint;
public String getLanguageServiceEndpoint() {
return languageServiceEndpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
public void setLanguageServiceEndpoint(String languageServiceEndpoint) {
this.languageServiceEndpoint = languageServiceEndpoint;
}
public String getDefaultLanguage() {

View File

@ -40,7 +40,7 @@ public class LoggingGatewayFilterFactory extends AbstractGatewayFilterFactory<Lo
if (config.isPostLogger())
logger.info("Post GatewayFilter logging: " + config.getBaseMessage());
}));
}, -2);
}, 1);
}
public static class Config {

View File

@ -12,6 +12,9 @@ import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
@Component
public class ModifyRequestGatewayFilterFactory extends AbstractGatewayFilterFactory<ModifyRequestGatewayFilterFactory.Config> {
@ -45,8 +48,7 @@ public class ModifyRequestGatewayFilterFactory extends AbstractGatewayFilterFact
exchange.getRequest()
.mutate()
.headers(h -> h.setAcceptLanguageAsLocales(Collections.singletonList(requestLocale)))
.build();
.headers(h -> h.setAcceptLanguageAsLocales(Collections.singletonList(requestLocale)));
}
String allOutgoingRequestLanguages = exchange.getRequest()
@ -56,8 +58,20 @@ public class ModifyRequestGatewayFilterFactory extends AbstractGatewayFilterFact
.map(range -> range.getRange())
.collect(Collectors.joining(","));
logger.info("Modify Request output - Request contains Accept-Language header: " + allOutgoingRequestLanguages);
return chain.filter(exchange);
logger.info("Modify request output - Request contains Accept-Language header: {}", allOutgoingRequestLanguages);
ServerWebExchange modifiedExchange = exchange.mutate()
.request(originalRequest -> originalRequest.uri(UriComponentsBuilder.fromUri(exchange.getRequest()
.getURI())
.replaceQueryParams(new LinkedMultiValueMap<String, String>())
.build()
.toUri()))
.build();
logger.info("Removed all query params: {}", modifiedExchange.getRequest()
.getURI());
return chain.filter(modifiedExchange);
};
}

View File

@ -0,0 +1,31 @@
package com.baeldung.springcloudgateway.customfilters.filters.global;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class FirstPreLastPostGlobalFilter implements GlobalFilter, Ordered {
final Logger logger = LoggerFactory.getLogger(FirstPreLastPostGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
logger.info("First Pre Global Filter");
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> {
logger.info("Last Post Global Filter");
}));
}
@Override
public int getOrder() {
return -1;
}
}

View File

@ -5,7 +5,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import reactor.core.publisher.Mono;
@ -23,17 +22,4 @@ public class LoggingGlobalFiltersConfigurations {
}));
};
}
@Bean
@Order(-1)
public GlobalFilter FirstPreLastPostGlobalFilter() {
return (exchange, chain) -> {
logger.info("First Pre Global Filter");
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> {
logger.info("Last Post Global Filter");
}));
};
}
}

View File

@ -4,14 +4,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class LoggingGlobalPreFilter implements GlobalFilter, Ordered {
public class LoggingGlobalPreFilter implements GlobalFilter {
final Logger logger = LoggerFactory.getLogger(LoggingGlobalPreFilter.class);
@ -20,9 +19,4 @@ public class LoggingGlobalPreFilter implements GlobalFilter, Ordered {
logger.info("Global Pre Filter executed");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}

View File

@ -9,8 +9,8 @@ spring.cloud.gateway.routes[0].filters[1]=Logging=My Custom Message, true, true
#spring.cloud.gateway.routes[0].filters[1].args[preLogger]=true
#spring.cloud.gateway.routes[0].filters[1].args[postLogger]=true
spring.cloud.gateway.routes[0].filters[2]=ModifyRequest=en
spring.cloud.gateway.routes[0].filters[3]=ModifyResponse
spring.cloud.gateway.routes[0].filters[2]=ModifyResponse
spring.cloud.gateway.routes[0].filters[3]=ModifyRequest=en
spring.cloud.gateway.routes[0].filters[4]=ChainRequest=http://localhost:8082/resource/language, fr
management.endpoints.web.exposure.include=*

View File

@ -45,6 +45,8 @@ public class CustomFiltersLiveTest {
response.expectStatus()
.isOk()
.expectHeader()
.doesNotExist("Bael-Custom-Language-Header")
.expectBody(String.class)
.isEqualTo("Service Resource");
@ -60,7 +62,8 @@ public class CustomFiltersLiveTest {
.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:"))
.haveAtLeastOne(eventContains("Modify request output - Request contains Accept-Language header:"))
.haveAtLeastOne(eventContainsExcept("Removed all query params: ", "locale"))
// Modify Response
.areNot(eventContains("Added custom header to Response"))
// Chain Request
@ -75,16 +78,33 @@ public class CustomFiltersLiveTest {
response.expectStatus()
.isOk()
.expectHeader()
.exists("Bael-Custom-Language-Header")
.expectBody(String.class)
.isEqualTo("Service Resource");
assertThat(LoggerListAppender.getEvents())
// Modify Response
.haveAtLeastOne(eventContains("Added custom header to Response"));
.haveAtLeastOne(eventContains("Added custom header to Response"))
.haveAtLeastOne(eventContainsExcept("Removed all query params: ", "locale"));
}
/**
* This condition will be successful if the event contains a substring
*/
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));
}
/**
* This condition will be successful if the event contains a substring, but not another one
*/
private Condition<ILoggingEvent> eventContainsExcept(String substring, String except) {
return new Condition<ILoggingEvent>(entry -> (substring == null || (entry.getFormattedMessage() != null && entry.getFormattedMessage()
.contains(substring)
&& !entry.getFormattedMessage()
.contains(except))),
String.format("entry with message '%s'", substring));
}
}