Spring Cloud Gateway:修改后的响应主体被截断

问题描述 投票:2回答:2

我一直在试验Spring Cloud Gateway,我正在尝试修改响应体。使用响应装饰器,我能够看到主体被修改,但是,缓冲区大小仍然是原始响应的大小。有没有办法将缓冲区大小扩展到新响应主体的大小?

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);
    }
}

示例:预期的重写响应是0123456789abcdefg如果原始内容是11个字节<p>test</p>,则重写的响应将被截断为0123456789a

java spring spring-cloud gateway reactor-netty
2个回答
1
投票

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

public class ModifyBodyGatewayFilterImpl implements GatewayFilter {

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


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

    ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) {

      @Override
      public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
        if (body instanceof Flux) {
          Flux<? extends DataBuffer> flux = (Flux<? extends DataBuffer>) body;

          return super.writeWith(flux.buffer().map(dataBuffers -> {
            ByteOutputStream outputStream = new ByteOutputStream();
            dataBuffers.forEach(i -> {
              byte[] array = new byte[i.readableByteCount()];
              i.read(array);
              outputStream.write(array);
            });
            outputStream.write("0123456789abcdefg".getBytes());
            return dataBufferFactory.wrap(outputStream.getBytes());
          }));
        }
        return super.writeWith(body);
      }
    };

    ServerWebExchange swe = exchange.mutate().response(decoratedResponse).build();
    return chain.filter(swe);
  }
}

它应该将所有响应块放在缓冲区中,当磁通完成时应释放缓冲区。


1
投票

你可以用它

// 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();

其中response是您想要的任何对象,它必须是可序列化的。

© www.soinside.com 2019 - 2024. All rights reserved.