* Issue #2787 Unwrap ServletException * Do not unwrap UnavailableException * unwrap to specific targets * fixes from review * fixes after merge Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
parent
e5f0531db0
commit
a315d5464f
|
@ -34,6 +34,8 @@ import java.util.function.Supplier;
|
|||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.UnavailableException;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
|
@ -552,19 +554,19 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
*/
|
||||
protected void handleException(Throwable failure)
|
||||
{
|
||||
// Unwrap wrapping Jetty exceptions.
|
||||
if (failure instanceof RuntimeIOException)
|
||||
failure = failure.getCause();
|
||||
// Unwrap wrapping Jetty and Servlet exceptions.
|
||||
Throwable quiet = unwrap(failure, QuietException.class);
|
||||
Throwable no_stack = unwrap(failure, BadMessageException.class, IOException.class, TimeoutException.class);
|
||||
|
||||
if (failure instanceof QuietException || !getServer().isRunning())
|
||||
if (quiet!=null || !getServer().isRunning())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(_request.getRequestURI(), failure);
|
||||
}
|
||||
else if (failure instanceof BadMessageException | failure instanceof IOException | failure instanceof TimeoutException)
|
||||
else if (no_stack!=null)
|
||||
{
|
||||
// No stack trace unless there is debug turned on
|
||||
LOG.warn("{} {}",_request.getRequestURI(), failure.toString());
|
||||
LOG.warn("{} {}",_request.getRequestURI(), no_stack.toString());
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(_request.getRequestURI(), failure);
|
||||
}
|
||||
|
@ -587,23 +589,6 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
}
|
||||
}
|
||||
|
||||
private void minimalErrorResponse(Throwable failure)
|
||||
{
|
||||
try
|
||||
{
|
||||
Integer code=(Integer)_request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
|
||||
_response.reset(true);
|
||||
_response.setStatus(code == null ? 500 : code);
|
||||
_response.flushBuffer();
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
if (x != failure)
|
||||
failure.addSuppressed(x);
|
||||
abort(failure);
|
||||
}
|
||||
}
|
||||
|
||||
/** Unwrap failure causes to find target class
|
||||
* @param failure The throwable to have its causes unwrapped
|
||||
* @param targets Exception classes that we should not unwrap
|
||||
|
@ -620,6 +605,33 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void minimalErrorResponse(Throwable failure)
|
||||
{
|
||||
try
|
||||
{
|
||||
int code = 500;
|
||||
Integer status=(Integer)_request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
|
||||
if (status!=null)
|
||||
code = status.intValue();
|
||||
else
|
||||
{
|
||||
Throwable cause = unwrap(failure,BadMessageException.class);
|
||||
if (cause instanceof BadMessageException)
|
||||
code = ((BadMessageException)cause).getCode();
|
||||
}
|
||||
|
||||
_response.reset(true);
|
||||
_response.setStatus(code);
|
||||
_response.flushBuffer();
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
if (x != failure)
|
||||
failure.addSuppressed(x);
|
||||
abort(failure);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isExpecting100Continue()
|
||||
{
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static javax.servlet.RequestDispatcher.ERROR_EXCEPTION;
|
||||
import static javax.servlet.RequestDispatcher.ERROR_EXCEPTION_TYPE;
|
||||
import static javax.servlet.RequestDispatcher.ERROR_MESSAGE;
|
||||
import static javax.servlet.RequestDispatcher.ERROR_STATUS_CODE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -38,10 +43,6 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
import org.eclipse.jetty.util.thread.Locker;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
import static javax.servlet.RequestDispatcher.ERROR_EXCEPTION;
|
||||
import static javax.servlet.RequestDispatcher.ERROR_MESSAGE;
|
||||
import static javax.servlet.RequestDispatcher.ERROR_STATUS_CODE;
|
||||
|
||||
/**
|
||||
* Implementation of AsyncContext interface that holds the state of request-response cycle.
|
||||
*/
|
||||
|
@ -713,7 +714,7 @@ public class HttpChannelState
|
|||
cancelTimeout();
|
||||
}
|
||||
|
||||
protected void onError(Throwable failure)
|
||||
protected void onError(Throwable th)
|
||||
{
|
||||
final List<AsyncListener> listeners;
|
||||
final AsyncContextEvent event;
|
||||
|
@ -721,15 +722,16 @@ public class HttpChannelState
|
|||
|
||||
int code=HttpStatus.INTERNAL_SERVER_ERROR_500;
|
||||
String reason=null;
|
||||
if (failure instanceof BadMessageException)
|
||||
Throwable cause = _channel.unwrap(th,BadMessageException.class,UnavailableException.class);
|
||||
if (cause instanceof BadMessageException)
|
||||
{
|
||||
BadMessageException bme = (BadMessageException)failure;
|
||||
BadMessageException bme = (BadMessageException)cause;
|
||||
code = bme.getCode();
|
||||
reason = bme.getReason();
|
||||
}
|
||||
else if (failure instanceof UnavailableException)
|
||||
else if (cause instanceof UnavailableException)
|
||||
{
|
||||
if (((UnavailableException)failure).isPermanent())
|
||||
if (((UnavailableException)cause).isPermanent())
|
||||
code = HttpStatus.NOT_FOUND_404;
|
||||
else
|
||||
code = HttpStatus.SERVICE_UNAVAILABLE_503;
|
||||
|
@ -738,15 +740,15 @@ public class HttpChannelState
|
|||
try(Locker.Lock lock= _locker.lock())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("onError {} {}",toStringLocked(),failure);
|
||||
LOG.debug("onError {} {}",toStringLocked(),th);
|
||||
|
||||
// Set error on request.
|
||||
if(_event!=null)
|
||||
{
|
||||
_event.addThrowable(failure);
|
||||
_event.addThrowable(th);
|
||||
_event.getSuppliedRequest().setAttribute(ERROR_STATUS_CODE,code);
|
||||
_event.getSuppliedRequest().setAttribute(ERROR_EXCEPTION,failure);
|
||||
_event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,failure==null?null:failure.getClass());
|
||||
_event.getSuppliedRequest().setAttribute(ERROR_EXCEPTION,th);
|
||||
_event.getSuppliedRequest().setAttribute(ERROR_EXCEPTION_TYPE,th==null?null:th.getClass());
|
||||
_event.getSuppliedRequest().setAttribute(ERROR_MESSAGE,reason);
|
||||
}
|
||||
else
|
||||
|
@ -755,8 +757,8 @@ public class HttpChannelState
|
|||
if (error!=null)
|
||||
throw new IllegalStateException("Error already set",error);
|
||||
baseRequest.setAttribute(ERROR_STATUS_CODE,code);
|
||||
baseRequest.setAttribute(ERROR_EXCEPTION,failure);
|
||||
baseRequest.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,failure==null?null:failure.getClass());
|
||||
baseRequest.setAttribute(ERROR_EXCEPTION,th);
|
||||
baseRequest.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,th==null?null:th.getClass());
|
||||
baseRequest.setAttribute(ERROR_MESSAGE,reason);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ import static org.junit.Assert.assertThat;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
|
@ -124,10 +126,25 @@ public class ErrorHandlerTest
|
|||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
|
||||
if (baseRequest.getDispatcherType()==DispatcherType.ERROR)
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
response.sendError(((Integer)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE)).intValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if(target.startsWith("/charencoding/"))
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.sendError(404);
|
||||
return;
|
||||
}
|
||||
|
||||
if(target.startsWith("/badmessage/"))
|
||||
{
|
||||
throw new ServletException(new BadMessageException(Integer.valueOf(target.substring(12))));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -328,4 +345,16 @@ public class ErrorHandlerTest
|
|||
assertThat("Response Content-Type", contentType, is(notNullValue()));
|
||||
assertThat("Response Content-Type value", contentType.getValue(), not(containsString("null")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadMessage() throws Exception
|
||||
{
|
||||
String rawResponse = connector.getResponse(
|
||||
"GET /badmessage/444 HTTP/1.1\r\n"+
|
||||
"Host: Localhost\r\n"+
|
||||
"\r\n");
|
||||
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
|
||||
|
||||
assertThat("Response status code", response.getStatus(), is(444));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue