diff options
author | Jesse McConnell | 2012-01-13 14:21:29 +0000 |
---|---|---|
committer | Jesse McConnell | 2012-01-13 14:21:29 +0000 |
commit | 16e33c3d1ebe0b9c6c45507d2d5c7045346bed29 (patch) | |
tree | 47df3c3e2987dbfdde676d11b180e7beb8b82e5d | |
parent | fc70ea92d743b451a22ecb3486a03f958489a67f (diff) | |
parent | c0d3266c59d12a1cc5c45715c233afd8f3a8a433 (diff) | |
download | org.eclipse.jetty.project-16e33c3d1ebe0b9c6c45507d2d5c7045346bed29.tar.gz org.eclipse.jetty.project-16e33c3d1ebe0b9c6c45507d2d5c7045346bed29.tar.xz org.eclipse.jetty.project-16e33c3d1ebe0b9c6c45507d2d5c7045346bed29.zip |
Merge branch 'master' into jetty-8
10 files changed, 163 insertions, 27 deletions
diff --git a/README.txt b/README.txt index 28a387764c..3412f8ff16 100644 --- a/README.txt +++ b/README.txt @@ -15,3 +15,5 @@ dependencies. The tests do a lot of stress testing, and on some machines it is necessary to set the file descriptor limit to greater than 2048 for the tests to all pass successfully. + +Bypass tests by building with -Dmaven.test.skip=true but note that this will not produce some test jars that are leveraged in other places in the build. diff --git a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index 219f9face3..6c77cd122e 100644 --- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -53,7 +53,7 @@ public class LikeJettyXml mbContainer.start(); server.getContainer().addEventListener(mbContainer); server.addBean(mbContainer,true); - mbContainer.addBean(Log.getRootLogger()); + mbContainer.addBean(new Log()); // Setup Threadpool QueuedThreadPool threadPool = new QueuedThreadPool(); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java index b417ce0cc2..618639ee05 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java @@ -1,6 +1,7 @@ package org.eclipse.jetty.client; import java.io.BufferedReader; +import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; @@ -34,6 +35,7 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.nio.AsyncConnection; import org.eclipse.jetty.io.nio.SslConnection; +import org.eclipse.jetty.server.AsyncHttpConnection; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; @@ -102,7 +104,7 @@ public class SslBytesServerTest extends SslBytesTest @Override protected AsyncConnection newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint) { - return new org.eclipse.jetty.server.AsyncHttpConnection(this, endPoint, getServer()) + return new AsyncHttpConnection(this, endPoint, getServer()) { @Override protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endPoint, HttpParser.EventHandler requestHandler) @@ -135,21 +137,32 @@ public class SslBytesServerTest extends SslBytesTest { public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { - request.setHandled(true); - String contentLength = request.getHeader("Content-Length"); - if (contentLength != null) + try { - int length = Integer.parseInt(contentLength); - ServletInputStream input = httpRequest.getInputStream(); - ServletOutputStream output = httpResponse.getOutputStream(); - byte[] buffer = new byte[32 * 1024]; - for (int i = 0; i < length; ++i) + request.setHandled(true); + String contentLength = request.getHeader("Content-Length"); + if (contentLength != null) { - int read = input.read(buffer); - if ("/echo".equals(target)) - output.write(buffer, 0, read); + int length = Integer.parseInt(contentLength); + ServletInputStream input = httpRequest.getInputStream(); + ServletOutputStream output = httpResponse.getOutputStream(); + byte[] buffer = new byte[32 * 1024]; + while (length > 0) + { + int read = input.read(buffer); + if (read < 0) + throw new EOFException(); + length -= read; + if (target.startsWith("/echo")) + output.write(buffer, 0, read); + } } } + catch (IOException x) + { + if (!(target.endsWith("suppress_exception"))) + throw x; + } } }); server.start(); @@ -860,6 +873,59 @@ public class SslBytesServerTest extends SslBytesTest // connection, and this will cause an exception in the // server that is trying to write the data + TimeUnit.MILLISECONDS.sleep(500); + proxy.sendRSTToServer(); + + // Wait a while to detect spinning + TimeUnit.MILLISECONDS.sleep(500); + Assert.assertThat(sslHandles.get(), lessThan(20)); + Assert.assertThat(sslFlushes.get(), lessThan(20)); + Assert.assertThat(httpParses.get(), lessThan(50)); + + client.close(); + } + + @Test + public void testRequestWithBigContentReadBlockedThenReset() throws Exception + { + final SSLSocket client = newClient(); + + SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow(); + client.startHandshake(); + Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS)); + + byte[] data = new byte[128 * 1024]; + Arrays.fill(data, (byte)'X'); + final String content = new String(data, "UTF-8"); + Future<Object> request = threadPool.submit(new Callable<Object>() + { + public Object call() throws Exception + { + OutputStream clientOutput = client.getOutputStream(); + clientOutput.write(("" + + "GET /echo_suppress_exception HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Content-Length: " + content.length() + "\r\n" + + "\r\n" + + content).getBytes("UTF-8")); + clientOutput.flush(); + return null; + } + }); + + // Nine TLSRecords will be generated for the request, + // but we write only 5 of them, so the server goes in read blocked state + for (int i = 0; i < 5; ++i) + { + // Application data + TLSRecord record = proxy.readFromClient(); + Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType()); + proxy.flushToServer(record, 0); + } + Assert.assertNull(request.get(5, TimeUnit.SECONDS)); + + // The server should be read blocked, and we send a RST + TimeUnit.MILLISECONDS.sleep(500); proxy.sendRSTToServer(); // Wait a while to detect spinning diff --git a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java index 395791ea6d..475a2da3a7 100644 --- a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java +++ b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/MBeanContainer.java @@ -34,6 +34,7 @@ import org.eclipse.jetty.util.component.Container.Relationship; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.log.StdErrLog; import org.eclipse.jetty.util.thread.ShutdownThread; /** diff --git a/jetty-jmx/src/main/resources/org/eclipse/jetty/util/log/jmx/Slf4jLog-mbean.properties b/jetty-jmx/src/main/resources/org/eclipse/jetty/util/log/jmx/Slf4jLog-mbean.properties deleted file mode 100644 index 58b10abec3..0000000000 --- a/jetty-jmx/src/main/resources/org/eclipse/jetty/util/log/jmx/Slf4jLog-mbean.properties +++ /dev/null @@ -1 +0,0 @@ -Slf4jLog: SL4J log adapter diff --git a/jetty-jmx/src/main/resources/org/eclipse/jetty/util/log/jmx/StdErrLog-mbean.properties b/jetty-jmx/src/main/resources/org/eclipse/jetty/util/log/jmx/StdErrLog-mbean.properties deleted file mode 100644 index 16e56bb70b..0000000000 --- a/jetty-jmx/src/main/resources/org/eclipse/jetty/util/log/jmx/StdErrLog-mbean.properties +++ /dev/null @@ -1 +0,0 @@ -StdErrLog: Log adapter that logs to stderr
\ No newline at end of file diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java index f402636937..67c6e7c5fb 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java @@ -18,7 +18,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; - +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -42,7 +43,14 @@ import org.eclipse.jetty.util.log.Logger; * <ul> * <li><b>allowedOrigins</b>, a comma separated list of origins that are * allowed to access the resources. Default value is <b>*</b>, meaning all - * origins</li> + * origins.<br /> + * If an allowed origin contains one or more * characters (for example + * http://*.domain.com), then "*" characters are converted to ".*", "." + * characters are escaped to "\." and the resulting allowed origin + * interpreted as a regular expression.<br /> + * Allowed origins can therefore be more complex expressions such as + * https?://*.domain.[a-z]{3} that matches http or https, multiple subdomains + * and any 3 letter top-level domain (.com, .net, .org, etc.).</li> * <li><b>allowedMethods</b>, a comma separated list of HTTP methods that * are allowed to be used when accessing the resources. Default value is * <b>GET,POST</b></li> @@ -229,19 +237,34 @@ public class CrossOriginFilter implements Filter if (origin.trim().length() == 0) continue; - boolean allowed = false; for (String allowedOrigin : allowedOrigins) { - if (allowedOrigin.equals(origin)) + if (allowedOrigin.contains("*")) { - allowed = true; - break; + Matcher matcher = createMatcher(origin,allowedOrigin); + if (matcher.matches()) + return true; + } + else if (allowedOrigin.equals(origin)) + { + return true; } } - if (!allowed) - return false; } - return true; + return false; + } + + private Matcher createMatcher(String origin, String allowedOrigin) + { + String regex = parseAllowedWildcardOriginToRegex(allowedOrigin); + Pattern pattern = Pattern.compile(regex); + return pattern.matcher(origin); + } + + private String parseAllowedWildcardOriginToRegex(String allowedOrigin) + { + String regex = allowedOrigin.replace(".","\\."); + return regex.replace("*",".*"); // we want to be greedy here to match multiple subdomains, thus we use .* } private boolean isSimpleRequest(HttpServletRequest request) diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java index 48bfcf391c..2b7ee1252f 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java @@ -62,7 +62,7 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool; * <p> * This servlet needs the jetty-util and jetty-client classes to be available to the web application. * <p> - * To facilitate JMX monitoring, the "HttpClient", it's "ThreadPool" and the "Logger" are set as context attributes prefixed with the servlet name. + * To facilitate JMX monitoring, the "HttpClient" and "ThreadPool" are set as context attributes prefixed with the servlet name. * <p> * The following init parameters may be used to configure the servlet: * <ul> @@ -127,7 +127,6 @@ public class ProxyServlet implements Servlet if (_context != null) { - _context.setAttribute(config.getServletName() + ".Logger",_log); _context.setAttribute(config.getServletName() + ".ThreadPool",_client.getThreadPool()); _context.setAttribute(config.getServletName() + ".HttpClient",_client); } diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java index bd9bfb576b..e6c15d11b5 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java @@ -80,6 +80,52 @@ public class CrossOriginFilterTest } @Test + public void testSimpleRequestWithMatchingWildcardOrigin() throws Exception + { + FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter()); + String origin = "http://subdomain.example.com"; + filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://*.example.com"); + tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT); + + CountDownLatch latch = new CountDownLatch(1); + tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*"); + + String request = "" + + "GET / HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Origin: " + origin + "\r\n" + + "\r\n"; + String response = tester.getResponses(request); + Assert.assertTrue(response.contains("HTTP/1.1 200")); + Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER)); + Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER)); + Assert.assertTrue(latch.await(1, TimeUnit.SECONDS)); + } + + @Test + public void testSimpleRequestWithMatchingWildcardOriginAndMultipleSubdomains() throws Exception + { + FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter()); + String origin = "http://subdomain.subdomain.example.com"; + filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://*.example.com"); + tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT); + + CountDownLatch latch = new CountDownLatch(1); + tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*"); + + String request = "" + + "GET / HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Origin: " + origin + "\r\n" + + "\r\n"; + String response = tester.getResponses(request); + Assert.assertTrue(response.contains("HTTP/1.1 200")); + Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER)); + Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER)); + Assert.assertTrue(latch.await(1, TimeUnit.SECONDS)); + } + + @Test public void testSimpleRequestWithMatchingOrigin() throws Exception { FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter()); @@ -330,6 +376,7 @@ public class CrossOriginFilterTest public static class ResourceServlet extends HttpServlet { + private static final long serialVersionUID = 1L; private final CountDownLatch latch; public ResourceServlet(CountDownLatch latch) diff --git a/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml b/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml index 9ccb222c0a..010d10d428 100644 --- a/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml +++ b/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml @@ -10,7 +10,7 @@ <context-param> <param-name>org.eclipse.jetty.server.context.ManagedAttributes</param-name> - <param-value>QoSFilter,TransparentProxy.Logger,TransparentProxy.ThreadPool,TransparentProxy.HttpClient</param-value> + <param-value>QoSFilter,TransparentProxy.ThreadPool,TransparentProxy.HttpClient</param-value> </context-param> <!-- Declare TestListener, which declares TestFilter --> |