如何在Spring Gateway中获取响应主体

huangapple go评论71阅读模式
英文:

How to get response body in Spring Gateway

问题

我正在使用Spring Cloud Gateway过滤器,并且需要获取响应体以进行日志记录。
我理解这可能有问题,因为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
---------------------------
英文:

I'm working with spring cloud gateway filters and need to get response body to log it.
I understand that it's problematic, as spring gateway is built on spring reactor, but nevertheless I'm looking for any way to do this.

Have global filter, code:


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&lt;byte[], byte[]&gt; {

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

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

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

    @Override
    public Mono&lt;Void&gt; filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println(&quot;---------------------------&quot;);
        System.out.println(&quot;       GLOBAL FILTER&quot;);
        System.out.println(&quot;---------------------------&quot;);
        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;
    }

In the console I only get this output about 30 times in a row and no output with phrase "APPLY METHOD".

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

答案1

得分: 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 {
            // 当已经路由时,它是响应体
        }
    }
}

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;
    }
}
英文:

im a rookie,both in English and Programing.
here is a way but may not elegant:
create a modifyResponseBodyFilter with the ModifyResponseBodyGatewayFilterFactory, and implement the RewriteFunction.

public class BodyRewrite implements RewriteFunction&lt;byte[], byte[]&gt; {
    @Override
    public Publisher&lt;byte[]&gt; apply(ServerWebExchange exchange, byte[] body) {
        String originalBody = body==null?&quot;&quot;: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&lt;Void&gt; 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;
    }
}

huangapple
  • 本文由 发表于 2020年10月20日 13:40:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/64439102.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定