Issue #113 channel persistance and completed getters
Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
parent
7ca6577ac6
commit
7dd3cfffe6
|
@ -34,8 +34,6 @@ 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;
|
||||
|
@ -48,9 +46,9 @@ import org.eclipse.jetty.http.HttpVersion;
|
|||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ChannelEndPoint;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.QuietException;
|
||||
import org.eclipse.jetty.io.RuntimeIOException;
|
||||
import org.eclipse.jetty.server.HttpChannelState.Action;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||
|
@ -74,6 +72,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
{
|
||||
private static final Logger LOG = Log.getLogger(HttpChannel.class);
|
||||
private final AtomicBoolean _committed = new AtomicBoolean();
|
||||
private final AtomicBoolean _responseCompleted = new AtomicBoolean();
|
||||
private final AtomicLong _requests = new AtomicLong();
|
||||
private final Connector _connector;
|
||||
private final Executor _executor;
|
||||
|
@ -246,6 +245,11 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
return _response;
|
||||
}
|
||||
|
||||
public Connection getConnection()
|
||||
{
|
||||
return _endPoint.getConnection();
|
||||
}
|
||||
|
||||
public EndPoint getEndPoint()
|
||||
{
|
||||
return _endPoint;
|
||||
|
@ -277,6 +281,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
public void recycle()
|
||||
{
|
||||
_committed.set(false);
|
||||
_responseCompleted.set(false);
|
||||
_request.recycle();
|
||||
_response.recycle();
|
||||
_committedMetaData=null;
|
||||
|
@ -662,11 +667,13 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
public String toString()
|
||||
{
|
||||
long timeStamp = _request.getTimeStamp();
|
||||
return String.format("%s@%x{r=%s,c=%b,a=%s,uri=%s,age=%d}",
|
||||
return String.format("%s@%x{r=%s,c=%b,c=%b/%b,a=%s,uri=%s,age=%d}",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_requests,
|
||||
_committed.get(),
|
||||
isRequestCompleted(),
|
||||
isResponseCompleted(),
|
||||
_state.getState(),
|
||||
_request.getHttpURI(),
|
||||
timeStamp == 0 ? 0 : System.currentTimeMillis() - timeStamp);
|
||||
|
@ -828,7 +835,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
|
||||
// wrap callback to process 100 responses
|
||||
final int status=info.getStatus();
|
||||
final Callback committed = (status<200&&status>=100)?new Commit100Callback(callback):new CommitCallback(callback, content, complete);
|
||||
final Callback committed = (status<200&&status>=100)?new Send100Callback(callback):new SendCallback(callback, content, true, complete);
|
||||
|
||||
notifyResponseBegin(_request);
|
||||
|
||||
|
@ -838,7 +845,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
else if (info==null)
|
||||
{
|
||||
// This is a normal write
|
||||
_transport.send(null,_request.isHead(), content, complete, new ContentCallback(callback, content, complete));
|
||||
_transport.send(null,_request.isHead(), content, complete, new SendCallback(callback, content, false, complete));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -878,6 +885,27 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
return _committed.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if the request lifecycle is completed
|
||||
*/
|
||||
public boolean isRequestCompleted()
|
||||
{
|
||||
return _state.isCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if the response is completely written.
|
||||
*/
|
||||
public boolean isResponseCompleted()
|
||||
{
|
||||
return _responseCompleted.get();
|
||||
}
|
||||
|
||||
public boolean isPersistent()
|
||||
{
|
||||
return _endPoint.isOpen();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Non-Blocking write, committing the response if needed.</p>
|
||||
* Called as last link in HttpOutput.Filter chain
|
||||
|
@ -1222,17 +1250,19 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
}
|
||||
}
|
||||
|
||||
private class CommitCallback extends Callback.Nested
|
||||
private class SendCallback extends Callback.Nested
|
||||
{
|
||||
private final ByteBuffer _content;
|
||||
private final int _length;
|
||||
private final boolean _commit;
|
||||
private final boolean _complete;
|
||||
|
||||
private CommitCallback(Callback callback, ByteBuffer content, boolean complete)
|
||||
private SendCallback(Callback callback, ByteBuffer content, boolean commit, boolean complete)
|
||||
{
|
||||
super(callback);
|
||||
_content = content == null ? BufferUtil.EMPTY_BUFFER : content.slice();
|
||||
_length = _content.remaining();
|
||||
_commit = commit;
|
||||
_complete = complete;
|
||||
}
|
||||
|
||||
|
@ -1241,11 +1271,15 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
{
|
||||
_written += _length;
|
||||
super.succeeded();
|
||||
notifyResponseCommit(_request);
|
||||
if (_content.hasRemaining())
|
||||
if (_commit)
|
||||
notifyResponseCommit(_request);
|
||||
if (_length>0)
|
||||
notifyResponseContent(_request, _content);
|
||||
if (_complete)
|
||||
{
|
||||
_responseCompleted.set(true);
|
||||
notifyResponseEnd(_request);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1281,11 +1315,11 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
}
|
||||
}
|
||||
|
||||
private class Commit100Callback extends CommitCallback
|
||||
private class Send100Callback extends SendCallback
|
||||
{
|
||||
private Commit100Callback(Callback callback)
|
||||
private Send100Callback(Callback callback)
|
||||
{
|
||||
super(callback, null, false);
|
||||
super(callback, null, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1297,30 +1331,4 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
super.failed(new IllegalStateException());
|
||||
}
|
||||
}
|
||||
|
||||
private class ContentCallback extends Callback.Nested
|
||||
{
|
||||
private final ByteBuffer _content;
|
||||
private final int _length;
|
||||
private final boolean _complete;
|
||||
|
||||
private ContentCallback(Callback callback, ByteBuffer content, boolean complete)
|
||||
{
|
||||
super(callback);
|
||||
_content = content == null ? BufferUtil.EMPTY_BUFFER : content.slice();
|
||||
_length = _content.remaining();
|
||||
_complete = complete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void succeeded()
|
||||
{
|
||||
_written += _length;
|
||||
super.succeeded();
|
||||
if (_content.hasRemaining())
|
||||
notifyResponseContent(_request, _content);
|
||||
if (_complete)
|
||||
notifyResponseEnd(_request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,9 +329,12 @@ public class RequestLogTest
|
|||
data.add(new Object[] { new ResponseSendErrorHandler(), "/sendError", "\"GET /sendError HTTP/1.0\" 599" });
|
||||
data.add(new Object[] { new ServletExceptionHandler(), "/sex", "\"GET /sex HTTP/1.0\" 500" });
|
||||
data.add(new Object[] { new IOExceptionHandler(), "/ioex", "\"GET /ioex HTTP/1.0\" 500" });
|
||||
data.add(new Object[] { new IOExceptionPartialHandler(), "/ioex", "\"GET /ioex HTTP/1.0\" 200" });
|
||||
data.add(new Object[] { new RuntimeExceptionHandler(), "/rtex", "\"GET /rtex HTTP/1.0\" 500" });
|
||||
data.add(new Object[] { new BadMessageHandler(), "/bad", "\"GET /bad HTTP/1.0\" 499" });
|
||||
data.add(new Object[] { new AbortHandler(), "/bad", "\"GET /bad HTTP/1.0\" 488" });
|
||||
data.add(new Object[] { new AbortPartialHandler(), "/bad", "\"GET /bad HTTP/1.0\" 200" });
|
||||
|
||||
|
||||
return data.stream().map(Arguments::of);
|
||||
}
|
||||
|
@ -623,6 +626,20 @@ public class RequestLogTest
|
|||
}
|
||||
}
|
||||
|
||||
private static class IOExceptionPartialHandler extends AbstractTestHandler
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
response.setContentType("text/plain");
|
||||
response.setContentLength(100);
|
||||
response.getOutputStream().println("You were expecting maybe a ");
|
||||
response.flushBuffer();
|
||||
throw new IOException("expected");
|
||||
}
|
||||
}
|
||||
|
||||
private static class RuntimeExceptionHandler extends AbstractTestHandler
|
||||
{
|
||||
@Override
|
||||
|
@ -652,6 +669,20 @@ public class RequestLogTest
|
|||
}
|
||||
}
|
||||
|
||||
private static class AbortPartialHandler extends AbstractTestHandler
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
response.setContentType("text/plain");
|
||||
response.setContentLength(100);
|
||||
response.getOutputStream().println("You were expecting maybe a ");
|
||||
response.flushBuffer();
|
||||
baseRequest.getHttpChannel().abort(new Throwable("bomb"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class OKErrorHandler extends ErrorHandler
|
||||
{
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue