[Knox适配]-Trino-474-转发规则魔改
# 一、背景说明:为什么 Trino 474 在 Knox 下会“打不开”
在通过 Knox 接入 Trino Web UI 的过程中,会发现一个很现实的问题:
Knox 自带的 Trino UI 转发规则,并不能直接适配 Trino 474。
在早期 Trino 版本中,Web UI 的前端资源路径相对稳定,而在 474 版本中,前端构建结构已经发生了变化:
/ui/dist/ui/assets/ui/vendor- 同时还会出现不带
/ui前缀的短路径请求
当这些请求经过 Knox 时,如果 rewrite 规则未覆盖完整路径,就会出现:
- 页面白屏
- 静态资源 404
- API 请求路径错乱
- 登录后跳转异常
因此,本篇文章的目标非常明确:
提示
通过修改 Knox 的 Trino UI 转发规则,让 Knox 2.1.0-RC2 能够完整承载 Trino 474 的 Web UI。
# 二、当前实验环境说明
在开始改动之前,先明确本次适配所使用的版本组合:
| 组件 | 版本 |
|---|---|
| Knox | 2.1.0-RC2 |
| Trino | 474 |
| 认证方式 | Kerberos / SPNEGO |
| 访问方式 | Knox 统一入口 |
笔记
后文所有修改,均基于该版本组合验证。
# 三、Knox UI 中 Trino 图标补齐
# 一)Trino UI 图标路径
在 Knox UI 中,Trino 默认并不包含官方图标定义,因此需要手动补齐。
图标存放路径为:
knox-homepage-ui/home/assets/service-logos/trinoui.png
该图标可以从网络中自行下载制作,图像内容并不影响功能,但文件名必须严格为:
trinoui.png
否则在 Knox UI 中会出现渲染失败的问题。

# 二)图标生效后的 UI 表现
在图标补齐后,安装完成的 Knox 默认拓扑页面中,即可看到 Trino 对应的 UI 入口选区。
需要注意
该 Trino UI 入口并非 Knox 官方默认提供,而是通过补齐资源后呈现出来的。

