Pass BadMessageException from parser to HttpReceiverOVerHTTP

This change has already mostly been made in 9.4, so essentially this is a back port.  However the
primary signature of HttpParser.Handler for badMessage has not been changed and a default method
used to handle the cause. This avoids breaking any usages of the interface.

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2018-10-04 13:30:11 +10:00
parent 863a19bccf
commit 9f7f0bdc5f
4 changed files with 28 additions and 8 deletions

View File

@ -26,7 +26,12 @@ public class HttpResponseException extends RuntimeException
public HttpResponseException(String message, Response response)
{
super(message);
this(message, response, null);
}
public HttpResponseException(String message, Response response, Throwable cause)
{
super(message, cause);
this.response = response;
}

View File

@ -302,13 +302,19 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
@Override
public void badMessage(int status, String reason)
{
badMessage(status, reason, null);
}
@Override
public void badMessage(int status, String reason, Throwable cause)
{
HttpExchange exchange = getHttpExchange();
if (exchange != null)
{
HttpResponse response = exchange.getResponse();
response.status(status).reason(reason);
failAndClose(new HttpResponseException("HTTP protocol violation: bad response on " + getHttpConnection(), response));
failAndClose(new HttpResponseException("HTTP protocol violation: bad response on " + getHttpConnection(), response, cause));
}
}

View File

@ -32,6 +32,7 @@ import org.eclipse.jetty.client.HttpResponseException;
import org.eclipse.jetty.client.Origin;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpVersion;
@ -204,6 +205,8 @@ public class HttpReceiverOverHTTPTest
catch (ExecutionException e)
{
Assert.assertTrue(e.getCause() instanceof HttpResponseException);
Assert.assertTrue(e.getCause().getCause() instanceof BadMessageException);
Assert.assertTrue(e.getCause().getCause().getCause() instanceof NumberFormatException);
}
}

View File

@ -996,7 +996,7 @@ public class HttpParser
catch(NumberFormatException e)
{
LOG.ignore(e);
throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Invalid Content-Length Value");
throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Invalid Content-Length Value",e);
}
}
@ -1453,7 +1453,7 @@ public class HttpParser
else
LOG.warn("bad HTTP parsed: "+e._code+(e.getReason()!=null?" "+e.getReason():"")+" for "+_handler);
setState(State.CLOSE);
_handler.badMessage(e.getCode(), e.getReason());
_handler.badMessage(e.getCode(), e.getReason(), e);
}
catch(NumberFormatException|IllegalStateException e)
{
@ -1461,19 +1461,19 @@ public class HttpParser
LOG.warn("parse exception: {} in {} for {}",e.toString(),_state,_handler);
if (DEBUG)
LOG.debug(e);
badMessage();
badMessage(e);
}
catch(Exception|Error e)
{
BufferUtil.clear(buffer);
LOG.warn("parse exception: "+e.toString()+" for "+_handler,e);
badMessage();
badMessage(e);
}
return false;
}
protected void badMessage()
protected void badMessage(Throwable cause)
{
if (_headerComplete)
{
@ -1482,7 +1482,7 @@ public class HttpParser
else if (_state!=State.CLOSED)
{
setState(State.CLOSE);
_handler.badMessage(400,_requestHandler!=null?"Bad Request":"Bad Response");
_handler.badMessage(400,_requestHandler!=null?"Bad Request":"Bad Response", cause);
}
}
@ -1803,6 +1803,12 @@ public class HttpParser
*/
public void badMessage(int status, String reason);
/* ------------------------------------------------------------ */
public default void badMessage(int status, String reason, Throwable cause)
{
badMessage(status, reason);
}
/* ------------------------------------------------------------ */
/** @return the size in bytes of the per parser header cache
*/