soul 入门 第十七章 contextpath插件

535 阅读1分钟

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);
    }