From c722262c759d5cddf97de4249c563c8d165b7c9f Mon Sep 17 00:00:00 2001 From: Junping Du Date: Wed, 23 Mar 2016 19:34:30 -0700 Subject: [PATCH] YARN-4820. ResourceManager web redirects in HA mode drops query parameters. Contributed by Varun Vasudev. (cherry picked from commit 19b645c93801a53d4486f9a7639186525e51f723) --- .../hadoop/yarn/client/TestRMFailover.java | 7 ++-- .../webapp/RMWebAppFilter.java | 40 ++++++++++++++----- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java index f32335127d1..b58a7751930 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java @@ -273,8 +273,8 @@ public void testRMWebAppRedirect() throws YarnException, redirectURL = getRedirectURL(rm2Url + "/metrics"); assertEquals(redirectURL,rm1Url + "/metrics"); - redirectURL = getRedirectURL(rm2Url + "/jmx"); - assertEquals(redirectURL,rm1Url + "/jmx"); + redirectURL = getRedirectURL(rm2Url + "/jmx?param1=value1+x¶m2=y"); + assertEquals(rm1Url + "/jmx?param1=value1+x¶m2=y", redirectURL); // standby RM links /conf, /stacks, /logLevel, /static, /logs, // /cluster/cluster as well as webService @@ -327,8 +327,9 @@ static String getRedirectURL(String url) { // do not automatically follow the redirection // otherwise we get too many redirections exception conn.setInstanceFollowRedirects(false); - if(conn.getResponseCode() == HttpServletResponse.SC_TEMPORARY_REDIRECT) + if(conn.getResponseCode() == HttpServletResponse.SC_TEMPORARY_REDIRECT) { redirectUrl = conn.getHeaderField("Location"); + } } catch (Exception e) { // throw new RuntimeException(e); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebAppFilter.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebAppFilter.java index 74137480b43..de2a23f786f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebAppFilter.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebAppFilter.java @@ -25,6 +25,8 @@ import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.util.List; import java.util.Random; import java.util.Set; @@ -48,6 +50,8 @@ import org.apache.hadoop.yarn.util.ConverterUtils; import org.apache.hadoop.yarn.webapp.YarnWebParams; import org.apache.hadoop.yarn.webapp.util.WebAppUtils; +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -106,22 +110,40 @@ public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { response.setCharacterEncoding("UTF-8"); - String uri = HtmlQuoting.quoteHtmlChars(request.getRequestURI()); + String htmlEscapedUri = HtmlQuoting.quoteHtmlChars(request.getRequestURI()); - if (uri == null) { - uri = "/"; + if (htmlEscapedUri == null) { + htmlEscapedUri = "/"; } + + String uriWithQueryString = htmlEscapedUri; + String htmlEscapedUriWithQueryString = htmlEscapedUri; + + String queryString = request.getQueryString(); + if (queryString != null && !queryString.isEmpty()) { + String reqEncoding = request.getCharacterEncoding(); + if (reqEncoding == null || reqEncoding.isEmpty()) { + reqEncoding = "ISO-8859-1"; + } + Charset encoding = Charset.forName(reqEncoding); + List params = URLEncodedUtils.parse(queryString, encoding); + String urlEncodedQueryString = URLEncodedUtils.format(params, encoding); + uriWithQueryString += "?" + urlEncodedQueryString; + htmlEscapedUriWithQueryString = HtmlQuoting.quoteHtmlChars( + request.getRequestURI() + "?" + urlEncodedQueryString); + } + RMWebApp rmWebApp = injector.getInstance(RMWebApp.class); rmWebApp.checkIfStandbyRM(); if (rmWebApp.isStandby() - && shouldRedirect(rmWebApp, uri)) { + && shouldRedirect(rmWebApp, htmlEscapedUri)) { String redirectPath = rmWebApp.getRedirectPath(); if (redirectPath != null && !redirectPath.isEmpty()) { - redirectPath += uri; - String redirectMsg = - "This is standby RM. The redirect url is: " + redirectPath; + redirectPath += uriWithQueryString; + String redirectMsg = "This is standby RM. The redirect url is: " + + htmlEscapedUriWithQueryString; PrintWriter out = response.getWriter(); out.println(redirectMsg); response.setHeader("Location", redirectPath); @@ -142,7 +164,7 @@ && shouldRedirect(rmWebApp, uri)) { int next = calculateExponentialTime(retryInterval); String redirectUrl = - appendOrReplaceParamter(path + uri, + appendOrReplaceParamter(path + uriWithQueryString, YarnWebParams.NEXT_REFRESH_INTERVAL + "=" + (retryInterval + 1)); if (redirectUrl == null || next > MAX_SLEEP_TIME) { doRetry = false; @@ -161,7 +183,7 @@ && shouldRedirect(rmWebApp, uri)) { } return; } else if (ahsEnabled) { - String ahsRedirectUrl = ahsRedirectPath(uri, rmWebApp); + String ahsRedirectUrl = ahsRedirectPath(uriWithQueryString, rmWebApp); if(ahsRedirectUrl != null) { response.setHeader("Location", ahsRedirectUrl); response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);