HADOOP-11350. The size of header buffer of HttpServer is too small when HTTPS is enabled. Contributed by Benoy Antony.

This commit is contained in:
Haohui Mai 2015-01-15 16:17:30 -08:00
parent 6f792fc198
commit 2e4df87104
5 changed files with 51 additions and 24 deletions

View File

@ -355,6 +355,9 @@ Release 2.7.0 - UNRELEASED
HADOOP-11462. TestSocketIOWithTimeout needs change for PowerPC platform. HADOOP-11462. TestSocketIOWithTimeout needs change for PowerPC platform.
(Ayappan via cnauroth) (Ayappan via cnauroth)
HADOOP-11350. The size of header buffer of HttpServer is too small when
HTTPS is enabled. (Benoy Antony via wheat9)
Release 2.6.0 - 2014-11-18 Release 2.6.0 - 2014-11-18
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -279,6 +279,7 @@ public final class HttpServer2 implements FilterContainer {
listener = HttpServer2.createDefaultChannelConnector(); listener = HttpServer2.createDefaultChannelConnector();
} else if ("https".equals(scheme)) { } else if ("https".equals(scheme)) {
SslSocketConnector c = new SslSocketConnectorSecure(); SslSocketConnector c = new SslSocketConnectorSecure();
c.setHeaderBufferSize(1024*64);
c.setNeedClientAuth(needsClientAuth); c.setNeedClientAuth(needsClientAuth);
c.setKeyPassword(keyPassword); c.setKeyPassword(keyPassword);

View File

@ -28,15 +28,32 @@ import org.apache.hadoop.http.HttpServer2.Builder;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** /**
* This is a base class for functional tests of the {@link HttpServer2}. * This is a base class for functional tests of the {@link HttpServer2}.
* The methods are static for other classes to import statically. * The methods are static for other classes to import statically.
*/ */
public class HttpServerFunctionalTest extends Assert { public class HttpServerFunctionalTest extends Assert {
@SuppressWarnings("serial")
public static class LongHeaderServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse response
) throws ServletException, IOException {
Assert.assertEquals(63 * 1024, request.getHeader("longheader").length());
response.setStatus(HttpServletResponse.SC_OK);
}
}
/** JVM property for the webapp test dir : {@value} */ /** JVM property for the webapp test dir : {@value} */
public static final String TEST_BUILD_WEBAPPS = "test.build.webapps"; public static final String TEST_BUILD_WEBAPPS = "test.build.webapps";
/** expected location of the test.build.webapps dir: {@value} */ /** expected location of the test.build.webapps dir: {@value} */
@ -44,6 +61,7 @@ public class HttpServerFunctionalTest extends Assert {
/** name of the test webapp: {@value} */ /** name of the test webapp: {@value} */
private static final String TEST = "test"; private static final String TEST = "test";
protected static URL baseUrl;
/** /**
* Create but do not start the test webapp server. The test webapp dir is * Create but do not start the test webapp server. The test webapp dir is
@ -227,4 +245,18 @@ public class HttpServerFunctionalTest extends Assert {
} }
return out.toString(); return out.toString();
} }
/**
* Test that verifies headers can be up to 64K long.
* The test adds a 63K header leaving 1K for other headers.
* This is because the header buffer setting is for ALL headers,
* names and values included. */
protected void testLongHeader(HttpURLConnection conn) throws IOException {
StringBuilder sb = new StringBuilder();
for (int i = 0 ; i < 63 * 1024; i++) {
sb.append("a");
}
conn.setRequestProperty("longheader", sb.toString());
assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
}
} }

View File

