Summary of small pits encountered by the spring cloud gateway interceptor

Keywords: Spring WebFlux less

Many friends may encounter the following problems when using spring cloud gateway

How to read Post request body in spring cloudgateway
    private BodyInserter getBodyInserter(ServerWebExchange exchange) {
        ServerRequest serverRequest = new DefaultServerRequest(exchange);
        Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
                .flatMap(body -> {
                   //The body here is the request body of Post
                });
        BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
        return bodyInserter;
    }
The Post request parameter in SpringCloudGateway can only be read once

This is because Gateway uses spring Webflux by default. To solve this problem, we need to reconstruct a request to replace the original request

        HttpHeaders headers=new HttpHeaders();
        CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
        ServerHttpRequestDecorator decorator = this.getServerHttpRequestDecorator(exchange,outputMessage);
       ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
                exchange.getRequest()) {
            @Override
            public Flux<DataBuffer> getBody() {
                return outputMessage.getBody();
            }
        };

After the server httprequest decorator is built, you need to replace the original request with the following method in the interceptor

                    return chain.filter(exchange.mutate().request(decorator).build());

How to read the return data of the post segment service in spring cloudgateway

It is consistent with the above idea of replacing request. Replace response

private ServerHttpResponse getServerHttpResponse(ServerWebExchange exchange) {
        ServerHttpResponse originalResponse = exchange.getResponse();
        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {


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

                Flux<DataBuffer> flux = null;
                if (body instanceof Mono) {
                    Mono<? extends DataBuffer> mono = (Mono<? extends DataBuffer>) body;
                    body = mono.flux();

                }
                if (body instanceof Flux) {
                    flux = (Flux<DataBuffer>) body;
                    return super.writeWith(flux.buffer().map(dataBuffers -> {
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                        dataBuffers.forEach(i -> {
                            byte[] array = new byte[i.readableByteCount()];
                            i.read(array);
                            DataBufferUtils.release(i);
                            outputStream.write(array, 0, array.length);
                        });
                        String result = outputStream.toString();
                        try {
                            if (outputStream != null) {
                                outputStream.close();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        log.info("Back end return data:{}", result);
                        return bufferFactory.wrap(result.getBytes());
                    }));
                }

                log.info("Degraded processing return data:{}" + body);
                return super.writeWith(body);
            }

        };
        return decoratedResponse;
    }

The upper part is to get a new response. After getting a new response, it is the same as the previous routine. Do this:

                    return chain.filter(exchange.mutate().request(decorator).response(decoratedResponse).build());

Some students may encounter that even if I rewrite the response according to the above method, they cannot read the return data. This may be because there is a problem with the priority configuration of the interceptor. Just implement the Ordered interface and rewrite the getOrder method, and then set the priority less than - 1

@Override
    public int getOrder() {
        return -2;
    }

Posted by Scorptique on Thu, 28 Nov 2019 06:25:34 -0800