diff --git a/Jenkinsfile b/Jenkinsfile index e7f1a37ab4c..295b1b35029 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -27,12 +27,12 @@ def getFullBuild(jdk, os, mainJdk) { // Checkout checkout scm withMaven( - maven: mvnName, - jdk: "$jdk", - publisherStrategy: 'EXPLICIT', - globalMavenSettingsConfig: settingsName, - mavenOpts: mavenOpts, - mavenLocalRepo: localRepo) { + maven: mvnName, + jdk: "$jdk", + publisherStrategy: 'EXPLICIT', + globalMavenSettingsConfig: settingsName, + mavenOpts: mavenOpts, + mavenLocalRepo: localRepo) { // Compile only sh "mvn -V -B clean install -DskipTests -T6 -e" // Javadoc only @@ -55,23 +55,23 @@ def getFullBuild(jdk, os, mainJdk) { if (mainJdk) { // Collect up the jacoco execution results def jacocoExcludes = - // build tools - "**/org/eclipse/jetty/ant/**" + ",**/org/eclipse/jetty/maven/**" + - ",**/org/eclipse/jetty/jspc/**" + - // example code / documentation - ",**/org/eclipse/jetty/embedded/**" + ",**/org/eclipse/jetty/asyncrest/**" + - ",**/org/eclipse/jetty/demo/**" + - // special environments / late integrations - ",**/org/eclipse/jetty/gcloud/**" + ",**/org/eclipse/jetty/infinispan/**" + - ",**/org/eclipse/jetty/osgi/**" + ",**/org/eclipse/jetty/spring/**" + - ",**/org/eclipse/jetty/http/spi/**" + - // test classes - ",**/org/eclipse/jetty/tests/**" + ",**/org/eclipse/jetty/test/**"; + // build tools + "**/org/eclipse/jetty/ant/**" + ",**/org/eclipse/jetty/maven/**" + + ",**/org/eclipse/jetty/jspc/**" + + // example code / documentation + ",**/org/eclipse/jetty/embedded/**" + ",**/org/eclipse/jetty/asyncrest/**" + + ",**/org/eclipse/jetty/demo/**" + + // special environments / late integrations + ",**/org/eclipse/jetty/gcloud/**" + ",**/org/eclipse/jetty/infinispan/**" + + ",**/org/eclipse/jetty/osgi/**" + ",**/org/eclipse/jetty/spring/**" + + ",**/org/eclipse/jetty/http/spi/**" + + // test classes + ",**/org/eclipse/jetty/tests/**" + ",**/org/eclipse/jetty/test/**"; jacoco inclusionPattern: '**/org/eclipse/jetty/**/*.class', - exclusionPattern: jacocoExcludes, - execPattern: '**/target/jacoco.exec', - classPattern: '**/target/classes', - sourcePattern: '**/src/main/java' + exclusionPattern: jacocoExcludes, + execPattern: '**/target/jacoco.exec', + classPattern: '**/target/classes', + sourcePattern: '**/src/main/java' consoleParsers = [[parserName: 'Maven'], [parserName: 'JavaDoc'], [parserName: 'JavaC']]; @@ -85,4 +85,4 @@ def getFullBuild(jdk, os, mainJdk) { } } -// vim: et:ts=2:sw=2:ft=groovy +// vim: et:ts=2:sw=2:ft=groovy \ No newline at end of file diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java index 7ae3fbb56d2..e2ff05cd6b8 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java @@ -108,7 +108,7 @@ public class HttpRequest implements Request headers.put(userAgentField); } - protected HttpConversation getConversation() + public HttpConversation getConversation() { return conversation; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java index a73a88ca5a1..cec9cd9110f 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java @@ -110,16 +110,16 @@ public class HttpChannelOverHTTP extends HttpChannel // Upgrade Response HttpRequest request = exchange.getRequest(); - if (request instanceof HttpConnectionUpgrader) + HttpConnectionUpgrader upgrader = (HttpConnectionUpgrader) request.getConversation().getAttribute(HttpConnectionUpgrader.class.getName()); + if (upgrader != null) { - HttpConnectionUpgrader listener = (HttpConnectionUpgrader)request; try { - listener.upgrade(response,getHttpConnection()); + upgrader.upgrade(response, getHttpConnection()); } catch (Throwable x) { - return new Result(result,x); + return new Result(result, x); } } } diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml index fedede3087c..4762bf5d57c 100644 --- a/jetty-distribution/pom.xml +++ b/jetty-distribution/pom.xml @@ -47,6 +47,7 @@ + org.apache.maven.plugins maven-dependency-plugin + org.ops4j.pax.exam diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java index 651fd354971..edfa3de5b24 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java @@ -42,7 +42,7 @@ import java.io.StringReader; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.fail; public class CookiePatternRuleTest diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 9215378668a..0be0552f29d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -21,12 +21,12 @@ package org.eclipse.jetty.server.handler; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -2610,35 +2610,25 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu // no security manager just return the classloader if (!_usingSecurityManager) + { return _classLoader; + } else { // check to see if the classloader of the caller is the same as the context - // classloader, or a parent of it - try + // classloader, or a parent of it, as required by the javadoc specification. + + // Wrap in a PrivilegedAction so that only Jetty code will require the + // "createSecurityManager" permission, not also application code that calls this method. + Caller caller = AccessController.doPrivileged((PrivilegedAction)Caller::new); + ClassLoader callerLoader = caller.getCallerClassLoader(2); + while (callerLoader != null) { - Class reflect = Loader.loadClass("sun.reflect.Reflection"); - Method getCallerClass = reflect.getMethod("getCallerClass",Integer.TYPE); - Class caller = (Class)getCallerClass.invoke(null,2); - - boolean ok = false; - ClassLoader callerLoader = caller.getClassLoader(); - while (!ok && callerLoader != null) - { - if (callerLoader == _classLoader) - ok = true; - else - callerLoader = callerLoader.getParent(); - } - - if (ok) + if (callerLoader == _classLoader) return _classLoader; + else + callerLoader = callerLoader.getParent(); } - catch (Exception e) - { - LOG.warn("Unable to check classloader of caller",e); - } - AccessController.checkPermission(new RuntimePermission("getClassLoader")); return _classLoader; } @@ -3161,4 +3151,17 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu */ void exitScope(Context context, Request request); } + + private static class Caller extends SecurityManager + { + public ClassLoader getCallerClassLoader(int depth) + { + if (depth < 0) + return null; + Class[] classContext = getClassContext(); + if (classContext.length <= depth) + return null; + return classContext[depth].getClassLoader(); + } + } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java index 4b9d167d45c..9043233ca10 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java @@ -31,12 +31,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.CompressedContentFormat; -import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpHeader; -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.http.MimeTypes; -import org.eclipse.jetty.http.PreEncodedHttpField; +import org.eclipse.jetty.http.*; import org.eclipse.jetty.http.pathmap.PathSpecSet; import org.eclipse.jetty.server.DeflaterPool; import org.eclipse.jetty.server.HttpOutput; @@ -156,6 +151,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory public static final int COMPRESSION_LEVEL = Deflater.DEFAULT_COMPRESSION; private static final Logger LOG = Log.getLogger(GzipHandler.class); private static final HttpField X_CE_GZIP = new PreEncodedHttpField("X-Content-Encoding","gzip"); + private static final HttpField TE_CHUNKED = new PreEncodedHttpField(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED.asString()); private static final Pattern COMMA_GZIP = Pattern.compile(".*, *gzip"); private int POOL_CAPACITY = -1; @@ -602,29 +598,46 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory // Handle request inflation if (_inflateBufferSize>0) { + boolean inflate = false; for (ListIterator i = baseRequest.getHttpFields().listIterator(); i.hasNext();) { HttpField field = i.next(); - if (field.getHeader()!=HttpHeader.CONTENT_ENCODING) - continue; - if (field.getValue().equalsIgnoreCase("gzip")) + if (field.getHeader()==HttpHeader.CONTENT_ENCODING) { - i.set(X_CE_GZIP); - baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(),_inflateBufferSize)); - break; - } + if (field.getValue().equalsIgnoreCase("gzip")) + { + i.set(X_CE_GZIP); + inflate = true; + break; + } - if (COMMA_GZIP.matcher(field.getValue()).matches()) - { - String v = field.getValue(); - v = v.substring(0,v.lastIndexOf(',')); - i.set(new HttpField(HttpHeader.CONTENT_ENCODING,v)); - i.add(X_CE_GZIP); - baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(),_inflateBufferSize)); - break; + if (COMMA_GZIP.matcher(field.getValue()).matches()) + { + String v = field.getValue(); + v = v.substring(0, v.lastIndexOf(',')); + i.set(new HttpField(HttpHeader.CONTENT_ENCODING, v)); + i.add(X_CE_GZIP); + inflate = true; + break; + } } - } + } + + if (inflate) + { + baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize)); + + for (ListIterator i = baseRequest.getHttpFields().listIterator(); i.hasNext();) + { + HttpField field = i.next(); + if (field.getHeader()==HttpHeader.CONTENT_LENGTH) + { + i.set(new HttpField("X-Content-Length", field.getValue())); + break; + } + } + } } // Are we already being gzipped? diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/CustomResourcesMonitorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/CustomResourcesMonitorTest.java index 57b4a5fe9a4..0048f34fcdb 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/CustomResourcesMonitorTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/CustomResourcesMonitorTest.java @@ -27,7 +27,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - import java.io.IOException; import java.io.InputStream; import java.net.Socket; @@ -38,7 +37,8 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.*; public class CustomResourcesMonitorTest { @@ -111,28 +111,14 @@ public class CustomResourcesMonitorTest InputStream input1 = socket1.getInputStream(); assertTrue(_fileOnDirectoryMonitor.isLowOnResources()); - try - { - input1.read(); - fail(); - } - catch (SocketTimeoutException expected) - { - } + assertThrows(SocketTimeoutException.class, () -> input1.read()); // Wait a couple of lowResources idleTimeouts. Thread.sleep(2 * lowResourcesIdleTimeout); // Verify the new socket is still open. assertTrue(_fileOnDirectoryMonitor.isLowOnResources()); - try - { - input1.read(); - fail(); - } - catch (SocketTimeoutException expected) - { - } + assertThrows(SocketTimeoutException.class, () -> input1.read()); Files.delete( tmpFile ); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/LowResourcesMonitorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/LowResourcesMonitorTest.java index 9d7bf40fcba..6cebfcdada6 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/LowResourcesMonitorTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/LowResourcesMonitorTest.java @@ -23,6 +23,7 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.TimerScheduler; import org.hamcrest.Matchers; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -38,7 +39,6 @@ import java.util.concurrent.CountDownLatch; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; -import static org.junit.Assert.fail; import static org.junit.jupiter.api.Assertions.*; public class LowResourcesMonitorTest @@ -248,28 +248,15 @@ public class LowResourcesMonitorTest InputStream input1 = socket1.getInputStream(); assertTrue(_lowResourcesMonitor.isLowOnResources()); - try - { - input1.read(); - fail(); - } - catch (SocketTimeoutException expected) - { - } + assertThrows( SocketTimeoutException.class, () -> input1.read()); // Wait a couple of lowResources idleTimeouts. Thread.sleep(2 * lowResourcesIdleTimeout); // Verify the new socket is still open. assertTrue(_lowResourcesMonitor.isLowOnResources()); - try - { - input1.read(); - fail(); - } - catch (SocketTimeoutException expected) - { - } + assertThrows( SocketTimeoutException.class, () -> input1.read()); + // Let the maxLowResourcesTime elapse. Thread.sleep(maxLowResourcesTime); diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java index 6a67f25abb9..48a39b7d2e7 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java @@ -18,32 +18,6 @@ package org.eclipse.jetty.servlet; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalToIgnoringCase; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.server.LocalConnector; import org.eclipse.jetty.server.Server; @@ -54,6 +28,33 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import javax.servlet.DispatcherType; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Enumeration; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + @SuppressWarnings("serial") public class GzipHandlerTest { @@ -104,6 +105,7 @@ public class GzipHandlerTest servlets.addServletWithMapping(IncludeServlet.class,"/include"); servlets.addServletWithMapping(EchoServlet.class,"/echo/*"); servlets.addServletWithMapping(DumpServlet.class,"/dump/*"); + servlets.addFilterWithMapping(CheckFilter.class,"/*", EnumSet.of(DispatcherType.REQUEST)); _server.start(); } @@ -508,6 +510,38 @@ public class GzipHandlerTest assertThat(response.getContent(),is(data)); } + + + @Test + public void testGzipRequestChunked() throws Exception + { + String data = "Hello Nice World! "; + for (int i = 0; i < 10; ++i) + data += data; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GZIPOutputStream output = new GZIPOutputStream(baos); + output.write(data.getBytes(StandardCharsets.UTF_8)); + output.close(); + byte[] bytes = baos.toByteArray(); + + // generated and parsed test + HttpTester.Request request = HttpTester.newRequest(); + HttpTester.Response response; + + request.setMethod("POST"); + request.setURI("/ctx/echo"); + request.setVersion("HTTP/1.1"); + request.setHeader("Host","tester"); + request.setHeader("Content-Type","text/plain"); + request.setHeader("Content-Encoding","gzip"); + request.add("Transfer-Encoding", "chunked"); + request.setContent(bytes); + response = HttpTester.parseResponse(_connector.getResponse(request.generate())); + + assertThat(response.getStatus(),is(200)); + assertThat(response.getContent(),is(data)); + + } @Test @@ -568,5 +602,27 @@ public class GzipHandlerTest assertThat(response.getStatus(),is(200)); assertThat(response.getContentBytes().length,is(512*1024)); } - + + public static class CheckFilter implements Filter + { + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException + { + if (request.getParameter("X-Content-Encoding")!=null) + assertEquals(-1,request.getContentLength()); + else if (request.getContentLength()>=0) + assertThat(request.getParameter("X-Content-Encoding"),Matchers.nullValue()); + chain.doFilter(request,response); + } + + @Override + public void destroy() + { + } + } } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/TypeUtilTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/TypeUtilTest.java index dc103c1b1d4..6349a364fae 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/TypeUtilTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/TypeUtilTest.java @@ -21,10 +21,10 @@ package org.eclipse.jetty.util; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assume.assumeTrue; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.nio.file.Path; import java.nio.file.Paths; diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/statistic/RateStatisticTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/statistic/RateStatisticTest.java index 0a768d4f990..9ef3e5578d2 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/statistic/RateStatisticTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/statistic/RateStatisticTest.java @@ -24,7 +24,8 @@ import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; + /* ------------------------------------------------------------ */ diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketUpgradeRequest.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketUpgradeRequest.java index 29a2622c849..a7b1ece3525 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketUpgradeRequest.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketUpgradeRequest.java @@ -411,9 +411,9 @@ public class WebSocketUpgradeRequest extends HttpRequest implements CompleteList { throw new IllegalStateException("Unable to start WebSocketClient", e); } - this.localEndpoint = localEndpoint; this.fut = new CompletableFuture<>(); + } private final String genRandomKey() @@ -503,6 +503,7 @@ public class WebSocketUpgradeRequest extends HttpRequest implements CompleteList } Throwable failure = result.getFailure(); + if ( (failure instanceof java.net.SocketException) || (failure instanceof java.io.InterruptedIOException) || (failure instanceof HttpResponseException) || diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java index e6a7b68b722..e00a8fe1fa3 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java @@ -845,7 +845,6 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem endpointFunctions.getLog().warn("Error during OPEN", t); onError(new CloseException(StatusCode.SERVER_ERROR, t)); } - /* Perform fillInterested outside of onConnected / onOpen. * * This is to allow for 2 specific scenarios. diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RedirectWebSocketClientTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RedirectWebSocketClientTest.java new file mode 100644 index 00000000000..e4d6ccbd0c4 --- /dev/null +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RedirectWebSocketClientTest.java @@ -0,0 +1,155 @@ +// +// ======================================================================== +// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.websocket.server; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import java.net.URI; +import java.util.concurrent.Future; + +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.HandlerList; +import org.eclipse.jetty.server.handler.SecuredRedirectHandler; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; +import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.server.helper.EchoServlet; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class RedirectWebSocketClientTest +{ + public static Server server; + public static URI serverWsUri; + public static URI serverWssUri; + + @BeforeAll + public static void startServer() throws Exception + { + server = new Server(); + + HttpConfiguration http_config = new HttpConfiguration(); + http_config.setSecureScheme("https"); + http_config.setSecurePort(0); + http_config.setOutputBufferSize(32768); + http_config.setRequestHeaderSize(8192); + http_config.setResponseHeaderSize(8192); + http_config.setSendServerVersion(true); + http_config.setSendDateHeader(false); + + SslContextFactory sslContextFactory = newSslContextFactory(); + + // SSL HTTP Configuration + HttpConfiguration https_config = new HttpConfiguration(http_config); + https_config.addCustomizer(new SecureRequestCustomizer()); + + // SSL Connector + ServerConnector sslConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), new HttpConnectionFactory(https_config)); + sslConnector.setPort(0); + server.addConnector(sslConnector); + + // Normal Connector + ServerConnector connector = new ServerConnector(server); + connector.setPort(0); + server.addConnector(connector); + + ServletContextHandler contextHandler = new ServletContextHandler(); + contextHandler.setContextPath("/"); + contextHandler.addServlet(EchoServlet.class, "/echo"); + + HandlerList handlers = new HandlerList(); + + handlers.addHandler(new SecuredRedirectHandler()); + handlers.addHandler(contextHandler); + handlers.addHandler(new DefaultHandler()); + + server.setHandler(handlers); + + server.start(); + + serverWsUri = URI.create("ws://localhost:" + connector.getLocalPort() + "/"); + serverWssUri = URI.create("wss://localhost:" + sslConnector.getLocalPort() + "/"); + + // adjust HttpConfiguration in connector + HttpConnectionFactory connectionFactory = connector.getConnectionFactory(HttpConnectionFactory.class); + connectionFactory.getHttpConfiguration().setSecurePort(sslConnector.getLocalPort()); + } + + @AfterAll + public static void stopServer() throws Exception + { + server.stop(); + } + + private static SslContextFactory newSslContextFactory() + { + SslContextFactory ssl = new SslContextFactory(); + ssl.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath()); + ssl.setKeyStorePassword("storepwd"); + ssl.setKeyManagerPassword("keypwd"); + return ssl; + } + + @Test + public void testRedirect() throws Exception + { + SslContextFactory ssl = newSslContextFactory(); + ssl.setTrustAll(false); + ssl.setEndpointIdentificationAlgorithm(null); + HttpClient httpClient = new HttpClient(ssl); + + WebSocketClient client = new WebSocketClient(httpClient); + client.addBean(httpClient, true); + client.start(); + + try + { + URI wsUri = serverWsUri.resolve("/echo"); + + ClientUpgradeRequest request = new ClientUpgradeRequest(); + Future sessionFuture = client.connect(new EmptyWebSocket(), wsUri, request); + Session session = sessionFuture.get(); + assertThat(session, is(notNullValue())); + } + finally + { + client.stop(); + } + } + + @WebSocket + public static class EmptyWebSocket { + + } +} diff --git a/pom.xml b/pom.xml index 97d4f395540..115ad628715 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,8 @@ 2.4.5.Final 1.0.5 + + false 2.22.0 @@ -50,7 +52,7 @@ - 5.0 + 5.1 @@ -647,6 +649,8 @@ ${project.build.directory} ${unix.socket.tmp} + true + ${jetty.testtracker.log} diff --git a/tests/test-integration/src/test/java/org/eclipse/jetty/test/support/JettyDistro.java b/tests/test-integration/src/test/java/org/eclipse/jetty/test/support/JettyDistro.java index 3cc69f47f27..27994a3e1d3 100644 --- a/tests/test-integration/src/test/java/org/eclipse/jetty/test/support/JettyDistro.java +++ b/tests/test-integration/src/test/java/org/eclipse/jetty/test/support/JettyDistro.java @@ -258,7 +258,7 @@ public class JettyDistro */ public JettyDistro(Class clazz, String artifact) throws IOException { - this.jettyHomeDir = MavenTestingUtils.getTargetTestingDir(clazz,"jettyHome"); + this.jettyHomeDir = MavenTestingUtils.getTargetTestingPath(clazz,"jettyHome").toFile(); if (artifact != null) { this.artifactName = artifact; diff --git a/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/ClusteredOrphanedSessionTest.java b/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/ClusteredOrphanedSessionTest.java index 0e54b028bc3..fb192d31b60 100644 --- a/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/ClusteredOrphanedSessionTest.java +++ b/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/ClusteredOrphanedSessionTest.java @@ -22,6 +22,7 @@ package org.eclipse.jetty.gcloud.session; import org.eclipse.jetty.server.session.AbstractClusteredOrphanedSessionTest; import org.eclipse.jetty.server.session.SessionDataStoreFactory; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; /** @@ -32,10 +33,25 @@ import org.junit.jupiter.api.Test; public class ClusteredOrphanedSessionTest extends AbstractClusteredOrphanedSessionTest { + public static GCloudSessionTestSupport __testSupport; + + @BeforeAll + public static void setUp () throws Exception + { + __testSupport = new GCloudSessionTestSupport(); + __testSupport.setUp(); + } + + @AfterAll + public static void tearDown () throws Exception + { + __testSupport.tearDown(); + } + @AfterAll public static void teardown () throws Exception { - GCloudTestSuite.__testSupport.deleteSessions(); + __testSupport.deleteSessions(); } @@ -46,7 +62,7 @@ public class ClusteredOrphanedSessionTest extends AbstractClusteredOrphanedSessi @Override public SessionDataStoreFactory createSessionDataStoreFactory() { - return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore()); + return GCloudSessionTestSupport.newSessionDataStoreFactory(__testSupport.getDatastore()); } diff --git a/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/ClusteredSessionScavengingTest.java b/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/ClusteredSessionScavengingTest.java index ab430f9c03a..31393388e63 100644 --- a/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/ClusteredSessionScavengingTest.java +++ b/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/ClusteredSessionScavengingTest.java @@ -22,6 +22,7 @@ package org.eclipse.jetty.gcloud.session; import org.eclipse.jetty.server.session.AbstractClusteredSessionScavengingTest; import org.eclipse.jetty.server.session.SessionDataStoreFactory; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; /** * ClusteredSessionScavengingTest @@ -30,11 +31,26 @@ import org.junit.jupiter.api.AfterAll; */ public class ClusteredSessionScavengingTest extends AbstractClusteredSessionScavengingTest { - + + public static GCloudSessionTestSupport __testSupport; + + @BeforeAll + public static void setUp () throws Exception + { + __testSupport = new GCloudSessionTestSupport(); + __testSupport.setUp(); + } + + @AfterAll + public static void tearDown () throws Exception + { + __testSupport.tearDown(); + } + @AfterAll public static void teardown () throws Exception { - GCloudTestSuite.__testSupport.deleteSessions(); + __testSupport.deleteSessions(); } @@ -44,7 +60,7 @@ public class ClusteredSessionScavengingTest extends AbstractClusteredSessionScav @Override public SessionDataStoreFactory createSessionDataStoreFactory() { - return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore()); + return GCloudSessionTestSupport.newSessionDataStoreFactory(__testSupport.getDatastore()); } diff --git a/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/GCloudSessionDataStoreTest.java b/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/GCloudSessionDataStoreTest.java index b652e034d7b..d10de993b63 100644 --- a/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/GCloudSessionDataStoreTest.java +++ b/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/GCloudSessionDataStoreTest.java @@ -22,7 +22,9 @@ package org.eclipse.jetty.gcloud.session; import org.eclipse.jetty.server.session.AbstractSessionDataStoreTest; import org.eclipse.jetty.server.session.SessionData; import org.eclipse.jetty.server.session.SessionDataStoreFactory; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; /** * GCloudSessionDataStoreTest @@ -32,24 +34,39 @@ import org.junit.jupiter.api.AfterEach; public class GCloudSessionDataStoreTest extends AbstractSessionDataStoreTest { + public static GCloudSessionTestSupport __testSupport; + + @BeforeAll + public static void setUp () throws Exception + { + __testSupport = new GCloudSessionTestSupport(); + __testSupport.setUp(); + } + + @AfterAll + public static void tearDown () throws Exception + { + __testSupport.tearDown(); + } + @AfterEach public void teardown () throws Exception { - GCloudTestSuite.__testSupport.deleteSessions(); + __testSupport.deleteSessions(); } @Override public SessionDataStoreFactory createSessionDataStoreFactory() { - return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore()); + return GCloudSessionTestSupport.newSessionDataStoreFactory(__testSupport.getDatastore()); } @Override public void persistSession(SessionData data) throws Exception { - GCloudTestSuite.__testSupport.createSession(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(), data.getCreated(), + __testSupport.createSession(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(), data.getCreated(), data.getAccessed(), data.getLastAccessed(), data.getMaxInactiveMs(), data.getExpiry(), data.getCookieSet(), data.getLastSaved(), data.getAllAttributes()); @@ -60,7 +77,7 @@ public class GCloudSessionDataStoreTest extends AbstractSessionDataStoreTest public void persistUnreadableSession(SessionData data) throws Exception { - GCloudTestSuite.__testSupport.createSession(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(), data.getCreated(), + __testSupport.createSession(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(), data.getCreated(), data.getAccessed(), data.getLastAccessed(), data.getMaxInactiveMs(), data.getExpiry(), data.getCookieSet(), data.getLastSaved(), null); } @@ -69,7 +86,7 @@ public class GCloudSessionDataStoreTest extends AbstractSessionDataStoreTest @Override public boolean checkSessionExists(SessionData data) throws Exception { - return GCloudTestSuite.__testSupport.checkSessionExists(data.getId()); + return __testSupport.checkSessionExists(data.getId()); } @@ -79,7 +96,7 @@ public class GCloudSessionDataStoreTest extends AbstractSessionDataStoreTest @Override public boolean checkSessionPersisted(SessionData data) throws Exception { - return GCloudTestSuite.__testSupport.checkSessionPersisted(data); + return __testSupport.checkSessionPersisted(data); } } diff --git a/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/GCloudTestSuite.java b/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/GCloudTestSuite.java deleted file mode 100644 index a77dd76aceb..00000000000 --- a/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/GCloudTestSuite.java +++ /dev/null @@ -1,55 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.gcloud.session; - -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -/** - * GCloudTestSuite - * - * Sets up the gcloud emulator once before running all tests. - * - */ -@RunWith(Suite.class) -@Suite.SuiteClasses({ - GCloudSessionDataStoreTest.class, - InvalidationSessionTest.class, - ClusteredSessionScavengingTest.class, - ClusteredOrphanedSessionTest.class -}) -public class GCloudTestSuite -{ - public static GCloudSessionTestSupport __testSupport; - - @BeforeAll - public static void setUp () throws Exception - { - __testSupport = new GCloudSessionTestSupport(); - __testSupport.setUp(); - } - - @AfterAll - public static void tearDown () throws Exception - { - __testSupport.tearDown(); - } -} diff --git a/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/InvalidationSessionTest.java b/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/InvalidationSessionTest.java index 476c8dd9e18..3e7809aa82a 100644 --- a/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/InvalidationSessionTest.java +++ b/tests/test-sessions/test-gcloud-sessions/src/test/java/org/eclipse/jetty/gcloud/session/InvalidationSessionTest.java @@ -23,6 +23,7 @@ package org.eclipse.jetty.gcloud.session; import org.eclipse.jetty.server.session.AbstractClusteredInvalidationSessionTest; import org.eclipse.jetty.server.session.SessionDataStoreFactory; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; /** * InvalidationSessionTest @@ -31,11 +32,26 @@ import org.junit.jupiter.api.AfterAll; */ public class InvalidationSessionTest extends AbstractClusteredInvalidationSessionTest { - + + public static GCloudSessionTestSupport __testSupport; + + @BeforeAll + public static void setUp () throws Exception + { + __testSupport = new GCloudSessionTestSupport(); + __testSupport.setUp(); + } + + @AfterAll + public static void tearDown () throws Exception + { + __testSupport.tearDown(); + } + @AfterAll public static void teardown () throws Exception { - GCloudTestSuite.__testSupport.deleteSessions(); + __testSupport.deleteSessions(); } /** @@ -44,6 +60,6 @@ public class InvalidationSessionTest extends AbstractClusteredInvalidationSessio @Override public SessionDataStoreFactory createSessionDataStoreFactory() { - return GCloudSessionTestSupport.newSessionDataStoreFactory(GCloudTestSuite.__testSupport.getDatastore()); + return GCloudSessionTestSupport.newSessionDataStoreFactory(__testSupport.getDatastore()); } }