soul 入门 第十七章 contextpath插件
介绍
soul网关在对目标服务调用的时候,该插件使用 context_path
插件来重写请求路径的contextPath
使用
在 soul-admin
–> 插件管理 –> context_path
设置为开启。
在网关的 pom.xml 文件中添加 context_path
的支持。
<!-- soul context_path plugin start-->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-spring-boot-starter-plugin-context-path</artifactId>
<version>${last.version}</version>
</dependency>
<!-- soul context_path plugin end-->
在soul-admin 后台的插件列表对应的context_path 添加选择器和规则 ,主要设置 contextPath 的值。
场景
context_path插件就是对uri的contextPath重新定义,当匹配到请求后,设置自定义的contextPath,那么就会根据请求的Url截取自定义的contextPath获取真正的Url,例如请求路径为/soul/http/order, 配置的contextPath为’/soul/http’,那么真正请求的url为’/order’。
代码实现
@Override
protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
assert soulContext != null;
final String handle = rule.getHandle();
final ContextMappingHandle contextMappingHandle = GsonUtils.getInstance().fromJson(handle, ContextMappingHandle.class);
if (Objects.isNull(contextMappingHandle) || StringUtils.isBlank(contextMappingHandle.getContextPath())) {
log.error("context path mapping rule configuration is null :{}", rule);
return chain.execute(exchange);
}
//check the context path illegal
if (!soulContext.getPath().startsWith(contextMappingHandle.getContextPath())) {
Object error = SoulResultWrap.error(SoulResultEnum.CONTEXT_PATH_ERROR.getCode(), SoulResultEnum.CONTEXT_PATH_ERROR.getMsg(), null);
return WebFluxResultUtils.result(exchange, error);
}
// 重新定义contextPath 关键逻辑
this.buildContextPath(soulContext, contextMappingHandle);
return chain.execute(exchange);
}
private void buildContextPath(final SoulContext context, final ContextMappingHandle handle) {
context.setContextPath(handle.getContextPath());
if (!StringUtils.isBlank(handle.getRealUrl())) {
log.info("context path mappingPlugin replaced old :{} , real:{}", context.getRealUrl(), handle.getRealUrl());
// 如果已经计算过真正的url,返回,不再重新定义contextPath
context.setRealUrl(handle.getRealUrl());
return;
}
// 重新定义contextPath,改写realUrl
Optional<String> optional = Arrays.stream(context.getPath()
.split(handle.getContextPath()))
.reduce((first, last) -> last);
optional.ifPresent(context::setRealUrl);
}