diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt index 3124b3a5ae6..904648228ad 100644 --- a/hadoop-yarn-project/CHANGES.txt +++ b/hadoop-yarn-project/CHANGES.txt @@ -616,6 +616,9 @@ Release 2.7.0 - UNRELEASED YARN-3247. TestQueueMappings should use CapacityScheduler explicitly. (Zhihai Xu via ozawa) + YARN-3239. WebAppProxy does not support a final tracking url which has + query fragments and params (Jian He via jlowe) + Release 2.6.0 - 2014-11-18 INCOMPATIBLE CHANGES diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServlet.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServlet.java index 6c0391f4ef8..47f77690edd 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServlet.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/main/java/org/apache/hadoop/yarn/server/webproxy/WebAppProxyServlet.java @@ -20,9 +20,9 @@ package org.apache.hadoop.yarn.server.webproxy; import java.io.IOException; import java.io.InputStream; +import java.io.ObjectInputStream; import java.io.OutputStream; import java.io.PrintWriter; -import java.io.ObjectInputStream; import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; @@ -38,6 +38,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.UriBuilder; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HostConfiguration; @@ -58,6 +59,8 @@ import org.apache.hadoop.yarn.util.TrackingUriPlugin; import org.apache.hadoop.yarn.webapp.MimeType; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; 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; @@ -325,11 +328,17 @@ public class WebAppProxyServlet extends HttpServlet { req.getQueryString(), true), runningUser, id); return; } - URI toFetch = new URI(trackingUri.getScheme(), - trackingUri.getAuthority(), - StringHelper.ujoin(trackingUri.getPath(), rest), req.getQueryString(), - null); - + + // Append the user-provided path and query parameter to the original + // tracking url. + List queryPairs = + URLEncodedUtils.parse(req.getQueryString(), null); + UriBuilder builder = UriBuilder.fromUri(trackingUri); + for (NameValuePair pair : queryPairs) { + builder.queryParam(pair.getName(), pair.getValue()); + } + URI toFetch = builder.path(rest).build(); + LOG.info("{} is accessing unchecked {}" + " which is the app master GUI of {} owned by {}", remoteUser, toFetch, appId, runningUser); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/test/java/org/apache/hadoop/yarn/server/webproxy/TestWebAppProxyServlet.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/test/java/org/apache/hadoop/yarn/server/webproxy/TestWebAppProxyServlet.java index e55c0adb294..aa6d918bcb1 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/test/java/org/apache/hadoop/yarn/server/webproxy/TestWebAppProxyServlet.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-web-proxy/src/test/java/org/apache/hadoop/yarn/server/webproxy/TestWebAppProxyServlet.java @@ -82,7 +82,7 @@ public class TestWebAppProxyServlet { Context context = new Context(); context.setContextPath("/foo"); server.setHandler(context); - context.addServlet(new ServletHolder(TestServlet.class), "/bar/"); + context.addServlet(new ServletHolder(TestServlet.class), "/bar"); server.getConnectors()[0].setHost("localhost"); server.start(); originalPort = server.getConnectors()[0].getLocalPort(); @@ -181,6 +181,19 @@ public class TestWebAppProxyServlet { proxyConn.setRequestProperty("Cookie", "checked_application_0_0000=true"); proxyConn.connect(); assertEquals(HttpURLConnection.HTTP_OK, proxyConn.getResponseCode()); + + // test user-provided path and query parameter can be appended to the + // original tracking url + appReportFetcher.answer = 5; + URL clientUrl = new URL("http://localhost:" + proxyPort + + "/proxy/application_00_0/test/tez?x=y&h=p"); + proxyConn = (HttpURLConnection) clientUrl.openConnection(); + proxyConn.connect(); + LOG.info("" + proxyConn.getURL()); + LOG.info("ProxyConn.getHeaderField(): " + proxyConn.getHeaderField(ProxyUtils.LOCATION)); + assertEquals("http://localhost:" + originalPort + + "/foo/bar/test/tez?a=b&x=y&h=p#main", proxyConn.getURL().toString()); + } finally { proxy.close(); } @@ -344,6 +357,14 @@ public class TestWebAppProxyServlet { return result; } else if (answer == 4) { throw new ApplicationNotFoundException("Application is not found"); + } else if (answer == 5) { + // test user-provided path and query parameter can be appended to the + // original tracking url + ApplicationReport result = getDefaultApplicationReport(appId); + result.setOriginalTrackingUrl("localhost:" + originalPort + + "/foo/bar?a=b#main"); + result.setYarnApplicationState(YarnApplicationState.FINISHED); + return result; } return null; }