SpringCloud-Gateway的请求头部自定义实践
在微服务框架中,SpringCloud-Gateway的方式几乎是首选。也得益于Reactor的实现,使得SpringCloud-Gateway的性能在所有的网关平台中脱颖而出。在一次项目实践中,需要自定义请求的头部信息,故来了一趟学习之旅。
一个请求在网关中的执行顺序是经过一系列的过滤器链进行链式调用并执行的。SpringCloud-Gateway中的过滤器又分为全局过滤器(GlobalFilter)和网关过滤器(XXXGatewayFilterFactory)又称路由过滤器,对于链式调用过滤器执行顺序见下图:
上图列出了SpringCloud-Gateway中框架带的过滤器及其优先级,其值越小,优先级越高。全局过滤器位置比较灵活,通过控制优先级,可以指定具体的执行顺序;但是,网关过滤器的执行顺序是有限制的,它的优先级范围在大于0且小于10150(这个版本依赖于框架版本,该值出自spring-cloud-starter-gateway-3.1.3),就算程序中优先级强制指定其他范围,也不会生效。注意,框架自带的过滤器的优先级也改变不了,或者不能被覆盖,强行指定优先级也会不生效的。另外,过滤器分为前置过滤和后置过滤,像拦截器中的Interceptor中的preHandle和postHandle,只不过写法不一样,因为SpringCloud-Gateway使用的reactor模式,有点模糊的小可爱,可以去了解了解。
上面学习了SpringCloud-Gateway的优先级后,来解决实际的问题。
抛出问题:目的是需要自定义请求的头部信息,只能返回指定的头部才能正确解析相关请求(用于和硬件终端通信),在经过SpringCloud-Gateway框架后,一个请求的头部带了很多额外信息,导致终端数据接受的时候解析失败。
问题发现:通过断点调试后,发现多了很多头部信息,一部分是网关整合了SpringSecurity,在经过过滤器链式调用后增加了很多额外头部,另一部分则来自http请求的,如Keep-Alive和Connection。
问题解决:首先是利用断点方式,发现都是调用了_NettyWriteResponseFilter_(优先级为-1)这个全局过滤器的后置方法后才添加的头部信息,因此使用路由过滤器是完成不了的,因为路由过滤器作用域小于全局过滤器的,作用范围更小。故需要实现全局过滤器去处理增加的头部,代码如下:文章来源:https://www.toymoban.com/news/detail-699514.html
@Slf4j
@Component
public class CustomHeaderGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange).doFirst(() -> {
if (exchange.getRequest().getPath().value().contains(xxx)) {
exchange.getResponse().beforeCommit(() -> Mono.fromRunnable(() -> {
HttpHeaders headers = exchange.getResponse().getHeaders();
headers.remove("Cache-Control");
headers.remove("Pragma");
headers.remove("Expires");
headers.remove("X-Content-Type-Options");
headers.remove("X-Frame-Options");
headers.remove("X-XSS-Protection");
headers.remove("Referrer-Policy");
}));
}
});
}
/**
* 指定在网关过滤器中的顺序,-100的优先级在NettyWriteResponseFilter前面,使得前置过滤在其之前执行,在其后置过滤之后执行(详细见springCloud过滤器规则)
* @return 顺序
*/
@Override
public int getOrder() {
return -100;
}
}
在上述代码中,值得注意的是去掉不需要的头部信息,也不是直接操作某个请求的HttpHeader,因为HttpHeader对应一个请求,每个请求它有自己管理头部信息的一个过程,只有在允许的操作过程中,才能对其修改。
上图中每个请求会对应四种阶段,在COMMITTED状态以后,是不允许进行编辑操作的,但可以查看
可以清晰看出在COMMITTED状态以后拿到的就是不可编辑的Header,是不允许对其写操作的
上图是应用COMMITTED的一个时机,所以结合我们的需求,就必须在COMMITTED状态应用之前完成自定义的头部处理,但是手动控制这个自定义的时机,还是非常困难的,你不确定这个doCommit()方法在什么时候调用,但是源码中是给我们提供了一个方法
在doCommit()这个方法中我们也看到了对commitActions这个容器进行了调用和处理,所以只要我们提前添加需要对Header处理的逻辑并放到这个容器中,那么在请求的整个处理过程中就会把我们的操作编织进去,从而就完成了我们自定义的一些操作。文章来源地址https://www.toymoban.com/news/detail-699514.html
到了这里,关于SpringCloudGateway框架下的http请求头部自定义实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!