Java Spring云网关:修改的响应主体被截断

Java Spring云网关:修改的响应主体被截断,java,spring,spring-cloud,gateway,reactor-netty,Java,Spring,Spring Cloud,Gateway,Reactor Netty,我已经对SpringCloudGateway进行了一些实验,我正在尝试修改响应主体。使用响应装饰器,我可以看到主体被修改,但是,缓冲区大小仍然是原始响应的大小。有没有办法将缓冲区大小扩展到新响应体的大小 public class ModifyBodyGatewayFilterImpl implements GatewayFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, Ga

我已经对SpringCloudGateway进行了一些实验,我正在尝试修改响应主体。使用响应装饰器,我可以看到主体被修改,但是,缓冲区大小仍然是原始响应的大小。有没有办法将缓冲区大小扩展到新响应体的大小

public class ModifyBodyGatewayFilterImpl implements GatewayFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        logger.info("\n\nexchange.getAttributes():\n {}\n\n", exchange.getAttributes());

        ServerHttpResponse response = exchange.getResponse();
        DataBufferFactory dataBufferFactory = response.bufferFactory();

        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) {

            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {

                Flux<? extends DataBuffer> flux = (Flux<? extends DataBuffer>) body;

                Flux<? extends DataBuffer> f = flux.flatMap( dataBuffer  -> {

                    byte[] origRespContent = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(origRespContent);

                    System.out.println("content::: " + (new String(origRespContent)));

                    //alocating a new buffer size does not help.
                    DataBuffer b = dataBufferFactory.allocateBuffer(256);
                    b.write("0123456789abcdefg".getBytes());

                    return Flux.just(b);
                });

                return super.writeWith(f);
            }
        };

        ServerWebExchange swe = exchange.mutate().response(decoratedResponse).build();
        return chain.filter(swe);
    }
}
公共类ModifyBodyGatewayFilterImpl实现GatewayFilter{
@凌驾
公共Mono筛选器(服务器WebExchange exchange、网关筛选器链){
logger.info(“\n\nexchange.getAttributes():\n{}\n\n”,exchange.getAttributes());
ServerHttpResponse response=exchange.getResponse();
DataBufferFactory DataBufferFactory=response.bufferFactory();
ServerHttpResponseDecorator decoratedResponse=新的ServerHttpResponseDecorator(响应){
@凌驾

public Mono writeWith(Publisher我使用buffer()方法解决了这个问题:

公共类ModifyBodyGatewayFilterImpl实现GatewayFilter{
@凌驾
公共Mono筛选器(服务器WebExchange exchange、网关筛选器链){
ServerHttpResponse response=exchange.getResponse();
DataBufferFactory DataBufferFactory=response.bufferFactory();
ServerHttpResponseDecorator decoratedResponse=新的ServerHttpResponseDecorator(响应){
@凌驾
公共Mono writeWith(Publisher您可以使用此

// prepare the mono to be returned
    DataBufferFactory dataBufferFactory = exchange.getResponse().bufferFactory();
    ObjectMapper objMapper = new ObjectMapper();
    byte[] obj;
    try {
        obj = objMapper.writeValueAsBytes(response);
        return exchange.getResponse().writeWith(Mono.just(obj).map(r -> dataBufferFactory.wrap(r)));
    } catch (JsonProcessingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return exchange.getResponse().setComplete();

如果
响应
是您想要的任何对象,它必须是可序列化的。

您还需要重写
内容长度
标题。 像这样:

byte[] bytes = "0123456789abcdefg".getBytes();
DataBuffer b = dataBufferFactory.wrap(bytes);
response.getHeaders().setContentLength(bytes.length);

我希望这有帮助:)

我遇到了同样的问题,数据是在两个缓冲区中接收的。基于@Alex解决方案,我通过加入但不使用
字节输出扩展
对其进行了改进

在我的解决方案中,我使用了
DefaultDataBufferFactory
join()
方法

@Override
public Mono<Void> writeWith(final Publisher<? extends DataBuffer> body) {

    if (body instanceof Flux) {
        Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
        return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
            var joinedBuffers = new DefaultDataBufferFactory().join(dataBuffers);
            
            byte[] content = new byte[joinedBuffers.readableByteCount()];
            joinedBuffers.read(content);
            final var responseBody = new String(content, StandardCharsets.UTF_8);
            // modify body
            return bufferFactory.wrap(responseBody.getBytes());
        }));
    }
    return super.writeWith(body);
}
@覆盖

公共Mono writeWith(最终发布者我正在寻找一种通用的方法来修改响应(我基本上是在修改JSON正文),而不需要处理
流量
(也就是说,
Mono
很好)因此,我开始研究SCG的
ModifyResponseBodyGatewayFilterFactory
今天在来自和来自的信息的帮助下做了什么

我能够想出一个快速而肮脏的解决方案并编写出来。基本上,我只是修改了
ModifyResponseBodyGatewayFilterFactory
今天正在做的事情,并针对我的用例对其进行了一些更改。解决方案的一部分如下:

@SuppressWarnings(“未选中”)
@凌驾

公共单写(我用这种方法得到了确切的结果。你能在Spring Cloud Gateway中实现这一点吗?这不仅仅是一个孤立的测试?你有没有将响应修改为比初始响应更大的响应?嘿@Matt,是的,我能使它以更大的响应工作。好吧,如果你在SCG中实现,那么我看不出问题是什么。使用最新的快照