【问题标题】:Is it possible to configure Spring Cloud Gateway with a Rewrite rule for Vue Router's history mode?是否可以为 Vue Router 的历史模式配置带有重写规则的 Spring Cloud Gateway?
【发布时间】:2020-11-27 15:23:44
【问题描述】:

我将 Spring Cloud Gateway 用作 API 网关,也用作托管 Vue.js SPA 的静态文件 (html/js/css) 的网络服务器。

Preclaimer:由于组织限制,我无法更改这个(糟糕的)架构。

目前,我正在使用默认的 Vue 路由器 hash 模式,这意味着 Vue 应用程序的客户端路由是通过 URL 哈希完成的,例如

http://hostname/#/route?parameter1=true

由于 Spring Cloud Gateway 还充当身份验证网关,因此它重定向到 OAuth2/OpenID SSO 服务器,并通过这样做,在重定向后丢弃 URL 哈希的路由信息​​。

我正在尝试通过切换到 Vue Router's history mode 来改变这种行为,这将启用类似的 URL

http://hostname/route?parameter1=true

因此,路由信息将“幸存”SSO 重定向。

为此,Vue 路由器文档包括 some examples for additional Webserver configuration (like mod_rewrite for Apache etc.)

遗憾的是,我的特殊情况没有包含示例;-)

我扫描了Spring Cloud Gateway 的文档,但没有找到与此案例匹配的内容。

简而言之:

是否可以配置 Spring Cloud Gateway 以匹配 Vue Router 的历史模式要求?

【问题讨论】:

    标签: vue.js mod-rewrite vue-router spring-cloud-gateway reactor-netty


    【解决方案1】:

    您可以从 Spring Boot 方面修复它。我的意思是,你可以:

    1. 启用 Vue 路由器历史模式,如文档 here 中所述
    2. 像这样构建一个 Spring Boot 转发控制器:
            @RequestMapping(value = "{_:^(?!index\\.html|api).$}")
            public String redirectApi() {
                LOG.info("URL entered directly into the Browser, so we need to redirect...");
                return "forward:/";
            }
    

    它基本上将所有路由转发到前端,除了://index.html/api/api/**

    Here你可以找到更详细的例子。

    【讨论】:

    • 谢谢,但遗憾的是我不能用经典的 Spring Boot Servlet 处理程序来做到这一点,因为 Spring Cloud Gateway 使用 Webflux。使用 Webflux 我尝试使用 RouterFunctions.route(RequestPredicates.GET("{_:^((?!index\\.html|api).)*$}") 产生异常: java.lang.IllegalArgumentException: No约束正则表达式中允许的捕获组:^((?!index\.html|api).)*$
    【解决方案2】:

    可以通过自定义RouterFunction来完成:

    @Bean
    public RouterFunction<ServerResponse> vueHistoryModeCatchAllRoute(
            @Value("classpath:/static/index.html") final Resource indexHtml) {
        HandlerFunction<ServerResponse> serveIndexHtmlFunction = request -> ok().contentType(MediaType.TEXT_HTML)
                .bodyValue(indexHtml);
        String firstApiSegmentExcludes = "api|actuator|js|img|css|fonts|favicon\\.ico";
        return route(GET("/{path:^(?!" + firstApiSegmentExcludes + ").*}"), serveIndexHtmlFunction)
                .and(route(GET("/{path:^(?!" + firstApiSegmentExcludes + ").*}/**"),
                        serveIndexHtmlFunction));
    }
    

    这将为所有与排除的路径之一 (firstApiSegmentExcludes) 不匹配的请求提供 index.html(包含 Vue.js 应用程序)。

    【讨论】:

      猜你喜欢
      • 2019-05-20
      • 2017-05-23
      • 2018-05-17
      • 2021-06-12
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      • 2018-11-15
      • 2017-06-26
      相关资源
      最近更新 更多