Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Wilkins2015-08-13 20:05:50 -0400
committerGreg Wilkins2015-08-13 20:06:57 -0400
commitd780839bec4d4e9940fd14ca0e3a2bb4495d45e5 (patch)
tree5592f45656f0b8f13c2b379d03b60b8f9e7b18f8
parent173f6d8b3bbedf458e255102e1e69135daa5a518 (diff)
downloadorg.eclipse.jetty.project-d780839bec4d4e9940fd14ca0e3a2bb4495d45e5.tar.gz
org.eclipse.jetty.project-d780839bec4d4e9940fd14ca0e3a2bb4495d45e5.tar.xz
org.eclipse.jetty.project-d780839bec4d4e9940fd14ca0e3a2bb4495d45e5.zip
474634 - AsyncListener.onError() handling.
Added HttpConfiguration.maxErrorDispatches to detect error loops Fixed ManyWays... unit test to handle error dispatch.
-rw-r--r--jetty-server/src/main/config/etc/jetty.xml1
-rw-r--r--jetty-server/src/main/config/modules/server.mod3
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java24
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java21
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToAsyncCommitBadBehaviourTest.java8
-rw-r--r--pom.xml2
6 files changed, 57 insertions, 2 deletions
diff --git a/jetty-server/src/main/config/etc/jetty.xml b/jetty-server/src/main/config/etc/jetty.xml
index c55953f8f3..aa5dcd68f2 100644
--- a/jetty-server/src/main/config/etc/jetty.xml
+++ b/jetty-server/src/main/config/etc/jetty.xml
@@ -87,6 +87,7 @@
<Set name="sendDateHeader"><Property name="jetty.httpConfig.sendDateHeader" deprecated="jetty.send.date.header" default="false" /></Set>
<Set name="headerCacheSize"><Property name="jetty.httpConfig.headerCacheSize" default="512" /></Set>
<Set name="delayDispatchUntilContent"><Property name="jetty.httpConfig.delayDispatchUntilContent" deprecated="jetty.delayDispatchUntilContent" default="true"/></Set>
+ <Set name="maxErrorDispatches"><Property name=jetty.httpConfig.maxErrorDispatches"/></Set>
<!-- Uncomment to enable handling of X-Forwarded- style headers
<Call name="addCustomizer">
<Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg>
diff --git a/jetty-server/src/main/config/modules/server.mod b/jetty-server/src/main/config/modules/server.mod
index 6b5dbe95ba..6857cca5e4 100644
--- a/jetty-server/src/main/config/modules/server.mod
+++ b/jetty-server/src/main/config/modules/server.mod
@@ -61,6 +61,9 @@ etc/jetty.xml
## Whether, for requests with content, delay dispatch until some content has arrived
# jetty.httpConfig.delayDispatchUntilContent=true
+## Maximum number of error dispatches to prevent looping
+# jetty.httpConfig.maxErrorDispatches=10
+
### Server configuration
## Whether ctrl+c on the console gracefully stops the Jetty server
# jetty.server.stopAtShutdown=true
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
index 1e1772ee33..6117cb12ce 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
@@ -318,12 +318,34 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
case ERROR_DISPATCH:
{
+ Throwable ex = _state.getAsyncContextEvent().getThrowable();
+
+ // Check for error dispatch loops
+ Integer loop_detect = (Integer)_request.getAttribute("org.eclipse.jetty.server.ERROR_DISPATCH");
+ if (loop_detect==null)
+ loop_detect=new Integer(1);
+ else
+ loop_detect=loop_detect+1;
+ _request.setAttribute("org.eclipse.jetty.server.ERROR_DISPATCH",loop_detect);
+ if (loop_detect > getHttpConfiguration().getMaxErrorDispatches())
+ {
+ LOG.warn("ERROR_DISPATCH loop detected on {} {}",_request,ex);
+ try
+ {
+ _response.sendError(HttpStatus.INTERNAL_SERVER_ERROR_500);
+ }
+ finally
+ {
+ _state.errorComplete();
+ }
+ break loop;
+ }
+
_request.setHandled(false);
_response.resetBuffer();
_response.getHttpOutput().reopen();
_request.setDispatcherType(DispatcherType.ERROR);
- Throwable ex = _state.getAsyncContextEvent().getThrowable();
String reason=null;
if (ex == null || ex instanceof TimeoutException)
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
index a9ec6f205a..1048e40697 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
@@ -63,6 +63,7 @@ public class HttpConfiguration
private boolean _sendDateHeader = true;
private boolean _delayDispatchUntilContent = true;
private boolean _persistentConnectionsEnabled = true;
+ private int _maxErrorDispatches = 10;
/* ------------------------------------------------------------ */
/**
@@ -118,6 +119,7 @@ public class HttpConfiguration
_sendXPoweredBy=config._sendXPoweredBy;
_delayDispatchUntilContent=config._delayDispatchUntilContent;
_persistentConnectionsEnabled=config._persistentConnectionsEnabled;
+ _maxErrorDispatches=config._maxErrorDispatches;
}
/* ------------------------------------------------------------ */
@@ -458,4 +460,23 @@ public class HttpConfiguration
{
return Boolean.TRUE.equals(_formEncodedMethods.get(method));
}
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return The maximum error dispatches for a request to prevent looping on an error
+ */
+ @ManagedAttribute("The maximum ERROR dispatches for a request for loop prevention (default 10)")
+ public int getMaxErrorDispatches()
+ {
+ return _maxErrorDispatches;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param max The maximum error dispatches for a request to prevent looping on an error
+ */
+ public void setMaxErrorDispatches(int max)
+ {
+ _maxErrorDispatches=max;
+ }
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToAsyncCommitBadBehaviourTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToAsyncCommitBadBehaviourTest.java
index 3526827b13..f03282beaf 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToAsyncCommitBadBehaviourTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToAsyncCommitBadBehaviourTest.java
@@ -30,6 +30,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -86,6 +87,13 @@ public class HttpManyWaysToAsyncCommitBadBehaviourTest extends AbstractHttpTest
public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
final CyclicBarrier resumeBarrier = new CyclicBarrier(1);
+
+ if (baseRequest.getDispatcherType()==DispatcherType.ERROR)
+ {
+ response.sendError(500);
+ return;
+ }
+
if (request.getAttribute(CONTEXT_ATTRIBUTE) == null)
{
final AsyncContext asyncContext = baseRequest.startAsync();
diff --git a/pom.xml b/pom.xml
index cc45ee37ee..a13697fc76 100644
--- a/pom.xml
+++ b/pom.xml
@@ -659,7 +659,7 @@
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
- <version>3.0</version>
+ <version>3.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>

Back to the top