Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions core/src/main/scala/org/apache/spark/ui/JettyUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -401,17 +401,13 @@ private[spark] object JettyUtils extends Logging {
uri.append(rest)
}

val rewrittenURI = URI.create(uri.toString())
if (query != null) {
return new URI(
rewrittenURI.getScheme(),
rewrittenURI.getAuthority(),
rewrittenURI.getPath(),
query,
rewrittenURI.getFragment()
).normalize()
val queryString = if (query == null) {
""
} else {
s"?$query"
}
rewrittenURI.normalize()
// SPARK-33611: use method `URI.create` to avoid percent-encoding twice on the query string.
URI.create(uri.toString() + queryString).normalize()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toString() is unnecesary here BTW.
So this relies on query already being escaped. That may be fine for the logic of this code, although in another world it would have been better to let this method take unescaped query strings and manage it here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion, Sean.

toString() is unnecesary here BTW.

uri is StringBuilder here. The original code also use toString().

So this relies on query already being escaped. That may be fine for the logic of this code, although in another world it would have been better to let this method take unescaped query strings and manage it here.

The query string here should be encoded already. I am not very familiar with this topic. Is there any better solution to handle both escaped/unescaped query string?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, OK, ignore the toString() comment.
I just mean that semantically, encoding is a URI detail. The program should probably not worry about it except when going to and from URIs. But that's not how this code is structured. It clearly already expects and escaped string as argument, which then means callers have to deal with it. But, I don't think it's necessary to change. If it is escaped then yes this is a fix.

}

def createProxyLocationHeader(
Expand Down
9 changes: 9 additions & 0 deletions core/src/test/scala/org/apache/spark/ui/UISuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,15 @@ class UISuite extends SparkFunSuite {
assert(rewrittenURI === null)
}

test("SPARK-33611: Avoid encoding twice on the query parameter of proxy rewrittenURI") {
val prefix = "/worker-id"
val target = "http://localhost:8081"
val path = "/worker-id/json"
val rewrittenURI =
JettyUtils.createProxyURI(prefix, target, path, "order%5B0%5D%5Bcolumn%5D=0")
assert(rewrittenURI.toString === "http://localhost:8081/json?order%5B0%5D%5Bcolumn%5D=0")
}

test("verify rewriting location header for reverse proxy") {
val clientRequest = mock(classOf[HttpServletRequest])
var headerValue = "http://localhost:4040/jobs"
Expand Down