瀏覽代碼

YARN-4820. ResourceManager web redirects in HA mode drops query parameters. Contributed by Varun Vasudev.

Junping Du 9 年之前
父節點
當前提交
19b645c938

+ 4 - 3
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/TestRMFailover.java

@@ -273,8 +273,8 @@ public class TestRMFailover extends ClientBaseWithFixes {
     redirectURL = getRedirectURL(rm2Url + "/metrics");
     assertEquals(redirectURL,rm1Url + "/metrics");
 
-    redirectURL = getRedirectURL(rm2Url + "/jmx");
-    assertEquals(redirectURL,rm1Url + "/jmx");
+    redirectURL = getRedirectURL(rm2Url + "/jmx?param1=value1+x&param2=y");
+    assertEquals(rm1Url + "/jmx?param1=value1+x&param2=y", redirectURL);
 
     // standby RM links /conf, /stacks, /logLevel, /static, /logs,
     // /cluster/cluster as well as webService
@@ -327,8 +327,9 @@ public class TestRMFailover extends ClientBaseWithFixes {
       // 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);
     }

+ 31 - 9
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.io.PrintWriter;
 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.Apps;
 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 class RMWebAppFilter extends GuiceContainer {
       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<NameValuePair> 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 @@ public class RMWebAppFilter extends GuiceContainer {
         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 @@ public class RMWebAppFilter extends GuiceContainer {
       }
       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);