zoukankan      html  css  js  c++  java
  • Soul 学习笔记---使用 rewrite,context-path 插件(二十)

    1.运行 context-path 插件

    我们在使用 soul 网关时,yml 文件里就配置了 contextPath,不过我们可以使用 context_path 插件进行重写,这也体现了 soul 网关的灵活配置

    登录 soul-admin 开启 context-path 插件,选择器规则配置如下

    我们使用网关 http://localhost:9195/context/http/order/findById?id=3 访问时,真正执行的 url 就是 http://192.168.1.99:8188/order/findById?id=3

    接下来看看 ContextPathMappingPlugin 是怎么执行的。

        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();
            //获取配置的 context path
            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);
            }
            //判断请求的路径是不是以我们配置的 context path 开头
            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);
            }
            //使用 context path 获取请求的url
            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());
                context.setRealUrl(handle.getRealUrl());
                return;
            }
            //获取真实的 url
            Optional<String> optional = Arrays.stream(context.getPath()
                    .split(handle.getContextPath()))
                    .reduce((first, last) -> last);
            optional.ifPresent(context::setRealUrl);
        }
    

    2.运行 rewrite 插件,规则配置如下

    这里就重写了我们的 url,真正的访问地址就被修改了。

    看下 rewrite 插件的源码,这部分比较简单,就是拿到 rewrite_uri,放到 exchange 里。接着就继续执行下一个插件。

        @Override
        protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
            String handle = rule.getHandle();
            final RewriteHandle rewriteHandle = GsonUtils.getInstance().fromJson(handle, RewriteHandle.class);
            if (Objects.isNull(rewriteHandle) || StringUtils.isBlank(rewriteHandle.getRewriteURI())) {
                log.error("uri rewrite rule can not configuration:{}", handle);
                return chain.execute(exchange);
            }
            //放到 exchange
            exchange.getAttributes().put(Constants.REWRITE_URI, rewriteHandle.getRewriteURI());
            return chain.execute(exchange);
        }
    
    

    使用是在 DividePlugin 使用的

        private String buildRealURL(final String domain, final SoulContext soulContext, final ServerWebExchange exchange) {
            String path = domain;
            //获取 rewrite 
            final String rewriteURI = (String) exchange.getAttributes().get(Constants.REWRITE_URI);
            if (StringUtils.isNoneBlank(rewriteURI)) {
                path = path + rewriteURI;
            } else {
                final String realUrl = soulContext.getRealUrl();
                if (StringUtils.isNoneBlank(realUrl)) {
                    path = path + realUrl;
                }
            }
            String query = exchange.getRequest().getURI().getQuery();
            if (StringUtils.isNoneBlank(query)) {
                return path + "?" + query;
            }
            return path;
        }
    

    这两部分的源码实现都比较简单。但却为我们使用 soul 网关时,多提供了一些选择。

  • 相关阅读:
    Using Apache Maven
    Getting Started(Google Cloud Storage Client Library)
    【iOS】PLA 3.3.12
    【Android】System.exit(0) 退出程序
    【iOS】Ineligible Devices || “无法下载应用程序”
    【iOS】No suitable application records found
    【Android】Failed to convert @drawable/picture into a drawable
    【SVN】eclipse 安装 SVN 插件
    【SVN】SVN Working copy is too old
    【Android】Android sdk content loader 0%
  • 原文地址:https://www.cnblogs.com/fightingting/p/14468793.html
Copyright © 2011-2022 走看看