携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
springcloudgateway进行请求地址转发
前文
本文内容为在使用springcloud的过程中,当需要对于请求的地址进行特殊的处理时,一种路由方案的处理。
具体方案
该方案主要是应用网关服务中gateway的特性进行处理,自定义一个过滤器并实现全局的过滤器。在过滤器中,我们要处理的核心对象则是exchange对象。而exchange对象本身则是网关用来处理请求的核心组件,其中包含了若干请求及响应的信息。而当我们想要把请求进行转发时,可能很容易想到将exchange中的request对象进行重新处理,利用新地址进行request对象的构建。但经过尝试,仅仅按照request=exchange.getRequest().mutate().path(newReqPath).build();重新构建对象,实际访问的地址依然是我们本来所填写的,并不能实现请求地址的转发功能。经过对于请求内容的比较,以及相关文档的查询,其实我们需要处理的是exchange中的属性,gatewayRequestUrl。这个属性才是实际在请求进行调用时,我们所采用的请求地址。因此进行请求转发的核心操作是需要进行该属性内容的变更,也就是如下的代码:
exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR,URI.create(newPath));
经过上述操作,即可将当前请求根据需要路由到我们所需要的请求地址当中。具体的原理还请查看源码了解。
完整的代码实现逻辑如下,核心部分也就是上述的内容。
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 该步骤可选。可以传递给下游服务器,⽤于业务处理
ServerHttpRequest requestBase = exchange.getRequest();
ServerWebExchangeUtils.addOriginalRequestUrl(exchange,requestBase.getURI());
ServerHttpRequest request;
String basePath = null;
String newReqPath = null;
Boolean needChange = false;
for (int i = 0; i < this.gatewayFilterProperties.getBaseUrl().size(); i++) {
basePath = this.gatewayFilterProperties.getBaseUrl().get(i);
if(basePath.equals(requestBase.getPath().value())){
if(this.gatewayFilterProperties.getNewUrl().size() > i){
newReqPath = this.gatewayFilterProperties.getNewUrl().get(i);
}else{
newReqPath = basePath;
}
needChange = true;
break;
}
}
if(needChange){
String newPath = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR).toString().replace(basePath,newReqPath);
request = exchange.getRequest().mutate().path(newReqPath)
.build();
exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR,URI.create(newPath));
ServerWebExchange build = exchange.mutate().request(request).build();
return chain.filter(build);
}else {
return chain.filter(exchange);
}
}