springcloud gateway 获取post请求体Json分段导致不全的解决方案
发布日期:2021-09-18 00:51:45 浏览次数:8 分类:技术文章

本文共 2686 字,大约阅读时间需要 8 分钟。

springcloud gateway 获取post请求体Json分段导致不全的解决方案

开发版本
springboot 2.0.8.RELEASE + springcloud Finchley.SR2 + spring cloud gateway

前端客户端采用post发送请求,content_type: application/json,

spring cloud gateway需要从request的中取出body进行网关的鉴权处理,然后把处理之后的数据重新封装到body中转发给下游业务系统,
最之前的方式采用的是以下方式读取请求体:
 AtomicReference<String> bodyRef = new AtomicReference<>();//缓存读取的request body信息
               Flux<DataBuffer> fluxBody = exchange.getRequest().getBody();
               fluxBody.subscribe(buffer -> {
                     CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
                     DataBufferUtils.release(buffer);
                     bodyRef.set(charBuffer.toString());
               });
               String bodyStr = bodyRef.get();

偶尔前端提出验签失败,检查上送请求体报文时发现错误:网关获取的body不完整。

尝试了网上的写法来获取body,于是改成了以下的写法来亲自验证,偶尔还是发现网关获取的body体不完整,说明此方法还是不行,有坑。

    private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){

        //获取请求体
        Flux<DataBuffer> body = serverHttpRequest.getBody();
        StringBuilder sb = new StringBuilder();
        body.subscribe(buffer -> {
            List<String> list = Lists.newArrayList();
            byte[] bytes = new byte[buffer.readableByteCount()];
            buffer.read(bytes);
            DataBufferUtils.release(buffer);
            String bodyString = new String(bytes, StandardCharsets.UTF_8);
            sb.append(bodyString);
        });
        return sb.toString();
    }

继续查询相关资料,有几篇文件介绍了要解决获取body不完整的情况得代用code路由的方式来配置,而不能采用yml,于是继续尝试。
    @Bean
    public RouteLocator tpauditRoutes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route(r ->r
                        .readBody(String.class, requestBody -> {
                            //log.info("requestBody is {}", requestBody);
                            // 这里 r.readBody做了一个前置语言,这样就可以在filter中通过exchange.getAttribute("cachedRequestBodyObject"); 获取body体
                            return true;
                        }).and()
                        .path("/gw/xxxdmin/**")
                        .filters(f -> f.stripPrefix(1)
                                       .hystrix(h -> h.setName("Hystrix").setFallbackUri("forward:/timeoutfallback")))
                        .uri("lb://ADMIN/")
                )
                .route(r ->r
                        .readBody(String.class, requestBody -> {
                            //log.info("requestBody is {}", requestBody);
                            // 这里 r.readBody做了一个前置语言,这样就可以在filter中通过exchange.getAttribute("cachedRequestBodyObject"); 获取body体
                            return true;
                        }).and()
                        .path("/gw/xxxapp/**")
                        .filters(f -> f.stripPrefix(1)
                                       .hystrix(h -> h.setName("Hystrix").setFallbackUri("forward:/timeoutfallback")))
                        .uri("lb://APP/")
                )

                .build();

    }

然后移除yml中配置的路由:

      routes:
          
        - id:  xxxAPP
          uri: lb://xxxAPP
          predicates:
          - Path=${server.servlet.context-path}/xxxapp/**
          filters:
          - StripPrefix=1
          - name: RequestRateLimiter
            args:
              redis-rate-limiter.replenishRate: 1 #允许用户每秒处理多少个请求
              redis-rate-limiter.burstCapacity: 1 #令牌桶的容量,允许在一秒钟内完成的最大请求数
              key-resolver: "#{@addressKeyResolver}" #使用SpEL按名称引用bean
              # 降级配置
          - name: Hystrix
            args:
              name: default
              fallbackUri: forward:/timeoutfallback

业务处理过滤器中通过String bodyStr = exchange.getAttribute("cachedRequestBodyObject");方法获取请求体,

最终问题得以解决。

但本人喜欢采用yml配置文件的形式来做路由,所以对于yml路由的配置,此坑还需要进一步的排查解决。

 

转载地址:https://blog.csdn.net/yucaifu1989/article/details/105121886 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:springcloud gateway GlobalFilter 签名校验,获取Post请求体
下一篇:springcloud Gateway 自定义过滤器例子

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月02日 17时47分22秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章