You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by do...@apache.org on 2026/10/19 21:53:19 UTC
(spark) branch branch-4.x updated: [SPARK-60342][CORE][UI] Respect UI root in Master UI links
This is an automated email from the ASF dual-hosted git repository.
dongjoon-hyun pushed a commit to branch branch-4.x
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/branch-4.x by this push:
new 22ed2349c008 [SPARK-60342][CORE][UI] Respect UI root in Master UI links
22ed2349c008 is described below
commit 22ed2349c008a8f1ae41ec42d3add816a29d0a1a
Author: Dongjoon Hyun <do...@apache.org>
AuthorDate: Mon Oct 19 14:52:56 2026 -0700
[SPARK-60342][CORE][UI] Respect UI root in Master UI links
### What changes were proposed in this pull request?
This PR aims to respect the UI root (`spark.ui.proxyBase`, `APPLICATION_WEB_PROXY_BASE`, or the Knox `X-Forwarded-Context` header) in the Master UI links, like SPARK-60311 did in the History Server log page.
- `MasterPage`: The `Environment` and `Log` links use `UIUtils.prependBaseUri`.
- `EnvironmentPage` and `LogPage`: The `Back to Master` links use `UIUtils.prependBaseUri`.
### Why are the changes needed?
Under a UI root, e.g., behind a front-end reverse proxy with a path (`spark.ui.reverseProxyUrl`) or Knox, these links go outside of the UI root and don't work. This bug exists since Apache Spark [v4.0.0](https://github.com/apache/spark/releases/tag/v4.0.0) (2025-05-19), which added the Master log page (SPARK-46870) and environment page (SPARK-47894).
### Does this PR introduce _any_ user-facing change?
Yes, the `Environment`, `Log`, and `Back to Master` links work under a UI root. There is no change when the UI root is empty (default).
### How was this patch tested?
Pass the CIs with the updated `MasterWorkerUISuite`, which fails without this fix. `MasterSuiteBase.verifyStaticResourcesServedByProxy` now checks all site-relative links, not only `/static`, and the test applies it to the Master `Environment` and `Log` pages too.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Opus 5.5
Closes #59595 from dongjoon-hyun/SPARK-60342.
Authored-by: Dongjoon Hyun <do...@apache.org>
Signed-off-by: Dongjoon Hyun <do...@apache.org>
(cherry picked from commit 269a4f743045b7f04d2f4bce2e27b917dd1534e2)
Signed-off-by: Dongjoon Hyun <do...@apache.org>
---
.../scala/org/apache/spark/deploy/master/ui/EnvironmentPage.scala | 2 +-
.../src/main/scala/org/apache/spark/deploy/master/ui/LogPage.scala | 2 +-
.../main/scala/org/apache/spark/deploy/master/ui/MasterPage.scala | 4 ++--
.../scala/org/apache/spark/deploy/master/MasterSuiteBase.scala | 6 ++++++
.../scala/org/apache/spark/deploy/master/MasterWorkerUISuite.scala | 7 +++++++
5 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/core/src/main/scala/org/apache/spark/deploy/master/ui/EnvironmentPage.scala b/core/src/main/scala/org/apache/spark/deploy/master/ui/EnvironmentPage.scala
index 087453175257..06a65d3641e5 100644
--- a/core/src/main/scala/org/apache/spark/deploy/master/ui/EnvironmentPage.scala
+++ b/core/src/main/scala/org/apache/spark/deploy/master/ui/EnvironmentPage.scala
@@ -62,7 +62,7 @@ private[ui] class EnvironmentPage(
val content =
<div>
- <p><a href="/">Back to Master</a></p>
+ <p><a href={UIUtils.prependBaseUri(request, "/")}>Back to Master</a></p>
</div>
<span>
<span class="collapse-table" data-bs-toggle="collapse"
diff --git a/core/src/main/scala/org/apache/spark/deploy/master/ui/LogPage.scala b/core/src/main/scala/org/apache/spark/deploy/master/ui/LogPage.scala
index 7da873622202..74227a5dfca9 100644
--- a/core/src/main/scala/org/apache/spark/deploy/master/ui/LogPage.scala
+++ b/core/src/main/scala/org/apache/spark/deploy/master/ui/LogPage.scala
@@ -62,7 +62,7 @@ private[ui] class LogPage(parent: MasterWebUI) extends WebUIPage("logPage") with
val content =
<script type="module" src={UIUtils.prependBaseUri(request, "/static/utils.js")}></script> ++
<div>
- <p><a href="/">Back to Master</a></p>
+ <p><a href={UIUtils.prependBaseUri(request, "/")}>Back to Master</a></p>
{range}
<div class="log-content overflow-auto p-1" style="height:80vh;">
<div>{moreButton}</div>
diff --git a/core/src/main/scala/org/apache/spark/deploy/master/ui/MasterPage.scala b/core/src/main/scala/org/apache/spark/deploy/master/ui/MasterPage.scala
index c89f586f7e6d..68cabe63ecf8 100644
--- a/core/src/main/scala/org/apache/spark/deploy/master/ui/MasterPage.scala
+++ b/core/src/main/scala/org/apache/spark/deploy/master/ui/MasterPage.scala
@@ -193,8 +193,8 @@ private[ui] class MasterPage(parent: MasterWebUI) extends WebUIPage("") {
{state.completedDrivers.count(_.state == DriverState.RELAUNCHING)} Relaunching)
</li>
<li><strong>Status:</strong> {state.status}
- (<a href={"/environment/"}>Environment</a>,
- <a href={"/logPage/?self&logType=out"}>Log</a>)
+ (<a href={UIUtils.prependBaseUri(request, "/environment/")}>Environment</a>,
+ <a href={UIUtils.prependBaseUri(request, "/logPage/?self&logType=out")}>Log</a>)
</li>
</ul>
</div>
diff --git a/core/src/test/scala/org/apache/spark/deploy/master/MasterSuiteBase.scala b/core/src/test/scala/org/apache/spark/deploy/master/MasterSuiteBase.scala
index 70291625cdb4..800ce81657e3 100644
--- a/core/src/test/scala/org/apache/spark/deploy/master/MasterSuiteBase.scala
+++ b/core/src/test/scala/org/apache/spark/deploy/master/MasterSuiteBase.scala
@@ -144,6 +144,9 @@ trait MasterSuiteBase extends SparkFunSuite
// groups represent URL and worker ID
val WORKER_LINK_RE = """<a href="(.+?)">\s*(worker-.+?)\s*</a>""".r
+ // regex to extract site-relative links from the webui HTML
+ val SITE_RELATIVE_LINK_RE = """href="(/[^"]*)"""".r
+
private var _master: Master = _
after {
@@ -179,6 +182,9 @@ trait MasterSuiteBase extends SparkFunSuite
html should include (s"""href="$proxyUrl/static""")
html should not include ("""src="/static""")
html should include (s"""src="$proxyUrl/static""")
+ // other site-relative links, e.g. "Back to Master", must not bypass the proxy either
+ (SITE_RELATIVE_LINK_RE findAllMatchIn html).map(_.group(1))
+ .filterNot(_.startsWith(proxyUrl)).toSeq shouldBe empty
}
protected def verifyDrivers(
diff --git a/core/src/test/scala/org/apache/spark/deploy/master/MasterWorkerUISuite.scala b/core/src/test/scala/org/apache/spark/deploy/master/MasterWorkerUISuite.scala
index 5f206f611fe6..47ecdb3dd044 100644
--- a/core/src/test/scala/org/apache/spark/deploy/master/MasterWorkerUISuite.scala
+++ b/core/src/test/scala/org/apache/spark/deploy/master/MasterWorkerUISuite.scala
@@ -133,6 +133,13 @@ class MasterWorkerUISuite extends MasterSuiteBase {
.tryWithResource(Source.fromURL(s"$masterUrl/"))(_.getLines().mkString("\n"))
html should include ("Spark Master at spark://")
verifyStaticResourcesServedByProxy(html, reverseProxyUrl)
+ Seq("environment/", "logPage/?self&logType=out").foreach { path =>
+ val pageHtml = Utils
+ .tryWithResource(Source.fromURL(s"$masterUrl/$path"))(_.getLines().mkString("\n"))
+ withClue(s"$path: ") {
+ verifyStaticResourcesServedByProxy(pageHtml, reverseProxyUrl)
+ }
+ }
verifyWorkerUI(html, masterUrl, reverseProxyUrl)
}
} finally {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org