[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:
parent
2b256270fe
commit
0b49d2ad6b
|
@ -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() {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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=*
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue