Gateway学习笔记一 responseBody和resquestBody的获取 | 您所在的位置:网站首页 › databufferfactory › Gateway学习笔记一 responseBody和resquestBody的获取 |
1 引言
笔者在实现开发者服务网关模块的任务过程中,遇到下列需求(有关requestBody和responseBody部分): 对所有的请求,取出requestBody作为参数,调用鉴权接口 不影响requsetBody前提下,路由转发 从路由转发的回复中取出responseBody,作为参数调用统计接口gateway的工作流程如图,filter的传递中,我们通常用ServerWebExchange来获取请求、回复、相关参数等。 我最初的思路,想当然地希望从ServerWebExchange中直接使用exchange.getXXX()方法获取body,
然而实际上从exchange中无法读取具体的requestBody和responseBody。
2 原因分析 2.1 ServerWebExchange ServerWebExchange命名为服务网络交换器,存放着重要的请求-响应属性、请求实例和响应实例等等,有点像Context的角色
注意到ServerWebExchange.mutate()方法,通过使用decorator将exchange重新包装起来。 ServerWebExchange实例可以理解为不可变实例,如果我们想要修改它,需要通过mutate()方法生成一个新的实例
2.2 ServerHttpRequest ServerHttpRequest实例是用于承载请求相关的属性和请求体。Spring Cloud Gateway中底层使用Netty处理网络请求,通过追溯源码,可以从ReactorHttpHandlerAdapter中得知ServerWebExchange实例中持有的ServerHttpRequest实例的具体实现是ReactorServerHttpRequest ReactorServerHttpRequest的父类AbstractServerHttpRequest中初始化内部属性headers的时候把请求的HTTP头部封装为只读的实例,所以不能直接从ServerHttpRequest实例中直接获取请求实例并且进行修改。
如果要修改,需要使用2.1中提到的mutate方法重新包装生成一个新实例,具体的实现在下面介绍。 3 解决方案 3.1 基于ReadBodyPredicateFactory的实现 ReadBodyPredicateFactory源码指出,body只允许从request中读取一次,再次读取时会抛异常。因此对于已经读取过的requestBody,为了不影响后期,需要对请求体内容进行二次包装,即第一次读取内容进行缓存,后面对同个请求体的读取则直接返回缓存内容。
下面是router提供的body读取方法,其中bodyToMono方法我们可以拿到完整的body内容,并返回指定类型inClass,body即为读取到的请求体内容对应的数组。 下面是仿照ReadBodyPredicateFactory的方式获取body的解决方案。 1 public final List |
CopyRight 2018-2019 实验室设备网 版权所有 |