【问题标题】:How to get response body in Spring Gateway如何在 Spring Gateway 中获取响应正文
【发布时间】:2021-02-02 22:10:28
【问题描述】:

我正在使用 spring 云网关过滤器,需要获取响应正文来记录它。 我知道这是有问题的,因为 spring gateway 是建立在 spring reactor 上的,但是我正在寻找任何方法来做到这一点。

有全局过滤器,代码:


import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class BodyRewrite implements RewriteFunction<byte[], byte[]> {

    @Override
    public Publisher<byte[]> apply(ServerWebExchange exchange, byte[] body) {
        System.out.println("-------------------------");
        System.out.println("       APPLY METHOD");
        System.out.println("-------------------------");
        String originalBody = body==null?"":new String(body);
        if (!ServerWebExchangeUtils.isAlreadyRouted(exchange)) {
            return Mono.just(originalBody.getBytes());
        } else {
            System.out.println("RESPONSE: " + originalBody);
        }

        return new Publisher<byte[]>() {
            @Override
            public void subscribe(Subscriber<? super byte[]> subscriber) {
                
            }
        };
    }
}

@Component
class ModifyResponseBodyFilter implements GlobalFilter, Ordered {
    @Autowired
    private ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory;
    @Autowired
    private BodyRewrite bodyRewrite;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("---------------------------");
        System.out.println("       GLOBAL FILTER");
        System.out.println("---------------------------");
        GatewayFilter delegate=modifyResponseBodyGatewayFilterFactory.apply(new ModifyResponseBodyGatewayFilterFactory.Config()
                .setRewriteFunction(byte[].class, byte[].class, bodyRewrite));
        return delegate.filter(exchange, chain);
    }

    @Override
    public int getOrder() {
        return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER-1;
    }

在控制台中,我仅连续获得大约 30 次此输出,并且没有带有短语“APPLY METHOD”的输出。

---------------------------
       GLOBAL FILTER
---------------------------

【问题讨论】:

    标签: java spring spring-cloud-gateway


    【解决方案1】:

    我是个菜鸟,英语和编程都懂。 这是一种方法,但可能不优雅: 使用 ModifyResponseBodyGatewayFilterFactory 创建一个 modifyResponseBodyFilter,并实现 RewriteFunction。

    public 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 {
            // its the reponse body when already routed
            }
        }
    }
    
    public class ModifyResponseBodyFilter implements GlobalFilter, Ordered {
        @Autowired
        private ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory;
        @Autowired
        private BodyRewrite bodyRewrite;
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            GatewayFilter delegate=modifyResponseBodyGatewayFilterFactory.apply(new ModifyResponseBodyGatewayFilterFactory.Config()
                    .setRewriteFunction(byte[].class, byte[].class, bodyRewrite));
            return delegate.filter(exchange, chain);
        }
    
        @Override
        public int getOrder() {
            return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER-1;
        }
    }
    

    【讨论】:

    • apply方法的else子句应该写什么?
    • 你可以只记录'originalBody'
    • 报错“应用上下文中某些bean的依赖形成循环:”我在描述中添加了图片。
    • 对不起,我在中国看不到ht图片。你能粘贴你的代码吗?顺便说一下,我上面粘贴的代码经过测试是可以的。你可以试着把依赖关系搞清楚。
    • 我修复了错误,它没有调用apply方法,所以没有得到响应体,是我做错了什么,还是你没有尝试这段代码?
    猜你喜欢
    • 2022-10-14
    • 1970-01-01
    • 2018-10-10
    • 2017-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    相关资源
    最近更新 更多