# 四、Trino 474 带来的路径变化问题
在早期 Trino 版本中,Knox 自带的 Trino UI rewrite 规则主要围绕以下路径:
/ui//vendor/assets
但在 Trino 474 中,实际访问过程中可以观察到:
- 静态资源大量集中在
/ui/dist - 同时存在
/trino/dist、/trino/assets等短路径请求 - 后端返回的
LocationHeader 也会携带/ui/*跳转路径
这些变化如果不在 Knox 中显式处理,就会导致转发链路不完整。
# 五、rewrite.xml 修改位置说明
本次修改的 rewrite 文件位于 Knox 源码中:
gateway-service-definitions/src/main/resources/services/trinoui/365/rewrite.xml
默认情况下,该规则主要适配早期 Trino 版本,因此 365 → 474 必须进行调整。
否则在实际访问时,会出现各种不可预期的转发错误。
# 六、适配 Trino 474 的 rewrite.xml 完整示例
下面是已经验证可用的 rewrite.xml 内容,用于适配 Trino 474 的 Web UI。
直接复制替换原文件
该内容为完整替换版本,未做裁剪。
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<rules>
<!-- ========== INBOUND ========== -->
<!-- 入口:/trino/ -> 后端 /ui/ -->
<rule dir="IN" name="TRINOUI/trinoui/inbound/root" pattern="*://*:*/**/trino/">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/"/>
</rule>
<!-- /trino/ui/... 直通 -->
<rule dir="IN" name="TRINOUI/trinoui/inbound/ui/vendor" pattern="*://*:*/**/trino/ui/vendor/{**}?{**}">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/vendor/{**}?{**}"/>
</rule>
<rule dir="IN" name="TRINOUI/trinoui/inbound/ui/assets" pattern="*://*:*/**/trino/ui/assets/{**}?{**}">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/assets/{**}?{**}"/>
</rule>
<rule dir="IN" name="TRINOUI/trinoui/inbound/ui/dist" pattern="*://*:*/**/trino/ui/dist/{**}?{**}">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/dist/{**}?{**}"/>
</rule>
<!-- ✅ 补齐:/trino/dist|assets|vendor(不带 /ui 的短路径) -->
<rule dir="IN" name="TRINOUI/trinoui/inbound/short/vendor" pattern="*://*:*/**/trino/vendor/{**}?{**}">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/vendor/{**}?{**}"/>
</rule>
<rule dir="IN" name="TRINOUI/trinoui/inbound/short/assets" pattern="*://*:*/**/trino/assets/{**}?{**}">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/assets/{**}?{**}"/>
</rule>
<rule dir="IN" name="TRINOUI/trinoui/inbound/short/dist" pattern="*://*:*/**/trino/dist/{**}?{**}">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/dist/{**}?{**}"/>
</rule>
<!-- 登录/登出 -->
<rule dir="IN" name="TRINOUI/trinoui/inbound/ui/login" pattern="*://*:*/**/trino/ui/login">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/login"/>
</rule>
<rule dir="IN" name="TRINOUI/trinoui/inbound/ui/logout" pattern="*://*:*/**/trino/ui/logout">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/logout"/>
</rule>
<!-- API -->
<rule dir="IN" name="TRINOUI/trinoui/inbound/ui/api" pattern="*://*:*/**/trino/ui/api/{**}">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/api/{**}"/>
</rule>
<!-- 兜底:/trino/ui/ 下面其它资源 -->
<rule dir="IN" name="TRINOUI/trinoui/inbound/ui/other" pattern="*://*:*/**/trino/ui/{**}?{**}">
<rewrite template="{$serviceUrl[TRINOUI]}/ui/{**}?{**}"/>
</rule>
<!-- ========== OUTBOUND (body/path rewrites) ========== -->
<!-- 你原来的 vendor/assets 是 /vendor /assets,这里保留 -->
<rule dir="OUT" name="TRINOUI/trinoui/outbound/vendor" pattern="/vendor/{**}?{**}">
<rewrite template="{$frontend[url]}/trino/ui/vendor/{**}?{**}"/>
</rule>
<rule dir="OUT" name="TRINOUI/trinoui/outbound/assets" pattern="/assets/{**}?{**}">
<rewrite template="{$frontend[url]}/trino/ui/assets/{**}?{**}"/>
</rule>
<!-- ✅ 补齐:后端返回 /ui/vendor|assets|dist 的情况 -->
<rule dir="OUT" name="TRINOUI/trinoui/outbound/ui-vendor" pattern="/ui/vendor/{**}?{**}">
<rewrite template="{$frontend[url]}/trino/ui/vendor/{**}?{**}"/>
</rule>
<rule dir="OUT" name="TRINOUI/trinoui/outbound/ui-assets" pattern="/ui/assets/{**}?{**}">
<rewrite template="{$frontend[url]}/trino/ui/assets/{**}?{**}"/>
</rule>
<rule dir="OUT" name="TRINOUI/trinoui/outbound/ui-dist" pattern="/ui/dist/{**}?{**}">
<rewrite template="{$frontend[url]}/trino/ui/dist/{**}?{**}"/>
</rule>
<!-- API -->
<rule dir="OUT" name="TRINOUI/trinoui/outbound/api" pattern="/ui/api/{**}">
<rewrite template="{$frontend[url]}/trino/ui/api/{**}"/>
</rule>
<!-- login -->
<rule dir="OUT" name="TRINOUI/trinoui/outbound/login" pattern="/ui/login">
<rewrite template="{$frontend[url]}/trino/ui/login"/>
</rule>
<!-- ========== OUTBOUND (Location header rewrite) ========== -->
<rule flow="OR" dir="OUT" name="TRINOUI/trino/outbound/headers/location">
<!-- 后端跳到 /ui/login.html:回到 /trino/ -->
<match pattern="*://*:*/ui/login.html">
<rewrite template="{$frontend[url]}/trino/"/>
</match>
<!-- 后端跳到 /ui/:改成 /trino/ui/ -->
<match pattern="*://*:*/ui/">
<rewrite template="{$frontend[url]}/trino/ui/"/>
</match>
<!-- 后端跳到 /ui/xxx:改成 /trino/ui/xxx -->
<match pattern="*://*:*/ui/{**}">
<rewrite template="{$frontend[url]}/trino/ui/{**}"/>
</match>
</rule>
<filter name="TRINOUI/trino/outbound/headers">
<content type="application/x-http-headers">
<apply path="Location" rule="TRINOUI/trino/outbound/headers/location"/>
</content>
</filter>
<filter name="TRINOUI/trino/outbound/body">
<content type="application/javascript">
<apply path="/ui/api/[\w]+" rule="TRINOUI/trinoui/outbound/api"/>
</content>
</filter>
</rules>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
⚠️ 该规则的核心目的只有一个: 确保 Trino 474 所有可能出现的前端与 API 请求路径,都能被 Knox 正确转发。