It's my first time at Spring Cloud Gateway implementation.
I need filter every request and apply a filter validation on some paths. Following the Baeldung Custom Filters tutorial I make a simple application to filter requests.
The application must release paths like /actuator/health
and validate specific paths to backend service. So far, I've implemented a GlobalFilter
and a GatewayFilterFactory
. The Global filter is called every request but the GatewayFilter is called just once when application starts, that way I can't make the auth logic to every request. The auth logic is about a specific header field. So, my grained questions are:
- How validate every request with a specific path?
- How refuse a request and send a error message?
GlobalFilter
@Component
public class LoggingGlobalPreFilter implements GlobalFilter {
final Logger LOGGER = LoggerFactory.getLogger(LoggingGlobalPreFilter.class);
@Override
public Mono<Void> filter(
ServerWebExchange exchange,
GatewayFilterChain chain) {
LOGGER.info("Global Pre Filter executed");
return chain.filter(exchange);
}
}
GatewayFilter
@Component
public class LoggingGatewayFilterFactory extends
AbstractGatewayFilterFactory<LoggingGatewayFilterFactory.Config> {
final Logger LOGGER =
LoggerFactory.getLogger(LoggingGatewayFilterFactory.class);
public LoggingGatewayFilterFactory() {
super(Config.class);
}
private Mono<Void> onError(ServerWebExchange exchange, String err, HttpStatus httpStatus) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(httpStatus);
return response.setComplete();
}
private boolean isAuthorizationValid(String authorizationHeader) {
boolean isValid = true;
return authorizationHeader.equals("x-header");
}
@Override
public GatewayFilter apply(Config config) {
LOGGER.info("M=apply, Msg=Applying Gateway Filter....");
return ((exchange, chain) -> {
LOGGER.info("M=apply, Msg=Applying Gateway Filter...."); // APARENTELLY NEVER ENTER HERE.
ServerHttpRequest request = exchange.getRequest();
if (!request.getHeaders().containsKey(TsApiGatewayConstants.HEADER_APIKEY)) {
return this.onError(exchange, TsApiGatewayConstants.MESSAGE_API_KEY_MISSING, HttpStatus.UNAUTHORIZED);
}
String apiKey = request.getHeaders().get(TsApiGatewayConstants.HEADER_APIKEY).get(0);
String userAgent = request.getHeaders().get(TsApiGatewayConstants.HEADER_USER_AGENT).get(0);
if (!this.isAuthorizationValid(userAgent)) {
return this.onError(exchange, TsApiGatewayConstants.MESSAGE_API_KEY_INVALID, HttpStatus.UNAUTHORIZED);
}
return chain.filter(exchange);
});
}
public static class Config {
private String baseMessage;
private boolean preLogger;
private boolean postLogger;
public Config(String baseMessage, boolean preLogger, boolean postLogger) {
this.baseMessage = baseMessage;
this.preLogger = preLogger;
this.postLogger = postLogger;
}
public String getBaseMessage() {
return baseMessage;
}
public void setBaseMessage(String baseMessage) {
this.baseMessage = baseMessage;
}
public boolean isPreLogger() {
return preLogger;
}
public void setPreLogger(boolean preLogger) {
this.preLogger = preLogger;
}
public boolean isPostLogger() {
return postLogger;
}
public void setPostLogger(boolean postLogger) {
this.postLogger = postLogger;
}
}
}
application.yml
cloud:
gateway:
routes:
- id: service_route
uri: https://backend-url:443
predicates:
- Path=/api
filters:
- Logging
Example path to filter: https://backend-url:443/api/service1