Merge remote-tracking branch 'origin/master' into jetty-http2
Conflicts: VERSION.txt aggregates/jetty-all/pom.xml apache-jsp/pom.xml apache-jstl/pom.xml examples/async-rest/async-rest-jar/pom.xml examples/async-rest/async-rest-webapp/pom.xml examples/async-rest/pom.xml examples/embedded/pom.xml examples/pom.xml examples/quickstart/pom.xml jetty-alpn/jetty-alpn-client/pom.xml jetty-alpn/jetty-alpn-server/pom.xml jetty-alpn/pom.xml jetty-annotations/pom.xml jetty-ant/pom.xml jetty-client/pom.xml jetty-continuation/pom.xml jetty-deploy/pom.xml jetty-distribution/pom.xml jetty-fcgi/fcgi-client/pom.xml jetty-fcgi/fcgi-server/pom.xml jetty-fcgi/pom.xml jetty-http-spi/pom.xml jetty-http/pom.xml jetty-io/pom.xml jetty-jaas/pom.xml jetty-jaspi/pom.xml jetty-jmx/pom.xml jetty-jndi/pom.xml jetty-jsp/pom.xml jetty-jspc-maven-plugin/pom.xml jetty-maven-plugin/pom.xml jetty-monitor/pom.xml jetty-nosql/pom.xml jetty-osgi/jetty-osgi-alpn/pom.xml jetty-osgi/jetty-osgi-boot-jsp/pom.xml jetty-osgi/jetty-osgi-boot-warurl/pom.xml jetty-osgi/jetty-osgi-boot/pom.xml jetty-osgi/jetty-osgi-httpservice/pom.xml jetty-osgi/jetty-osgi-npn/pom.xml jetty-osgi/pom.xml jetty-osgi/test-jetty-osgi-context/pom.xml jetty-osgi/test-jetty-osgi-webapp/pom.xml jetty-osgi/test-jetty-osgi/pom.xml jetty-plus/pom.xml jetty-proxy/pom.xml jetty-quickstart/pom.xml jetty-rewrite/pom.xml jetty-runner/pom.xml jetty-security/pom.xml jetty-server/pom.xml jetty-servlet/pom.xml jetty-servlets/pom.xml jetty-spdy/pom.xml jetty-spdy/spdy-alpn-tests/pom.xml jetty-spdy/spdy-client/pom.xml jetty-spdy/spdy-core/pom.xml jetty-spdy/spdy-example-webapp/pom.xml jetty-spdy/spdy-http-client-transport/pom.xml jetty-spdy/spdy-http-common/pom.xml jetty-spdy/spdy-http-server/pom.xml jetty-spdy/spdy-npn-tests/pom.xml jetty-spdy/spdy-server/pom.xml jetty-spring/pom.xml jetty-start/pom.xml jetty-util-ajax/pom.xml jetty-util/pom.xml jetty-webapp/pom.xml jetty-websocket/javax-websocket-client-impl/pom.xml jetty-websocket/javax-websocket-server-impl/pom.xml jetty-websocket/pom.xml jetty-websocket/websocket-api/pom.xml jetty-websocket/websocket-client/pom.xml jetty-websocket/websocket-common/pom.xml jetty-websocket/websocket-server/pom.xml jetty-websocket/websocket-servlet/pom.xml jetty-xml/pom.xml pom.xml tests/pom.xml tests/test-continuation/pom.xml tests/test-integration/pom.xml tests/test-loginservice/pom.xml tests/test-sessions/pom.xml tests/test-sessions/test-hash-sessions/pom.xml tests/test-sessions/test-jdbc-sessions/pom.xml tests/test-sessions/test-mongodb-sessions/pom.xml tests/test-sessions/test-sessions-common/pom.xml tests/test-webapps/pom.xml tests/test-webapps/test-dispatch-webapp/pom.xml tests/test-webapps/test-jaas-webapp/pom.xml tests/test-webapps/test-jetty-webapp/pom.xml tests/test-webapps/test-jndi-webapp/pom.xml tests/test-webapps/test-mock-resources/pom.xml tests/test-webapps/test-proxy-webapp/pom.xml tests/test-webapps/test-servlet-spec/pom.xml tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml tests/test-webapps/test-webapp-rfc2616/pom.xml
This commit is contained in:
commit
66980f2449
62
VERSION.txt
62
VERSION.txt
|
@ -1,6 +1,64 @@
|
|||
jetty-10.0.0-SNAPSHOT
|
||||
jetty-9.3.0-SNAPSHOT
|
||||
|
||||
jetty-9.2.2-SNAPSHOT
|
||||
jetty-9.2.3-SNAPSHOT
|
||||
|
||||
jetty-9.2.2-v20140723 - 23 July 2014
|
||||
+ 411323 DosFilter/QoSFilter should use AsyncContext rather than
|
||||
Continuations.
|
||||
+ 432815 Fixed selector stop race
|
||||
+ 434536 Improved Customizer javadoc
|
||||
+ 435322 Fixed Iterating Callback close
|
||||
+ 435653 encode async dispatched requestURI
|
||||
+ 435895 jetty spring module is not in distribution
|
||||
+ 436874 WebSocket client throwing a NullPointer when handling a pong
|
||||
+ 436894 GzipFilter code cleanup
|
||||
+ 436916 CGI: "Search docroot for a matching execCmd" logic is wrong
|
||||
+ 436987 limited range of default acceptors and selectors
|
||||
+ 437051 Refactor Filter chain handling of Request.isAsyncSupported
|
||||
+ 437395 Start / Properties in template sections should be default applied for
|
||||
enabled modules
|
||||
+ 437419 Allow scanning of META-INF for resources,fragments,tlds for unpacked
|
||||
jars
|
||||
+ 437430 jettyXml not consistent between jetty:run and jetty:run-forked
|
||||
+ 437462 consistent test failure in jetty-start under windows
|
||||
+ 437706 ServletTester calls LocalConnector method with hardcoded timeout
|
||||
+ 437800 URLs with single quote and spaces return 404
|
||||
+ 437996 avoid async status race by not setting 200 on handled
|
||||
+ 438079 Review garbage creation in 9.2.x series.
|
||||
+ 438190 findbug improvements
|
||||
+ 438204 leave IPv6 addresses [] wrapped in getServerName
|
||||
+ 438327 Remove hard coded Allow from OPTIONS *
|
||||
+ 438331 AbstractLogger.debug(String,long) infinite loop
|
||||
+ 438434 ResourceHandler checks aliases
|
||||
+ 438895 Add mvn jetty:effective-web-xml goal
|
||||
+ 439066 javadoc setStopAtShutdown
|
||||
+ 439067 Improved graceful stop timeout handling
|
||||
+ 439194 Do not configure fake server for jetty:run-forked
|
||||
+ 439201 GzipFilter and AsyncGzipFilter should strip charset from Content-Type
|
||||
before making exclusion comparison in doFilter
|
||||
+ 439369 Deprecate CrossContextPseudoSession
|
||||
+ 439387 Ensure empty servlet-class never generated for quickstart
|
||||
+ 439390 Ensure jsp scratchdir is created same way for quickstart and
|
||||
non-quickstart
|
||||
+ 439394 load-on-startup with value 0 not preserved for quickstart
|
||||
+ 439399 Scan tlds for apache jasper standard taglib with jetty-maven-plugin
|
||||
+ 439438 DataSourceLoginService does not refresh passwords when changed in
|
||||
database
|
||||
+ 439507 Possible timing side-channel when comparing MD5-Credentials
|
||||
+ 439540 setReuseAddress() in ServerConnector.java is not coded properly
|
||||
+ 439652 GzipHandler super.doStart
|
||||
+ 439663 Allow mappings to be declared before servlet/filter
|
||||
+ 439672 support using Apache commons daemon for managing Jetty
|
||||
+ 439753 ConstraintSecurityHandler has dead code for processing constraints
|
||||
+ 439788 CORS filter headers gone between 9.2.0.M0 and 9.2.1 .v20140609 for
|
||||
ProxyServlet requests.
|
||||
+ 439809 mvn jetty:jspc cannot find taglibs in dependency jars
|
||||
+ 439895 No event callback should be invoked after the "failure" callback.
|
||||
+ 440020 Abort bad proxy responses with sendError(-1)
|
||||
+ 440038 Content decoding may fail.
|
||||
+ 440114 ContextHandlerCollection does not skip context wrappers
|
||||
+ 440122 Remove usages of ForkInvoker.
|
||||
>>>>>>> origin/master
|
||||
|
||||
jetty-9.2.1.v20140609 - 09 June 2014
|
||||
+ 347110 Supprt ClassFileTransormers in WebAppClassLoader
|
||||
|
|
|
@ -63,6 +63,20 @@
|
|||
<type>war</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-spec-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>test-jetty-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>javax-websocket-server-impl</artifactId>
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
</goals>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Import-Package>javax.servlet.*;version="[2.6.0,3.2)",org.objectweb.asm.*;version=4,*</Import-Package>
|
||||
<Import-Package>javax.servlet.*;version="[2.6.0,3.2)",org.objectweb.asm.*;version=5,*</Import-Package>
|
||||
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=javax.servlet.ServletContainerInitializer)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)"</Require-Capability>
|
||||
</instructions>
|
||||
</configuration>
|
||||
|
|
|
@ -698,7 +698,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||
contentLatch.set(new CountDownLatch(1));
|
||||
callback.succeeded();
|
||||
|
||||
Assert.assertTrue(completeLatch.await(555, TimeUnit.SECONDS));
|
||||
Assert.assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
|
||||
Assert.assertEquals(2, contentCount.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,6 @@ import java.net.URI;
|
|||
import java.net.URL;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TreeSet;
|
||||
|
@ -35,7 +32,6 @@ import org.eclipse.jetty.annotations.ClassNameResolver;
|
|||
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
|
||||
import org.eclipse.jetty.util.ConcurrentHashSet;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.Constants;
|
||||
|
||||
|
@ -51,13 +47,6 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
|
|||
private ConcurrentHashMap<Resource, Bundle> _resourceToBundle = new ConcurrentHashMap<Resource, Bundle>();
|
||||
private ConcurrentHashMap<Bundle,URI> _bundleToUri = new ConcurrentHashMap<Bundle, URI>();
|
||||
|
||||
static
|
||||
{
|
||||
//As of jetty 9.2.0, the impl of asm visitor classes is compatible with both asm4 and asm5.
|
||||
//We need to use asm4 with osgi, because we need to use aries spifly to support annotations,
|
||||
//and currently this only supports asm4. Therefore, we set the asm api version to be 4 for osgi.
|
||||
ASM_OPCODE_VERSION = Opcodes.ASM4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of a jetty URI Resource and its associated OSGi bundle.
|
||||
|
@ -212,5 +201,4 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
|
|||
scanClass(handlers, getResource(bundle), classUrl.openStream());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -164,24 +164,10 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.aries.spifly</groupId>
|
||||
<artifactId>org.apache.aries.spifly.dynamic.bundle</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>1.0.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<version>4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-commons</artifactId>
|
||||
<version>4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-tree</artifactId>
|
||||
<version>4.1</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<!-- Jetty Deps -->
|
||||
|
@ -189,20 +175,6 @@
|
|||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-annotations</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-commons</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm-tree</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
|
@ -362,31 +334,6 @@
|
|||
</dependency>
|
||||
|
||||
<!-- Eclipse OSGi Deps -->
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.eclipse.osgi</groupId>
|
||||
<artifactId>org.eclipse.osgi</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.osgi</groupId>
|
||||
<artifactId>org.eclipse.osgi.services</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.equinox.http</groupId>
|
||||
<artifactId>servlet</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
-->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>test-jetty-webapp</artifactId>
|
||||
|
|
|
@ -31,13 +31,12 @@ import javax.inject.Inject;
|
|||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.ops4j.pax.exam.Configuration;
|
||||
import org.ops4j.pax.exam.CoreOptions;
|
||||
import org.ops4j.pax.exam.MavenUtils;
|
||||
import org.ops4j.pax.exam.Option;
|
||||
import org.ops4j.pax.exam.Configuration;
|
||||
import org.ops4j.pax.exam.junit.PaxExam;
|
||||
import org.ops4j.pax.exam.options.MavenUrlReference.VersionResolver;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
|
||||
|
@ -64,7 +63,7 @@ public class TestJettyOSGiBootCore
|
|||
options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
|
||||
options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
|
||||
options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
|
||||
|
||||
options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.annotations.LEVEL").value("DEBUG"))));
|
||||
return options.toArray(new Option[options.size()]);
|
||||
}
|
||||
|
||||
|
@ -82,20 +81,12 @@ public class TestJettyOSGiBootCore
|
|||
public static List<Option> coreJettyDependencies()
|
||||
{
|
||||
List<Option> res = new ArrayList<Option>();
|
||||
|
||||
String jdk = System.getProperty("java.version");
|
||||
int firstdot = jdk.indexOf(".");
|
||||
jdk = jdk.substring(0,firstdot+2);
|
||||
double version = Double.parseDouble(jdk);
|
||||
|
||||
if (version < 1.8)
|
||||
{
|
||||
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm" ).versionAsInProject().start());
|
||||
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-commons" ).versionAsInProject().start());
|
||||
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-tree" ).versionAsInProject().start());
|
||||
res.add(mavenBundle().groupId( "org.apache.aries" ).artifactId( "org.apache.aries.util" ).version("1.0.0").start());
|
||||
res.add(mavenBundle().groupId( "org.apache.aries.spifly" ).artifactId( "org.apache.aries.spifly.dynamic.bundle" ).version("1.0.0").start());
|
||||
}
|
||||
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm" ).versionAsInProject().start());
|
||||
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-commons" ).versionAsInProject().start());
|
||||
res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-tree" ).versionAsInProject().start());
|
||||
res.add(mavenBundle().groupId( "org.apache.aries" ).artifactId( "org.apache.aries.util" ).versionAsInProject().start());
|
||||
res.add(mavenBundle().groupId( "org.apache.aries.spifly" ).artifactId( "org.apache.aries.spifly.dynamic.bundle" ).versionAsInProject().start());
|
||||
|
||||
res.add(mavenBundle().groupId( "javax.servlet" ).artifactId( "javax.servlet-api" ).versionAsInProject().noStart());
|
||||
res.add(mavenBundle().groupId( "javax.annotation" ).artifactId( "javax.annotation-api" ).versionAsInProject().noStart());
|
||||
|
@ -119,10 +110,7 @@ public class TestJettyOSGiBootCore
|
|||
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-client" ).versionAsInProject().noStart());
|
||||
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-jndi" ).versionAsInProject().noStart());
|
||||
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-plus" ).versionAsInProject().noStart());
|
||||
if (version < 1.8)
|
||||
{
|
||||
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-annotations" ).versionAsInProject().start());
|
||||
}
|
||||
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-annotations" ).versionAsInProject().start());
|
||||
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-api" ).versionAsInProject().noStart());
|
||||
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-common" ).versionAsInProject().noStart());
|
||||
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-servlet" ).versionAsInProject().noStart());
|
||||
|
|
|
@ -60,7 +60,8 @@ public class AsyncProxyServlet extends ProxyServlet
|
|||
{
|
||||
try
|
||||
{
|
||||
_log.debug("{} proxying content to downstream: {} bytes", getRequestId(request), length);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} proxying content to downstream: {} bytes", getRequestId(request), length);
|
||||
StreamWriter writeListener = (StreamWriter)request.getAttribute(WRITE_LISTENER_ATTRIBUTE);
|
||||
if (writeListener == null)
|
||||
{
|
||||
|
@ -130,24 +131,30 @@ public class AsyncProxyServlet extends ProxyServlet
|
|||
{
|
||||
int requestId = getRequestId(request);
|
||||
ServletInputStream input = request.getInputStream();
|
||||
_log.debug("{} asynchronous read start on {}", requestId, input);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} asynchronous read start on {}", requestId, input);
|
||||
|
||||
// First check for isReady() because it has
|
||||
// side effects, and then for isFinished().
|
||||
while (input.isReady() && !input.isFinished())
|
||||
{
|
||||
int read = input.read(buffer);
|
||||
_log.debug("{} asynchronous read {} bytes on {}", requestId, read, input);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} asynchronous read {} bytes on {}", requestId, read, input);
|
||||
if (read > 0)
|
||||
{
|
||||
_log.debug("{} proxying content to upstream: {} bytes", requestId, read);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} proxying content to upstream: {} bytes", requestId, read);
|
||||
onRequestContent(proxyRequest, request, provider, buffer, 0, read, this);
|
||||
// Do not call isReady() so that we can apply backpressure.
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!input.isFinished())
|
||||
_log.debug("{} asynchronous read pending on {}", requestId, input);
|
||||
{
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} asynchronous read pending on {}", requestId, input);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onRequestContent(Request proxyRequest, HttpServletRequest request, DeferredContentProvider provider, byte[] buffer, int offset, int length, Callback callback)
|
||||
|
@ -158,7 +165,8 @@ public class AsyncProxyServlet extends ProxyServlet
|
|||
@Override
|
||||
public void onAllDataRead() throws IOException
|
||||
{
|
||||
_log.debug("{} proxying content to upstream completed", getRequestId(request));
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} proxying content to upstream completed", getRequestId(request));
|
||||
provider.close();
|
||||
}
|
||||
|
||||
|
@ -225,23 +233,27 @@ public class AsyncProxyServlet extends ProxyServlet
|
|||
if (state == WriteState.READY)
|
||||
{
|
||||
// There is data to write.
|
||||
_log.debug("{} asynchronous write start of {} bytes on {}", requestId, length, output);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} asynchronous write start of {} bytes on {}", requestId, length, output);
|
||||
output.write(buffer, offset, length);
|
||||
state = WriteState.PENDING;
|
||||
if (output.isReady())
|
||||
{
|
||||
_log.debug("{} asynchronous write of {} bytes completed on {}", requestId, length, output);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} asynchronous write of {} bytes completed on {}", requestId, length, output);
|
||||
complete();
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.debug("{} asynchronous write of {} bytes pending on {}", requestId, length, output);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} asynchronous write of {} bytes pending on {}", requestId, length, output);
|
||||
}
|
||||
}
|
||||
else if (state == WriteState.PENDING)
|
||||
{
|
||||
// The write blocked but is now complete.
|
||||
_log.debug("{} asynchronous write of {} bytes completing on {}", requestId, length, output);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} asynchronous write of {} bytes completing on {}", requestId, length, output);
|
||||
complete();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.UnavailableException;
|
||||
import javax.servlet.http.Cookie;
|
||||
|
@ -133,7 +132,8 @@ public class BalancerServlet extends ProxyServlet
|
|||
protected URI rewriteURI(HttpServletRequest request)
|
||||
{
|
||||
BalancerMember balancerMember = selectBalancerMember(request);
|
||||
_log.debug("Selected {}", balancerMember);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("Selected {}", balancerMember);
|
||||
String path = request.getRequestURI();
|
||||
String query = request.getQueryString();
|
||||
if (query != null)
|
||||
|
|
|
@ -119,7 +119,8 @@ public abstract class ProxyConnection extends AbstractConnection
|
|||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
LOG.debug(ProxyConnection.this + " could not fill", x);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(ProxyConnection.this + " could not fill", x);
|
||||
disconnect();
|
||||
return Action.SUCCEEDED;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import java.util.Set;
|
|||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
|
@ -52,7 +51,6 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.server.HttpConnection;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.HttpCookieStore;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -203,7 +201,8 @@ public class ProxyServlet extends HttpServlet
|
|||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
_log.debug(x);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,7 +363,8 @@ public class ProxyServlet extends HttpServlet
|
|||
{
|
||||
if (!_whiteList.contains(hostPort))
|
||||
{
|
||||
_log.debug("Host {}:{} not whitelisted", host, port);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("Host {}:{} not whitelisted", host, port);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +372,8 @@ public class ProxyServlet extends HttpServlet
|
|||
{
|
||||
if (_blackList.contains(hostPort))
|
||||
{
|
||||
_log.debug("Host {}:{} blacklisted", host, port);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("Host {}:{} blacklisted", host, port);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +392,8 @@ public class ProxyServlet extends HttpServlet
|
|||
StringBuffer uri = request.getRequestURL();
|
||||
if (request.getQueryString() != null)
|
||||
uri.append("?").append(request.getQueryString());
|
||||
_log.debug("{} rewriting: {} -> {}", requestId, uri, rewrittenURI);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} rewriting: {} -> {}", requestId, uri, rewrittenURI);
|
||||
}
|
||||
|
||||
if (rewrittenURI == null)
|
||||
|
@ -495,7 +497,8 @@ public class ProxyServlet extends HttpServlet
|
|||
|
||||
protected void onClientRequestFailure(Request proxyRequest, HttpServletRequest request, Throwable failure)
|
||||
{
|
||||
_log.debug(getRequestId(request) + " client request failure", failure);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug(getRequestId(request) + " client request failure", failure);
|
||||
proxyRequest.abort(failure);
|
||||
}
|
||||
|
||||
|
@ -538,7 +541,8 @@ public class ProxyServlet extends HttpServlet
|
|||
{
|
||||
try
|
||||
{
|
||||
_log.debug("{} proxying content to downstream: {} bytes", getRequestId(request), length);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} proxying content to downstream: {} bytes", getRequestId(request), length);
|
||||
response.getOutputStream().write(buffer, offset, length);
|
||||
callback.succeeded();
|
||||
}
|
||||
|
@ -550,27 +554,30 @@ public class ProxyServlet extends HttpServlet
|
|||
|
||||
protected void onResponseSuccess(HttpServletRequest request, HttpServletResponse response, Response proxyResponse)
|
||||
{
|
||||
_log.debug("{} proxying successful", getRequestId(request));
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} proxying successful", getRequestId(request));
|
||||
AsyncContext asyncContext = request.getAsyncContext();
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
protected void onResponseFailure(HttpServletRequest request, HttpServletResponse response, Response proxyResponse, Throwable failure)
|
||||
{
|
||||
_log.debug(getRequestId(request) + " proxying failed", failure);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug(getRequestId(request) + " proxying failed", failure);
|
||||
if (response.isCommitted())
|
||||
{
|
||||
// Use Jetty specific behavior to close connection
|
||||
try
|
||||
{
|
||||
// Use Jetty specific behavior to close connection.
|
||||
response.sendError(-1);
|
||||
AsyncContext asyncContext = request.getAsyncContext();
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (IOException x)
|
||||
{
|
||||
getServletContext().log("close failed", e);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug(getRequestId(request) + " could not close the connection", failure);
|
||||
}
|
||||
AsyncContext asyncContext = request.getAsyncContext();
|
||||
asyncContext.complete();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -687,7 +694,8 @@ public class ProxyServlet extends HttpServlet
|
|||
String contextPath = config.getServletContext().getContextPath();
|
||||
_prefix = _prefix == null ? contextPath : (contextPath + _prefix);
|
||||
|
||||
proxyServlet._log.debug(config.getServletName() + " @ " + _prefix + " to " + _proxyTo);
|
||||
if (proxyServlet._log.isDebugEnabled())
|
||||
proxyServlet._log.debug(config.getServletName() + " @ " + _prefix + " to " + _proxyTo);
|
||||
}
|
||||
|
||||
protected URI rewriteURI(HttpServletRequest request)
|
||||
|
@ -807,7 +815,8 @@ public class ProxyServlet extends HttpServlet
|
|||
onResponseSuccess(request, response, result.getResponse());
|
||||
else
|
||||
onResponseFailure(request, response, result.getResponse(), result.getFailure());
|
||||
_log.debug("{} proxying complete", getRequestId(request));
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} proxying complete", getRequestId(request));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -832,7 +841,8 @@ public class ProxyServlet extends HttpServlet
|
|||
@Override
|
||||
protected ByteBuffer onRead(byte[] buffer, int offset, int length)
|
||||
{
|
||||
_log.debug("{} proxying content to upstream: {} bytes", getRequestId(request), length);
|
||||
if (_log.isDebugEnabled())
|
||||
_log.debug("{} proxying content to upstream: {} bytes", getRequestId(request), length);
|
||||
return onRequestContent(proxyRequest, request, buffer, offset, length);
|
||||
}
|
||||
|
||||
|
|
|
@ -354,7 +354,7 @@ public class ProxyServletTest
|
|||
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
|
||||
.method(HttpMethod.POST)
|
||||
.content(new BytesContentProvider(content))
|
||||
.timeout(555, TimeUnit.SECONDS)
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
|
|
|
@ -31,7 +31,9 @@ import java.util.concurrent.Semaphore;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.AsyncEvent;
|
||||
import javax.servlet.AsyncListener;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
@ -47,9 +49,7 @@ import javax.servlet.http.HttpSessionBindingEvent;
|
|||
import javax.servlet.http.HttpSessionBindingListener;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
|
||||
import org.eclipse.jetty.continuation.Continuation;
|
||||
import org.eclipse.jetty.continuation.ContinuationListener;
|
||||
import org.eclipse.jetty.continuation.ContinuationSupport;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.annotation.ManagedOperation;
|
||||
|
@ -168,7 +168,10 @@ public class DoSFilter implements Filter
|
|||
private static final int USER_IP = 1;
|
||||
private static final int USER_UNKNOWN = 0;
|
||||
|
||||
private ServletContext _context;
|
||||
private final String _suspended = "DoSFilter@" + Integer.toHexString(hashCode()) + ".SUSPENDED";
|
||||
private final String _resumed = "DoSFilter@" + Integer.toHexString(hashCode()) + ".RESUMED";
|
||||
private final ConcurrentHashMap<String, RateTracker> _rateTrackers = new ConcurrentHashMap<>();
|
||||
private final List<String> _whitelist = new CopyOnWriteArrayList<>();
|
||||
private volatile long _delayMs;
|
||||
private volatile long _throttleMs;
|
||||
private volatile long _maxWaitMs;
|
||||
|
@ -181,34 +184,18 @@ public class DoSFilter implements Filter
|
|||
private Semaphore _passes;
|
||||
private volatile int _throttledRequests;
|
||||
private volatile int _maxRequestsPerSec;
|
||||
private Queue<Continuation>[] _queue;
|
||||
private ContinuationListener[] _listeners;
|
||||
private final ConcurrentHashMap<String, RateTracker> _rateTrackers = new ConcurrentHashMap<>();
|
||||
private final List<String> _whitelist = new CopyOnWriteArrayList<>();
|
||||
private Queue<AsyncContext>[] _queues;
|
||||
private AsyncListener[] _listeners;
|
||||
private Scheduler _scheduler;
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException
|
||||
{
|
||||
_context = filterConfig.getServletContext();
|
||||
|
||||
_queue = new Queue[getMaxPriority() + 1];
|
||||
_listeners = new ContinuationListener[getMaxPriority() + 1];
|
||||
for (int p = 0; p < _queue.length; p++)
|
||||
_queues = new Queue[getMaxPriority() + 1];
|
||||
_listeners = new AsyncListener[_queues.length];
|
||||
for (int p = 0; p < _queues.length; p++)
|
||||
{
|
||||
_queue[p] = new ConcurrentLinkedQueue<>();
|
||||
|
||||
final int priority = p;
|
||||
_listeners[p] = new ContinuationListener()
|
||||
{
|
||||
public void onComplete(Continuation continuation)
|
||||
{
|
||||
}
|
||||
|
||||
public void onTimeout(Continuation continuation)
|
||||
{
|
||||
_queue[priority].remove(continuation);
|
||||
}
|
||||
};
|
||||
_queues[p] = new ConcurrentLinkedQueue<>();
|
||||
_listeners[p] = new DoSAsyncListener(p);
|
||||
}
|
||||
|
||||
_rateTrackers.clear();
|
||||
|
@ -275,8 +262,9 @@ public class DoSFilter implements Filter
|
|||
|
||||
_scheduler = startScheduler();
|
||||
|
||||
if (_context != null && Boolean.parseBoolean(filterConfig.getInitParameter(MANAGED_ATTR_INIT_PARAM)))
|
||||
_context.setAttribute(filterConfig.getFilterName(), this);
|
||||
ServletContext context = filterConfig.getServletContext();
|
||||
if (context != null && Boolean.parseBoolean(filterConfig.getInitParameter(MANAGED_ATTR_INIT_PARAM)))
|
||||
context.setAttribute(filterConfig.getFilterName(), this);
|
||||
}
|
||||
|
||||
protected Scheduler startScheduler() throws ServletException
|
||||
|
@ -306,37 +294,40 @@ public class DoSFilter implements Filter
|
|||
return;
|
||||
}
|
||||
|
||||
// Look for the rate tracker for this request
|
||||
// Look for the rate tracker for this request.
|
||||
RateTracker tracker = (RateTracker)request.getAttribute(__TRACKER);
|
||||
|
||||
if (tracker == null)
|
||||
{
|
||||
// This is the first time we have seen this request.
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Filtering {}", request);
|
||||
|
||||
// get a rate tracker associated with this request, and record one hit
|
||||
// Get a rate tracker associated with this request, and record one hit.
|
||||
tracker = getRateTracker(request);
|
||||
|
||||
// Calculate the rate and check it is over the allowed limit
|
||||
final boolean overRateLimit = tracker.isRateExceeded(System.currentTimeMillis());
|
||||
|
||||
// pass it through if we are not currently over the rate limit
|
||||
// Pass it through if we are not currently over the rate limit.
|
||||
if (!overRateLimit)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Allowing {}", request);
|
||||
doFilterChain(filterChain, request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// We are over the limit.
|
||||
|
||||
// So either reject it, delay it or throttle it
|
||||
// So either reject it, delay it or throttle it.
|
||||
long delayMs = getDelayMs();
|
||||
boolean insertHeaders = isInsertHeaders();
|
||||
switch ((int)delayMs)
|
||||
{
|
||||
case -1:
|
||||
{
|
||||
// Reject this request
|
||||
LOG.warn("DOS ALERT: Request rejected ip=" + request.getRemoteAddr() + ",session=" + request.getRequestedSessionId() + ",user=" + request.getUserPrincipal());
|
||||
// Reject this request.
|
||||
LOG.warn("DOS ALERT: Request rejected ip={}, session={}, user={}", request.getRemoteAddr(), request.getRequestedSessionId(), request.getUserPrincipal());
|
||||
if (insertHeaders)
|
||||
response.addHeader("DoSFilter", "unavailable");
|
||||
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
|
@ -344,39 +335,41 @@ public class DoSFilter implements Filter
|
|||
}
|
||||
case 0:
|
||||
{
|
||||
// fall through to throttle code
|
||||
LOG.warn("DOS ALERT: Request throttled ip=" + request.getRemoteAddr() + ",session=" + request.getRequestedSessionId() + ",user=" + request.getUserPrincipal());
|
||||
// Fall through to throttle the request.
|
||||
LOG.warn("DOS ALERT: Request throttled ip={}, session={}, user={}", request.getRemoteAddr(), request.getRequestedSessionId(), request.getUserPrincipal());
|
||||
request.setAttribute(__TRACKER, tracker);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// insert a delay before throttling the request
|
||||
LOG.warn("DOS ALERT: Request delayed="+delayMs+"ms ip=" + request.getRemoteAddr() + ",session=" + request.getRequestedSessionId() + ",user=" + request.getUserPrincipal());
|
||||
// Insert a delay before throttling the request,
|
||||
// using the suspend+timeout mechanism of AsyncContext.
|
||||
LOG.warn("DOS ALERT: Request delayed={}ms, ip={}, session={}, user={}", delayMs, request.getRemoteAddr(), request.getRequestedSessionId(), request.getUserPrincipal());
|
||||
if (insertHeaders)
|
||||
response.addHeader("DoSFilter", "delayed");
|
||||
Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||
request.setAttribute(__TRACKER, tracker);
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
if (delayMs > 0)
|
||||
continuation.setTimeout(delayMs);
|
||||
continuation.suspend();
|
||||
asyncContext.setTimeout(delayMs);
|
||||
asyncContext.addListener(new DoSTimeoutAsyncListener());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Throttle the request
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Throttling {}", request);
|
||||
|
||||
// Throttle the request.
|
||||
boolean accepted = false;
|
||||
try
|
||||
{
|
||||
// check if we can afford to accept another request at this time
|
||||
// Check if we can afford to accept another request at this time.
|
||||
accepted = _passes.tryAcquire(getMaxWaitMs(), TimeUnit.MILLISECONDS);
|
||||
|
||||
if (!accepted)
|
||||
{
|
||||
// we were not accepted, so either we suspend to wait,or if we were woken up we insist or we fail
|
||||
final Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||
|
||||
// We were not accepted, so either we suspend to wait,
|
||||
// or if we were woken up we insist or we fail.
|
||||
Boolean throttled = (Boolean)request.getAttribute(__THROTTLED);
|
||||
long throttleMs = getThrottleMs();
|
||||
if (throttled != Boolean.TRUE && throttleMs > 0)
|
||||
|
@ -385,30 +378,39 @@ public class DoSFilter implements Filter
|
|||
request.setAttribute(__THROTTLED, Boolean.TRUE);
|
||||
if (isInsertHeaders())
|
||||
response.addHeader("DoSFilter", "throttled");
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
request.setAttribute(_suspended, Boolean.TRUE);
|
||||
if (throttleMs > 0)
|
||||
continuation.setTimeout(throttleMs);
|
||||
continuation.suspend();
|
||||
|
||||
continuation.addContinuationListener(_listeners[priority]);
|
||||
_queue[priority].add(continuation);
|
||||
asyncContext.setTimeout(throttleMs);
|
||||
asyncContext.addListener(_listeners[priority]);
|
||||
_queues[priority].add(asyncContext);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Throttled {}, {}ms", request, throttleMs);
|
||||
return;
|
||||
}
|
||||
// else were we resumed?
|
||||
else if (request.getAttribute("javax.servlet.resumed") == Boolean.TRUE)
|
||||
|
||||
Boolean resumed = (Boolean)request.getAttribute(_resumed);
|
||||
if (resumed == Boolean.TRUE)
|
||||
{
|
||||
// we were resumed and somebody stole our pass, so we wait for the next one.
|
||||
// We were resumed, we wait for the next pass.
|
||||
_passes.acquire();
|
||||
accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if we were accepted (either immediately or after throttle)
|
||||
// If we were accepted (either immediately or after throttle)...
|
||||
if (accepted)
|
||||
// call the chain
|
||||
{
|
||||
// ...call the chain.
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Allowing {}", request);
|
||||
doFilterChain(filterChain, request, response);
|
||||
}
|
||||
else
|
||||
{
|
||||
// fail the request
|
||||
// ...otherwise fail the request.
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Rejecting {}", request);
|
||||
if (isInsertHeaders())
|
||||
response.addHeader("DoSFilter", "unavailable");
|
||||
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
|
@ -416,21 +418,28 @@ public class DoSFilter implements Filter
|
|||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
_context.log("DoS", e);
|
||||
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (accepted)
|
||||
{
|
||||
// wake up the next highest priority request.
|
||||
for (int p = _queue.length; p-- > 0; )
|
||||
// Wake up the next highest priority request.
|
||||
for (int p = _queues.length - 1; p >= 0; --p)
|
||||
{
|
||||
Continuation continuation = _queue[p].poll();
|
||||
if (continuation != null && continuation.isSuspended())
|
||||
AsyncContext asyncContext = _queues[p].poll();
|
||||
if (asyncContext != null)
|
||||
{
|
||||
continuation.resume();
|
||||
break;
|
||||
ServletRequest candidate = asyncContext.getRequest();
|
||||
Boolean suspended = (Boolean)candidate.getAttribute(_suspended);
|
||||
if (suspended == Boolean.TRUE)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Resuming {}", request);
|
||||
candidate.setAttribute(_resumed, Boolean.TRUE);
|
||||
asyncContext.dispatch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_passes.release();
|
||||
|
@ -449,7 +458,6 @@ public class DoSFilter implements Filter
|
|||
closeConnection(request, response, thread);
|
||||
}
|
||||
};
|
||||
|
||||
Scheduler.Task task = _scheduler.schedule(requestTimeout, getMaxRequestMs(), TimeUnit.MILLISECONDS);
|
||||
try
|
||||
{
|
||||
|
@ -1056,10 +1064,10 @@ public class DoSFilter implements Filter
|
|||
{
|
||||
private static final long serialVersionUID = 3534663738034577872L;
|
||||
|
||||
transient protected final String _id;
|
||||
transient protected final int _type;
|
||||
transient protected final long[] _timestamps;
|
||||
transient protected int _next;
|
||||
protected transient final String _id;
|
||||
protected transient final int _type;
|
||||
protected transient final long[] _timestamps;
|
||||
protected transient int _next;
|
||||
|
||||
public RateTracker(String id, int type, int maxRequestsPerSecond)
|
||||
{
|
||||
|
@ -1115,7 +1123,8 @@ public class DoSFilter implements Filter
|
|||
//and ensure that we take ourselves out of the session so we are not saved
|
||||
_rateTrackers.remove(_id);
|
||||
se.getSession().removeAttribute(__TRACKER);
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Value removed: {}", getId());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Value removed: {}", getId());
|
||||
}
|
||||
|
||||
public void sessionDidActivate(HttpSessionEvent se)
|
||||
|
@ -1171,4 +1180,45 @@ public class DoSFilter implements Filter
|
|||
return "Fixed" + super.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private class DoSTimeoutAsyncListener implements AsyncListener
|
||||
{
|
||||
@Override
|
||||
public void onStartAsync(AsyncEvent event) throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(AsyncEvent event) throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeout(AsyncEvent event) throws IOException
|
||||
{
|
||||
event.getAsyncContext().dispatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(AsyncEvent event) throws IOException
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class DoSAsyncListener extends DoSTimeoutAsyncListener
|
||||
{
|
||||
private final int priority;
|
||||
|
||||
public DoSAsyncListener(int priority)
|
||||
{
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeout(AsyncEvent event) throws IOException
|
||||
{
|
||||
_queues[priority].remove(event.getAsyncContext());
|
||||
super.onTimeout(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -362,8 +362,10 @@ public class QoSFilter implements Filter
|
|||
public void onTimeout(AsyncEvent event) throws IOException
|
||||
{
|
||||
// Remove before it's redispatched, so it won't be
|
||||
// redispatched again in the finally block below.
|
||||
_queues[priority].remove(event.getAsyncContext());
|
||||
// redispatched again at the end of the filtering.
|
||||
AsyncContext asyncContext = event.getAsyncContext();
|
||||
_queues[priority].remove(asyncContext);
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,12 +18,8 @@
|
|||
|
||||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -34,6 +30,9 @@ import org.junit.Assert;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class DoSFilterTest extends AbstractDoSFilterTest
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(DoSFilterTest.class);
|
||||
|
@ -62,7 +61,7 @@ public class DoSFilterTest extends AbstractDoSFilterTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void isRateExceededTest() throws InterruptedException
|
||||
public void testRateIsRateExceeded() throws InterruptedException
|
||||
{
|
||||
DoSFilter doSFilter = new DoSFilter();
|
||||
|
||||
|
|
|
@ -3,3 +3,4 @@ org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
|||
#org.eclipse.jetty.servlets.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.servlets.GzipFilter.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.servlets.QoSFilter.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.servlets.DoSFilter.LEVEL=DEBUG
|
||||
|
|
|
@ -18,16 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.spdy.server.http;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -40,15 +30,15 @@ import java.util.concurrent.ExecutionException;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.AsyncEvent;
|
||||
import javax.servlet.AsyncListener;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.continuation.Continuation;
|
||||
import org.eclipse.jetty.continuation.ContinuationSupport;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.server.HttpChannel;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
@ -63,15 +53,23 @@ import org.eclipse.jetty.spdy.api.StringDataInfo;
|
|||
import org.eclipse.jetty.spdy.api.SynInfo;
|
||||
import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
|
||||
import org.eclipse.jetty.util.Fields;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.log.StdErrLog;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ServerHTTPSPDYTest.class);
|
||||
public static final String SUSPENDED_ATTRIBUTE = ServerHTTPSPDYTest.class.getName() + ".SUSPENDED";
|
||||
|
||||
public ServerHTTPSPDYTest(short version)
|
||||
{
|
||||
|
@ -1160,10 +1158,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
throws IOException, ServletException
|
||||
{
|
||||
request.setHandled(true);
|
||||
|
||||
final Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||
continuation.suspend();
|
||||
|
||||
final AsyncContext asyncContext = request.startAsync();
|
||||
new Thread()
|
||||
{
|
||||
@Override
|
||||
|
@ -1172,7 +1167,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
try
|
||||
{
|
||||
readRequestData(request, data.length);
|
||||
continuation.complete();
|
||||
asyncContext.complete();
|
||||
latch.countDown();
|
||||
}
|
||||
catch (IOException x)
|
||||
|
@ -1213,17 +1208,17 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
throws IOException, ServletException
|
||||
{
|
||||
request.setHandled(true);
|
||||
final Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||
if (continuation.isInitial())
|
||||
{
|
||||
continuation.setTimeout(1000);
|
||||
continuation.suspend();
|
||||
}
|
||||
else
|
||||
if (request.getAttribute(SUSPENDED_ATTRIBUTE) == Boolean.TRUE)
|
||||
{
|
||||
dispatchedAgainAfterExpire.countDown();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
asyncContext.setTimeout(1000);
|
||||
asyncContext.addListener(new AsyncListenerAdapter());
|
||||
request.setAttribute(SUSPENDED_ATTRIBUTE, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
}, 30000), null);
|
||||
|
||||
|
@ -1257,18 +1252,18 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
throws IOException, ServletException
|
||||
{
|
||||
request.setHandled(true);
|
||||
final Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||
if (continuation.isInitial())
|
||||
{
|
||||
readRequestData(request, data.length);
|
||||
continuation.setTimeout(1000);
|
||||
continuation.suspend();
|
||||
}
|
||||
else
|
||||
if (request.getAttribute(SUSPENDED_ATTRIBUTE) == Boolean.TRUE)
|
||||
{
|
||||
dispatchedAgainAfterExpire.countDown();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
readRequestData(request, data.length);
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
asyncContext.setTimeout(1000);
|
||||
asyncContext.addListener(new AsyncListenerAdapter());
|
||||
request.setAttribute(SUSPENDED_ATTRIBUTE, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
}, 30000), null);
|
||||
|
||||
|
@ -1312,10 +1307,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
throws IOException, ServletException
|
||||
{
|
||||
request.setHandled(true);
|
||||
|
||||
final Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||
continuation.suspend();
|
||||
|
||||
final AsyncContext asyncContext = request.startAsync();
|
||||
new Thread()
|
||||
{
|
||||
@Override
|
||||
|
@ -1328,7 +1320,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
int read = 0;
|
||||
while (read < 2 * data.length)
|
||||
read += input.read(buffer);
|
||||
continuation.complete();
|
||||
asyncContext.complete();
|
||||
latch.countDown();
|
||||
}
|
||||
catch (IOException x)
|
||||
|
@ -1371,17 +1363,20 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
throws IOException, ServletException
|
||||
{
|
||||
request.setHandled(true);
|
||||
|
||||
final Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||
|
||||
if (continuation.isInitial())
|
||||
if (request.getAttribute(SUSPENDED_ATTRIBUTE) == Boolean.TRUE)
|
||||
{
|
||||
OutputStream output = httpResponse.getOutputStream();
|
||||
output.write(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
final AsyncContext asyncContext = request.startAsync();
|
||||
request.setAttribute(SUSPENDED_ATTRIBUTE, Boolean.TRUE);
|
||||
InputStream input = request.getInputStream();
|
||||
byte[] buffer = new byte[256];
|
||||
int read = 0;
|
||||
while (read < data.length)
|
||||
read += input.read(buffer);
|
||||
continuation.suspend();
|
||||
new Thread()
|
||||
{
|
||||
@Override
|
||||
|
@ -1390,7 +1385,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
try
|
||||
{
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
continuation.resume();
|
||||
asyncContext.dispatch();
|
||||
latch.countDown();
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
|
@ -1400,11 +1395,6 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
}
|
||||
}.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputStream output = httpResponse.getOutputStream();
|
||||
output.write(data);
|
||||
}
|
||||
}
|
||||
}, 30000), null);
|
||||
|
||||
|
@ -1532,7 +1522,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
}, idleTimeout), null);
|
||||
|
||||
Fields headers = SPDYTestUtils.createHeaders("localhost", connector.getPort(), version, "GET", "/");
|
||||
Stream stream = session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, true, (byte)0),
|
||||
session.syn(new SynInfo(5, TimeUnit.SECONDS, headers, true, (byte)0),
|
||||
new StreamFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
|
@ -1609,4 +1599,27 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
|
|||
});
|
||||
}
|
||||
|
||||
private class AsyncListenerAdapter implements AsyncListener
|
||||
{
|
||||
@Override
|
||||
public void onStartAsync(AsyncEvent event) throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(AsyncEvent event) throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeout(AsyncEvent event) throws IOException
|
||||
{
|
||||
event.getAsyncContext().dispatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(AsyncEvent event) throws IOException
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -26,6 +26,7 @@
|
|||
<connection>scm:git:http://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git</connection>
|
||||
<developerConnection>scm:git:ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git</developerConnection>
|
||||
<url>http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree</url>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
<build>
|
||||
<defaultGoal>install</defaultGoal>
|
||||
|
@ -40,6 +41,7 @@
|
|||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
</configuration>
|
||||
|
|
Loading…
Reference in New Issue