Jackson streaming api & WebFlux response body in Spring Cloud Gateway

Viewed 620

I'm pretty new to Spring Cloud Gateway and Spring WebFlux.

I have a requirement where I need to gather all the IDs of the data elements in the response for logging purposes.

I have done so in a very memory-intensive way, by reading the DataBuffer into a byte array, parsing it and then wrapping it into a DataBuffer and passing it along.

However, this isn't very viable when the responses are big and I am making use of the Jackson Streaming API so it seems silly.

Anyone have any tips on how to achieve this? All the examples I have seen seem to do it in a similar way, by buffering the entire response in memory.

Current version (Groovy):

class DataIdResponseHandler extends ServerHttpResponseDecorator {

    final DataBufferFactory dataBufferFactory

    DataIdResponseHandler(ServerHttpResponse delegate) {
        super(delegate)
        dataBufferFactory = delegate.bufferFactory()
    }

    @Override
    Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
        Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body

        return super.writeWith(fluxBody.map { dataBuffer ->
            byte[] content = new byte[dataBuffer.readableByteCount()]
            dataBuffer.read(content)

            List<String> dataIds = DataIdParser.parseFromByteArray(content)
            DataIdCollector.add(dataIds)

            return dataBufferFactory.wrap(content)
        })
    }

}

Reactive version of the above would method would be:

return super.writeWith(fluxBody.doOnNext {  DataBuffer dataBuffer ->
            List<String> dataIds = DataIdParser.parseFromByteArray(dataBuffer.toString(Charset.defaultCharset()).bytes)
            Logger logger = LoggerFactory.getLogger(DataIdResponseFilter)
            logger.info(dataIds.toString())
        })

Oddly enough, if there's an interaction with the DataBuffer where you access the asInputStream() and you read from that it'll empty the DataBuffer and the actual response will be empty. If you use the toString() method, which obviously also reads from the DataBuffer, the buffer and hence body will still be complete.

0 Answers
Related