I have 2 classes: filter and class to get response body. As far as I know I need to specify order NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER-1 so filter will get response body.
But when I implement Ordered or use annotation @Order or via OrderedGatewayFilter I cann’t call BodyRewrite class(which gets response body). When I try to use this for global filter(implemented GlobalFilter) it works fine.
May it be because I extend AbstractNameValueGatewayFilterFactory and I can’t specify order for it?
Full code: https://github.com/artem-kurilko/NettyFilter
Jwt filter class:
@Component public class JWTFilter extends AbstractNameValueGatewayFilterFactory { private final ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory; private final BodyRewrite bodyRewrite; @Autowired public JWTFilter(ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory, BodyRewrite bodyRewrite, ErrorWebExceptionHandler errorWebExceptionHandler) { this.modifyResponseBodyGatewayFilterFactory = modifyResponseBodyGatewayFilterFactory; this.bodyRewrite = bodyRewrite; } @Override public GatewayFilter apply(NameValueConfig config) { System.out.println("n JWT FILTERn"); return new OrderedGatewayFilter((exchange, chain) -> { GatewayFilter delegate = modifyResponseBodyGatewayFilterFactory.apply(new ModifyResponseBodyGatewayFilterFactory.Config() .setRewriteFunction(byte[].class, byte[].class, bodyRewrite)); return delegate.filter(exchange, chain).then(Mono.fromRunnable(() -> System.out.println("nPost JWTFilter executedn"))); }, NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER-1); } }
Global filter:
@Component public class ModifyResponseBodyFilter implements GlobalFilter, Ordered { private final ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory; private final BodyRewrite bodyRewrite; @Autowired public ModifyResponseBodyFilter(ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory, BodyRewrite bodyRewrite, ErrorWebExceptionHandler errorWebExceptionHandler) { this.modifyResponseBodyGatewayFilterFactory = modifyResponseBodyGatewayFilterFactory; this.bodyRewrite = bodyRewrite; } @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { if (exchange.getRequest().getURI().getPath().equals("/key/login")) { return exchange.getResponse().setComplete(); } GatewayFilter delegate=modifyResponseBodyGatewayFilterFactory.apply(new ModifyResponseBodyGatewayFilterFactory.Config() .setRewriteFunction(byte[].class, byte[].class, bodyRewrite)); return delegate.filter(exchange, chain).then(Mono.fromRunnable(() -> System.out.println("nPost GlobalFilter executedn"))); } @Override public int getOrder() { return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER-1; } }
Class to receive response body:
@Component class BodyRewrite implements RewriteFunction<byte[], byte[]> { @Override public Publisher<byte[]> apply(ServerWebExchange exchange, byte[] body) { String originalBody = body==null?"":new String(body); if (!ServerWebExchangeUtils.isAlreadyRouted(exchange)) { return Mono.just(originalBody.getBytes()); } else { System.out.println("------------------------------------"); System.out.println("got response body: " + originalBody); System.out.println("------------------------------------"); return Mono.just(body); } } }
application.yml
spring: cloud: gateway: routes: - id: global_route uri: http://httbin.org predicates: - Path=/key/login filters: - JWTFilter=RSA512,HS512 - id: global_route uri: http://httbin.org predicates: - Path=/** filters: - RewritePath=/service(?<segment>/?.*), ${segment} server: port: 8082
Output on jwt filter route
Stopped global filter as it is jwt filter route Post JWTFilter executed
Output on global filter route
got response body: Something Post GlobalFilter executed
So when I try to call BodyRewrite via JWTFilter it doesn’t work, but with global filter it works correctly.
Advertisement
Answer
First, you should know GatewayFilter is used for a special route, so that you should bind it to a route.GlobalFilter will take effect for all routes.
And it’s redundant that assembling a GatewayFilter with a GatewayFilter.