From ebb9a82519c622bb898e1eec5798c2298c726694 Mon Sep 17 00:00:00 2001 From: Devaraj K Date: Wed, 17 Jun 2015 15:56:18 +0530 Subject: [PATCH] YARN-3148. Allow CORS related headers to passthrough in WebAppProxyServlet. Contributed by Varun Saxena. --- hadoop-yarn-project/CHANGES.txt | 3 + .../server/webproxy/WebAppProxyServlet.java | 5 +- .../webproxy/TestWebAppProxyServlet.java | 57 +++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt index c793a31979b..afe76bdb580 100644 --- a/hadoop-yarn-project/CHANGES.txt +++ b/hadoop-yarn-project/CHANGES.txt @@ -309,6 +309,9 @@ Release 2.8.0 - UNRELEASED YARN-3789. Improve logs for LeafQueue#activateApplications(). (Bibin A Chundatt via devaraj) + YARN-3148. Allow CORS related headers to passthrough in WebAppProxyServlet. + (Varun Saxena via devaraj) + OPTIMIZATIONS YARN-3339. TestDockerContainerExecutor should pull a single image and not 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 b1e355d1af6..33f36f0f340 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 @@ -81,7 +81,10 @@ public class WebAppProxyServlet extends HttpServlet { "Accept-Encoding", "Accept-Language", "Accept-Charset", - "Content-Type")); + "Content-Type", + "Origin", + "Access-Control-Request-Method", + "Access-Control-Request-Headers")); public static final String PROXY_USER_COOKIE_NAME = "proxy-user"; 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 2a2ca2ca3d2..8e68c38afcd 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 @@ -31,6 +31,7 @@ import java.net.HttpCookie; import java.net.HttpURLConnection; import java.net.URI; import java.net.URL; +import java.util.Enumeration; import java.util.List; import java.util.Map; @@ -72,6 +73,10 @@ public class TestWebAppProxyServlet { private static Server server; private static int originalPort = 0; + private static int numberOfHeaders = 0; + private static final String UNKNOWN_HEADER = "Unknown-Header"; + private static boolean hasUnknownHeader = false; + /** * Simple http server. Server should send answer with status 200 @@ -88,6 +93,9 @@ public class TestWebAppProxyServlet { originalPort = server.getConnectors()[0].getLocalPort(); LOG.info("Running embedded servlet container at: http://localhost:" + originalPort); + // This property needs to be set otherwise CORS Headers will be dropped + // by HttpUrlConnection + System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); } @SuppressWarnings("serial") @@ -96,6 +104,18 @@ public class TestWebAppProxyServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + int numHeaders = 0; + hasUnknownHeader = false; + @SuppressWarnings("unchecked") + Enumeration names = req.getHeaderNames(); + while(names.hasMoreElements()) { + String headerName = names.nextElement(); + if (headerName.equals(UNKNOWN_HEADER)) { + hasUnknownHeader = true; + } + ++numHeaders; + } + numberOfHeaders = numHeaders; resp.setStatus(HttpServletResponse.SC_OK); } @@ -206,6 +226,43 @@ public class TestWebAppProxyServlet { } } + @Test(timeout=5000) + public void testWebAppProxyPassThroughHeaders() throws Exception { + Configuration configuration = new Configuration(); + configuration.set(YarnConfiguration.PROXY_ADDRESS, "localhost:9091"); + configuration.setInt("hadoop.http.max.threads", 5); + WebAppProxyServerForTest proxy = new WebAppProxyServerForTest(); + proxy.init(configuration); + proxy.start(); + + int proxyPort = proxy.proxy.proxyServer.getConnectorAddress(0).getPort(); + + try { + URL url = new URL("http://localhost:" + proxyPort + "/proxy/application_00_1"); + HttpURLConnection proxyConn = (HttpURLConnection) url.openConnection(); + // set headers + proxyConn.addRequestProperty("Origin", "http://www.someurl.com"); + proxyConn.addRequestProperty("Access-Control-Request-Method", "GET"); + proxyConn.addRequestProperty( + "Access-Control-Request-Headers", "Authorization"); + proxyConn.addRequestProperty(UNKNOWN_HEADER, "unknown"); + // Verify if four headers mentioned above have been added + assertEquals(proxyConn.getRequestProperties().size(), 4); + proxyConn.connect(); + assertEquals(HttpURLConnection.HTTP_OK, proxyConn.getResponseCode()); + // Verify if number of headers received by end server is 8. + // Eight headers include Accept, Host, Connection, User-Agent, Cookie, + // Origin, Access-Control-Request-Method and + // Access-Control-Request-Headers. Pls note that Unknown-Header is dropped + // by proxy as it is not in the list of allowed headers. + assertEquals(numberOfHeaders, 8); + assertFalse(hasUnknownHeader); + } finally { + proxy.close(); + } + } + + /** * Test main method of WebAppProxyServer */