440020 Abort bad proxy responses with sendError(-1)

This commit is contained in:
Greg Wilkins 2014-07-23 16:31:19 +10:00
parent 564ffca5dc
commit e199b671bb
5 changed files with 32 additions and 26 deletions

View File

@ -32,6 +32,7 @@ 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;
@ -51,6 +52,7 @@ 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;
@ -558,7 +560,15 @@ public class ProxyServlet extends HttpServlet
_log.debug(getRequestId(request) + " proxying failed", failure);
if (response.isCommitted())
{
request.setAttribute("org.eclipse.jetty.server.Response.failure", failure);
// Use Jetty specific behavior to close connection
try
{
response.sendError(-1);
}
catch (IOException e)
{
getServletContext().log("close failed", e);
}
AsyncContext asyncContext = request.getAsyncContext();
asyncContext.complete();
}

View File

@ -402,21 +402,8 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
}
else
{
// There is no way in the Servlet API to directly close a connection,
// so we rely on applications to pass this attribute to signal they
// want to hard close the connection, without even closing the output.
Object failure = _request.getAttribute("org.eclipse.jetty.server.Response.failure");
if (failure != null)
{
if (LOG.isDebugEnabled())
LOG.debug("Explicit response failure", failure);
failed();
}
else
{
// Complete generating the response
_response.closeOutput();
}
// Complete generating the response
_response.closeOutput();
}
}
catch(EofException|ClosedChannelException e)
@ -812,10 +799,11 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
/**
* If a write or similar to this channel fails this method should be called. The standard implementation
* of {@link #failed()} is a noop. But the different implementations of HttpChannel might want to take actions.
* is to call {@link HttpTransport#abort()}
*/
public void failed()
public void abort()
{
_transport.abort();
}
private class CommitCallback implements Callback

View File

@ -537,10 +537,10 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
}
@Override
public void failed()
public void abort()
{
super.abort();
_generator.setPersistent(false);
getEndPoint().shutdownOutput();
}
@Override

View File

@ -157,7 +157,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
catch(IOException e)
{
LOG.debug(e);
_channel.failed();
_channel.abort();
}
releaseBuffer();
return;
@ -192,7 +192,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
catch(IOException e)
{
LOG.debug(e);
_channel.failed();
_channel.abort();
}
releaseBuffer();
return;

View File

@ -541,10 +541,7 @@ public class Response implements HttpServletResponse
@Override
public void sendError(int sc) throws IOException
{
if (sc == 102)
sendProcessing();
else
sendError(sc, null);
sendError(sc, null);
}
@Override
@ -553,6 +550,17 @@ public class Response implements HttpServletResponse
if (isIncluding())
return;
switch(code)
{
case -1:
_channel.abort();
return;
case 102:
sendProcessing();
return;
default:
}
if (isCommitted())
LOG.warn("Committed before "+code+" "+message);