@ -67,7 +67,6 @@ import java.util.concurrent.Executors;
public class TestHttpServer extends HttpServerFunctionalTest { public class TestHttpServer extends HttpServerFunctionalTest {
static final Log LOG = LogFactory.getLog(TestHttpServer.class); static final Log LOG = LogFactory.getLog(TestHttpServer.class);
private static HttpServer2 server; private static HttpServer2 server;
private static URL baseUrl;
private static final int MAX_THREADS = 10; private static final int MAX_THREADS = 10;
@SuppressWarnings("serial") @SuppressWarnings("serial")
@ -120,17 +119,6 @@ public class TestHttpServer extends HttpServerFunctionalTest {
} }
} }
@SuppressWarnings("serial")
public static class LongHeaderServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse response
) throws ServletException, IOException {
Assert.assertEquals(63 * 1024, request.getHeader("longheader").length());
response.setStatus(HttpServletResponse.SC_OK);
}
}
@SuppressWarnings("serial") @SuppressWarnings("serial")
public static class HtmlContentServlet extends HttpServlet { public static class HtmlContentServlet extends HttpServlet {
@Override @Override
@ -210,20 +198,10 @@ public class TestHttpServer extends HttpServerFunctionalTest {
readOutput(new URL(baseUrl, "/echomap?a=b&c<=d&a=>"))); readOutput(new URL(baseUrl, "/echomap?a=b&c<=d&a=>")));
} }
/**
* Test that verifies headers can be up to 64K long.
* The test adds a 63K header leaving 1K for other headers.
* This is because the header buffer setting is for ALL headers,
* names and values included. */
@Test public void testLongHeader() throws Exception { @Test public void testLongHeader() throws Exception {
URL url = new URL(baseUrl, "/longheader"); URL url = new URL(baseUrl, "/longheader");
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); HttpURLConnection conn = (HttpURLConnection) url.openConnection();
StringBuilder sb = new StringBuilder(); testLongHeader(conn);
for (int i = 0 ; i < 63 * 1024; i++) {
sb.append("a");
}
conn.setRequestProperty("longheader", sb.toString());
assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
} }
@Test public void testContentTypes() throws Exception { @Test public void testContentTypes() throws Exception {

View File

@ -49,7 +49,6 @@ public class TestSSLHttpServer extends HttpServerFunctionalTest {
private static final Log LOG = LogFactory.getLog(TestSSLHttpServer.class); private static final Log LOG = LogFactory.getLog(TestSSLHttpServer.class);
private static Configuration conf; private static Configuration conf;
private static HttpServer2 server; private static HttpServer2 server;
private static URL baseUrl;
private static String keystoresDir; private static String keystoresDir;
private static String sslConfDir; private static String sslConfDir;
private static SSLFactory clientSslFactory; private static SSLFactory clientSslFactory;
@ -85,6 +84,7 @@ public class TestSSLHttpServer extends HttpServerFunctionalTest {
sslConf.get("ssl.server.truststore.password"), sslConf.get("ssl.server.truststore.password"),
sslConf.get("ssl.server.truststore.type", "jks")).build(); sslConf.get("ssl.server.truststore.type", "jks")).build();
server.addServlet("echo", "/echo", TestHttpServer.EchoServlet.class); server.addServlet("echo", "/echo", TestHttpServer.EchoServlet.class);
server.addServlet("longheader", "/longheader", LongHeaderServlet.class);
server.start(); server.start();
baseUrl = new URL("https://" baseUrl = new URL("https://"
+ NetUtils.getHostPortString(server.getConnectorAddress(0))); + NetUtils.getHostPortString(server.getConnectorAddress(0)));
@ -106,6 +106,19 @@ public class TestSSLHttpServer extends HttpServerFunctionalTest {
"/echo?a=b&c<=d&e=>"))); "/echo?a=b&c<=d&e=>")));
} }
/**
* Test that verifies headers can be up to 64K long.
* The test adds a 63K header leaving 1K for other headers.
* This is because the header buffer setting is for ALL headers,
* names and values included. */
@Test
public void testLongHeader() throws Exception {
URL url = new URL(baseUrl, "/longheader");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(clientSslFactory.createSSLSocketFactory());
testLongHeader(conn);
}
private static String readOut(URL url) throws Exception { private static String readOut(URL url) throws Exception {
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(clientSslFactory.createSSLSocketFactory()); conn.setSSLSocketFactory(clientSslFactory.createSSLSocketFactory());