spring cloud gateway自定义filter获取request

最近网上查询关于spring cloud gateway获取request的各种资料,尝试后发现都存在一些问题,结合几篇文章,翻看了一部分源码,总结出了一套个人认为稍微好一些的解决方法(还是有些问题)。

@Slf4j
@Component
public class PostBodyGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        HttpHeaders headers = request.getHeaders();
        String method = request.getMethodValue();
        String contentType = headers.getFirst("Content-Type");
        //去除文件上传
        if (!Strings.isNullOrEmpty(contentType) && contentType.startsWith("multipart/form-data")) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        if ("POST".equalsIgnoreCase(method)) {  //判断是否为POST请求
            ServerRequest serverRequest = new DefaultServerRequest(exchange);
//            Flux<String> flux = serverRequest.bodyToFlux(String.class);
//            ServerHttpRequest newRequest = new ServerHttpRequestDecorator(request) {
//                private StringBuilder respBody=new StringBuilder();
//                @Override
//                public HttpHeaders getHeaders() {
//                    HttpHeaders httpHeaders = new HttpHeaders();
//                    httpHeaders.putAll(super.getHeaders());
//                    httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
//                    return httpHeaders;
//                }
//                @Override
//                public Flux<DataBuffer> getBody() {
//                    return flux.map(body -> {
//                        respBody.append(body).append("\n");
//                        NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
//                        return nettyDataBufferFactory.wrap(body.getBytes());
//                    }).doOnComplete(()-> log.info("\n请求url={},请求参数={}\n,headers{}",super.getPath().value(),respBody.toString(),super.getHeaders()));
//                }
//            };
//            return chain.filter(exchange.mutate().request(newRequest).build());
            Mono<String> bodyToMono = serverRequest.bodyToMono(String.class);
            return bodyToMono.flatMap(body -> {
                log.info(body);
                ServerHttpRequest newRequest = new ServerHttpRequestDecorator(request) {
                    @Override
                    public HttpHeaders getHeaders() {
                        HttpHeaders httpHeaders = new HttpHeaders();
                        httpHeaders.putAll(super.getHeaders());
                        httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
                        return httpHeaders;
                    }

                    @Override
                    public Flux<DataBuffer> getBody() {
                        NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
                        DataBuffer bodyDataBuffer = nettyDataBufferFactory.wrap(body.getBytes());
                        return Flux.just(bodyDataBuffer);
                    }
                };
                return chain.filter(exchange.mutate().request(newRequest).build());
            });
        }
        return chain.filter(exchange);
    }

代码参考了源码类(ModifyRequestBodyGatewayFilterFactory),get获取request参数在这里不再讨论,网上资料很多哈。着重说下post获取方式

Mono<String> bodyToMono = serverRequest.bodyToMono(String.class);
return bodyToMono.flatMap(body -> {
    log.info(body);
    ServerHttpRequest newRequest = new ServerHttpRequestDecorator(request) {
        @Override
        public HttpHeaders getHeaders() {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.putAll(super.getHeaders());
            httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
            return httpHeaders;
        }

        @Override
        public Flux<DataBuffer> getBody() {
            NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
            DataBuffer bodyDataBuffer = nettyDataBufferFactory.wrap(body.getBytes());
            return Flux.just(bodyDataBuffer);
        }
    };
    return chain.filter(exchange.mutate().request(newRequest).build());
});

通过上面的代码可以解决请求体过长被截断的问题,并且可以在其中修改请求参数,做一些业务相关逻辑(比如参数校验,参数增删等),但是这种方式有个问题是当请求体为空时获取不到响应体。下面这段代码可以解决这个问题,但是只能做一些请求日志记录。

Flux<String> flux = serverRequest.bodyToFlux(String.class);
//            ServerHttpRequest newRequest = new ServerHttpRequestDecorator(request) {
//                private StringBuilder respBody=new StringBuilder();
//                @Override
//                public HttpHeaders getHeaders() {
//                    HttpHeaders httpHeaders = new HttpHeaders();
//                    httpHeaders.putAll(super.getHeaders());
//                    httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
//                    return httpHeaders;
//                }
//                @Override
//                public Flux<DataBuffer> getBody() {
//                    return flux.map(body -> {
//                        respBody.append(body).append("\n");
//                        NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
//                        return nettyDataBufferFactory.wrap(body.getBytes());
//                    }).doOnComplete(()-> log.info("\n请求url={},请求参数={}\n,headers={}",super.getPath().value(),respBody.toString(),super.getHeaders()));
//                }
//            };
//            return chain.filter(exchange.mutate().request(newRequest).build());

因为请求体会被截断,这里用stringbuider连接

ps:对flux这种操作还不太习惯,另外感觉spring cloud gateway的坑还是有点多的- -。

如果各位有更好的解决方法,希望互相交流一下。。。

转载于:https://my.oschina.net/u/4023883/blog/2997179

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值