Summary of small pits encountered by SpringCloud Gateway interceptor

Many friends may have encountered the following problems when using SpringCloudGateway

How to read Post request body in SpringCloudGateway
    private BodyInserter getBodyInserter(ServerWebExchange exchange) {
        ServerRequest serverRequest = new DefaultServerRequest(exchange);
        Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
                .flatMap(body -> {
                   //这里的body就是Post的请求体
                });
        BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
        return bodyInserter;
    }
Post request parameters in SpringCloudGateway can only be read once

This is because the Gateway uses Spring Webflux by default. To solve this problem, it is necessary 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();
            }
        };

When the ServerHttpRequestDecorator is constructed, the following method needs to be used in the interceptor to replace the original request

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

How to read the return data of the back-end service in SpringCloudGateway

Consistent with the idea of ​​replacing the request above, just replace the 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("后端返回数据:{}", result);
                        return bufferFactory.wrap(result.getBytes());
                    }));
                }

                log.info("降级处理返回数据:{}" + body);
                return super.writeWith(body);
            }

        };
        return decoratedResponse;
    }

The above is to get a new response. After getting the new response, it is the same as the previous routine, so do this:

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

Some students may encounter that even if the response is rewritten according to the above method, the returned data cannot be read. The reason may be that there is a problem with the priority configuration of the interceptor. It is only necessary to implement the Ordered interface and rewrite the getOrder method. , and then set the priority to less than -1

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

1

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324084700&siteId=291194637