使用 undertow-handlers.conf 重写路径无法按预期工作

Posted

技术标签:

【中文标题】使用 undertow-handlers.conf 重写路径无法按预期工作【英文标题】:Rewriting paths with undertow-handlers.conf doesn't work as expected 【发布时间】:2019-04-19 23:45:28 【问题描述】:

背景

带有 Angular 7 UI 的 JBoss 7.1.5 EAP 后端。

我需要让 JBoss 知道 UI 的路由,但是将它们全部重写到 UI 的索引页面以供 Angular 路由。

项目的结构如下:

webapp/
  WEB-INF/
    undertow-handlers.conf
    web.xml
    ...etc
  login/
    background.jpg
  login.jsp
  index.jsp

  assets/*
  ...html
  ...js
  ...css

index.jsp 就是response.sendRedirect("index.html")s,其中 index.html 是 Angular CLI 生成的资产的一部分。 javascript 和 HTML 来自 webapp/,图片来自 webapp/assets/

配置

来自standalone-full.xml

<subsystem xmlns="urn:jboss:domain:undertow:4.0">
    <buffer-cache name="default"/>
    <server name="default-server">
        <http-listener name="http" socket-binding="http" redirect-socket="https"/>
        <host name="default-host" alias="localhost,workstation">
            <location name="/" handler="welcome-content"/>
            <filter-ref name="request-dumper"/>
        </host>
    </server>
    <servlet-container name="default">
        <jsp-config x-powered-by="false"/>
        <websockets/>
    </servlet-container>
    <handlers>
        <file name="welcome-content" path="$jboss.home.dir/welcome-content"/>
    </handlers>
    <filters>
        <filter name="request-dumper" module="io.undertow.core" class-name="io.undertow.server.handlers.RequestDumpingHandler"/>
    </filters>
</subsystem>

<subsystem xmlns="urn:jboss:domain:web:2.2" default-virtual-server="default-host" native="false">
    <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
    <virtual-server name="default-host">
        <alias name="localhost"/>
        <alias name="workstation"/>
    </virtual-server>
</subsystem>

通过上面的配置,我看到了预期的服务器日志:

[org.wildfly.extension.undertow] (ServerService Thread Pool -- 84) WFLYUT0021: Registered web context: '/' for server 'default-server'

我可以访问该站点的登录页面,并且 URI / 按预期提供主要的角度索引页面和资产。

问题

我需要的是这个上下文中的路径(如/base/shop/60)由 Angular 处理,因此重定向到索引。

作为基于this answer的简单测试,我在WEB-INF/undertow-handlers.conf中尝试了这条单一规则:

exists(%RELATIVE_PATH) -> done
path-prefix('/') -> rewrite('/');

但是 当我得到 404 时,它似乎什么都不做

我试过-&gt; rewrite('/index.html')-&gt; rewrite('/index.jsp') 都没有成功。

不过,文件显然正在被读取,因为如果我将垃圾放入文件中,它会在服务器日志中引发异常。

UT000045: Error parsing predicated handler string Invalid expression:
# path('/base') -> rewrite('/')

我错过了什么?

相当是 JBoss 和整个 Undertow 生态系统的新手;请让我知道我应该在这个问题中添加哪些其他细节。

好奇心

激活请求转储程序后,我看到 JBoss (User-Agent=Java/1.8.0_181) 在启动后立即向 / 发出了一个初始请求,但是当我从浏览器导航到 / 时,我在垃圾场。但我确实看到了对/base 的请求失败。这是为什么呢?

【问题讨论】:

【参考方案1】:

我正在从 /gui 提供 Angular 8 SPA(就像你一样,我的 API 在另一个 servlet 中)。我对 Undertow 2.0.15 (EAP 7.2) 所做的只是添加一个 WEB-INF/undertow-handlers.conf :

path-prefix['gui'] and not file(%U) -> rewrite('/gui/index.html')

我猜如果您的 SPA 在 / 您可以:

not file(%U) -> rewrite('/index.html')

【讨论】:

酷!我不知道这是可用的。从那以后,我们重新构建了站点以在 Docker 中使用 nginx,但这要优雅得多,所以请勾选。【参考方案2】:

我有两个问题:

我缺少规则,我误解了path-prefix 的功能(它匹配完整和非终端 路径段,而不是像正则表达式^(group) 一样)。

我的最终工作 undertow-handlers.conf 看起来像这样:

regex('/login(.*)') -> done;

path-prefix('/assets') -> done;

regex('(.*).js') -> done;
regex('(.*).map') -> done;

regex('(.*).svg') -> done;
regex('(.*).png') -> done;

regex('(.*).eot') -> done;
regex('(.*).woff2') -> done;

regex('(.*).html') -> done;

path('/') -> rewrite('/index.html');

path('/base') -> rewrite('index.html');
path-prefix('/shop') -> rewrite('index.html');


...and all my other angular routes

注意/base是一个终端路径段,与path匹配,而/shop/60需要一个额外的路径参数,所以需要path-prefex

无论出于何种原因,上述链接问题中提出的解决方案,简单地使用path-prefix('/') 捕获所有内容在我的情况下都不起作用。

可能有用的旁注:我们有一个 REST 服务器,它在另一个 servlet 上下文中从 /RestService/ 提供服务,因此不需要任何规则来允许它继续工作。

另外,我是通过ng hmr使用webpack的开发代理服务器,也需要添加与undertow规则等效的byPassProxy规则。

我很高兴对此进行了改进:请不要犹豫,发表评论或添加其他答案。

【讨论】:

以上是关于使用 undertow-handlers.conf 重写路径无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

测试使用

第一篇 用于测试使用

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”