474634 - AsyncListener.onError() handling.
Added HttpConfiguration.maxErrorDispatches to detect error loops Fixed ManyWays... unit test to handle error dispatch.
This commit is contained in:
parent
173f6d8b3b
commit
d780839bec
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue