Merge remote-tracking branch 'origin/master' into jetty-9.1
Conflicts: jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
This commit is contained in:
commit
852be79a3c
|
@ -26,8 +26,10 @@ import static org.junit.Assert.fail;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.AsynchronousServerSocketChannel;
|
import java.nio.channels.AsynchronousServerSocketChannel;
|
||||||
|
@ -389,42 +391,40 @@ public class IOTest
|
||||||
@Test
|
@Test
|
||||||
public void testReset() throws Exception
|
public void testReset() throws Exception
|
||||||
{
|
{
|
||||||
ServerSocket connector;
|
try (ServerSocket connector = new ServerSocket(0);
|
||||||
Socket client;
|
Socket client = new Socket("127.0.0.1", connector.getLocalPort());
|
||||||
Socket server;
|
Socket server = connector.accept();)
|
||||||
|
{
|
||||||
|
client.setTcpNoDelay(true);
|
||||||
|
client.setSoLinger(true, 0);
|
||||||
|
server.setTcpNoDelay(true);
|
||||||
|
server.setSoLinger(true, 0);
|
||||||
|
|
||||||
connector = new ServerSocket(0);
|
client.getOutputStream().write(1);
|
||||||
client = new Socket("127.0.0.1", connector.getLocalPort());
|
assertEquals(1, server.getInputStream().read());
|
||||||
server = connector.accept();
|
server.getOutputStream().write(1);
|
||||||
client.setTcpNoDelay(true);
|
assertEquals(1, client.getInputStream().read());
|
||||||
client.setSoLinger(true, 0);
|
|
||||||
server.setTcpNoDelay(true);
|
|
||||||
server.setSoLinger(true, 0);
|
|
||||||
|
|
||||||
client.getOutputStream().write(1);
|
// Server generator shutdowns output after non persistent sending response.
|
||||||
assertEquals(1, server.getInputStream().read());
|
server.shutdownOutput();
|
||||||
server.getOutputStream().write(1);
|
|
||||||
assertEquals(1, client.getInputStream().read());
|
|
||||||
|
|
||||||
// Server generator shutdowns output after non persistent sending response.
|
// client endpoint reads EOF and shutdown input as result
|
||||||
server.shutdownOutput();
|
assertEquals(-1, client.getInputStream().read());
|
||||||
|
client.shutdownInput();
|
||||||
|
|
||||||
// client endpoint reads EOF and shutdown input as result
|
// client connection see's EOF and shutsdown output as no more requests to be sent.
|
||||||
assertEquals(-1, client.getInputStream().read());
|
client.shutdownOutput();
|
||||||
client.shutdownInput();
|
|
||||||
|
|
||||||
// client connection see's EOF and shutsdown output as no more requests to be sent.
|
// Since input already shutdown, client also closes socket.
|
||||||
client.shutdownOutput();
|
client.close();
|
||||||
|
|
||||||
// Since input already shutdown, client also closes socket.
|
// Server reads the EOF from client oshut and shut's down it's input
|
||||||
client.close();
|
assertEquals(-1, server.getInputStream().read());
|
||||||
|
server.shutdownInput();
|
||||||
|
|
||||||
// Server reads the EOF from client oshut and shut's down it's input
|
// Since output was already shutdown, server closes
|
||||||
assertEquals(-1, server.getInputStream().read());
|
server.close();
|
||||||
server.shutdownInput();
|
}
|
||||||
|
|
||||||
// Since output was already shutdown, server closes
|
|
||||||
server.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -432,10 +432,12 @@ public class IOTest
|
||||||
{
|
{
|
||||||
AsynchronousServerSocketChannel connector = AsynchronousServerSocketChannel.open();
|
AsynchronousServerSocketChannel connector = AsynchronousServerSocketChannel.open();
|
||||||
connector.bind(null);
|
connector.bind(null);
|
||||||
|
InetSocketAddress addr=(InetSocketAddress)connector.getLocalAddress();
|
||||||
Future<AsynchronousSocketChannel> acceptor = connector.accept();
|
Future<AsynchronousSocketChannel> acceptor = connector.accept();
|
||||||
|
|
||||||
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
|
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
|
||||||
client.connect(connector.getLocalAddress()).get(5, TimeUnit.SECONDS);
|
|
||||||
|
client.connect(new InetSocketAddress("127.0.0.1",addr.getPort())).get(5, TimeUnit.SECONDS);
|
||||||
|
|
||||||
AsynchronousSocketChannel server = acceptor.get(5, TimeUnit.SECONDS);
|
AsynchronousSocketChannel server = acceptor.get(5, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
|
|
@ -413,9 +413,12 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,x);
|
||||||
|
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,x.getClass());
|
||||||
if (_state.isSuspended())
|
if (_state.isSuspended())
|
||||||
{
|
{
|
||||||
HttpFields fields = new HttpFields();
|
HttpFields fields = new HttpFields();
|
||||||
|
fields.add(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
|
||||||
ResponseInfo info = new ResponseInfo(_request.getHttpVersion(), fields, 0, HttpStatus.INTERNAL_SERVER_ERROR_500, null, _request.isHead());
|
ResponseInfo info = new ResponseInfo(_request.getHttpVersion(), fields, 0, HttpStatus.INTERNAL_SERVER_ERROR_500, null, _request.isHead());
|
||||||
boolean committed = sendResponse(info, null, true);
|
boolean committed = sendResponse(info, null, true);
|
||||||
if (!committed)
|
if (!committed)
|
||||||
|
@ -429,8 +432,7 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,x);
|
_response.setHeader(HttpHeader.CONNECTION.asString(),HttpHeaderValue.CLOSE.asString());
|
||||||
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,x.getClass());
|
|
||||||
_response.sendError(500, x.getMessage());
|
_response.sendError(500, x.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -461,7 +461,7 @@ public class HttpConnectionTest
|
||||||
|
|
||||||
offset=0;
|
offset=0;
|
||||||
requests=
|
requests=
|
||||||
"GET /R1?read=1&error=599 HTTP/1.1\n"+
|
"GET /R1?read=1&error=499 HTTP/1.1\n"+
|
||||||
"Host: localhost\n"+
|
"Host: localhost\n"+
|
||||||
"Transfer-Encoding: chunked\n"+
|
"Transfer-Encoding: chunked\n"+
|
||||||
"Content-Type: text/plain; charset=utf-8\n"+
|
"Content-Type: text/plain; charset=utf-8\n"+
|
||||||
|
@ -481,7 +481,7 @@ public class HttpConnectionTest
|
||||||
|
|
||||||
response=connector.getResponses(requests);
|
response=connector.getResponses(requests);
|
||||||
|
|
||||||
offset = checkContains(response,offset,"HTTP/1.1 599");
|
offset = checkContains(response,offset,"HTTP/1.1 499");
|
||||||
offset = checkContains(response,offset,"HTTP/1.1 200");
|
offset = checkContains(response,offset,"HTTP/1.1 200");
|
||||||
offset = checkContains(response,offset,"/R2");
|
offset = checkContains(response,offset,"/R2");
|
||||||
offset = checkContains(response,offset,"encoding=UTF-8");
|
offset = checkContains(response,offset,"encoding=UTF-8");
|
||||||
|
|
|
@ -51,6 +51,8 @@ import javax.servlet.http.HttpServlet;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
|
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||||
import org.eclipse.jetty.http.PathMap;
|
import org.eclipse.jetty.http.PathMap;
|
||||||
import org.eclipse.jetty.io.EofException;
|
import org.eclipse.jetty.io.EofException;
|
||||||
import org.eclipse.jetty.io.RuntimeIOException;
|
import org.eclipse.jetty.io.RuntimeIOException;
|
||||||
|
@ -499,7 +501,7 @@ public class ServletHandler extends ScopedHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug("chain={}",chain);
|
LOG.debug("chain={}",chain);
|
||||||
|
Throwable th=null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (servlet_holder==null)
|
if (servlet_holder==null)
|
||||||
|
@ -547,7 +549,7 @@ public class ServletHandler extends ScopedHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// unwrap cause
|
// unwrap cause
|
||||||
Throwable th=e;
|
th=e;
|
||||||
if (th instanceof ServletException)
|
if (th instanceof ServletException)
|
||||||
{
|
{
|
||||||
if (th instanceof QuietServletException)
|
if (th instanceof QuietServletException)
|
||||||
|
@ -573,6 +575,7 @@ public class ServletHandler extends ScopedHandler
|
||||||
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,th);
|
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,th);
|
||||||
if (!response.isCommitted())
|
if (!response.isCommitted())
|
||||||
{
|
{
|
||||||
|
baseRequest.getResponse().getHttpFields().put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
|
||||||
if (th instanceof UnavailableException)
|
if (th instanceof UnavailableException)
|
||||||
{
|
{
|
||||||
UnavailableException ue = (UnavailableException)th;
|
UnavailableException ue = (UnavailableException)th;
|
||||||
|
@ -586,33 +589,34 @@ public class ServletHandler extends ScopedHandler
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LOG.debug("Response already committed",th);
|
LOG.debug("Response already committed",th);
|
||||||
|
|
||||||
// Complete async requests
|
|
||||||
if (request.isAsyncStarted())
|
|
||||||
request.getAsyncContext().complete();
|
|
||||||
}
|
}
|
||||||
catch(Error e)
|
catch(Error e)
|
||||||
{
|
{
|
||||||
if ("ContinuationThrowable".equals(e.getClass().getSimpleName()))
|
if ("ContinuationThrowable".equals(e.getClass().getSimpleName()))
|
||||||
throw e;
|
throw e;
|
||||||
|
th=e;
|
||||||
if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
|
if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
|
||||||
throw e;
|
throw e;
|
||||||
LOG.warn("Error for "+request.getRequestURI(),e);
|
LOG.warn("Error for "+request.getRequestURI(),e);
|
||||||
if(LOG.isDebugEnabled())LOG.debug(request.toString());
|
if(LOG.isDebugEnabled())
|
||||||
|
LOG.debug(request.toString());
|
||||||
|
|
||||||
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,e.getClass());
|
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,e.getClass());
|
||||||
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,e);
|
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,e);
|
||||||
if (!response.isCommitted())
|
if (!response.isCommitted())
|
||||||
|
{
|
||||||
|
baseRequest.getResponse().getHttpFields().put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
|
||||||
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
LOG.debug("Response already committed for handling ",e);
|
LOG.debug("Response already committed for handling ",e);
|
||||||
|
|
||||||
// Complete async requests
|
|
||||||
if (request.isAsyncStarted())
|
|
||||||
request.getAsyncContext().complete();
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
// Complete async errored requests
|
||||||
|
if (th!=null && request.isAsyncStarted())
|
||||||
|
request.getAsyncContext().complete();
|
||||||
|
|
||||||
if (servlet_holder!=null)
|
if (servlet_holder!=null)
|
||||||
baseRequest.setHandled(true);
|
baseRequest.setHandled(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,9 +239,8 @@ public abstract class ContinuationBase
|
||||||
|
|
||||||
int port=_port;
|
int port=_port;
|
||||||
String response=null;
|
String response=null;
|
||||||
try
|
try (Socket socket = new Socket("localhost",port);)
|
||||||
{
|
{
|
||||||
Socket socket = new Socket("localhost",port);
|
|
||||||
socket.setSoTimeout(10000);
|
socket.setSoTimeout(10000);
|
||||||
socket.getOutputStream().write(request.getBytes("UTF-8"));
|
socket.getOutputStream().write(request.getBytes("UTF-8"));
|
||||||
socket.getOutputStream().flush();
|
socket.getOutputStream().flush();
|
||||||
|
@ -269,6 +268,7 @@ public abstract class ContinuationBase
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
@Override
|
||||||
protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
|
protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
|
||||||
{
|
{
|
||||||
final Continuation continuation = ContinuationSupport.getContinuation(request);
|
final Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||||
|
@ -306,7 +306,7 @@ public abstract class ContinuationBase
|
||||||
|
|
||||||
if (continuation.isInitial())
|
if (continuation.isInitial())
|
||||||
{
|
{
|
||||||
((HttpServletResponse)response).addHeader("history","initial");
|
response.addHeader("history","initial");
|
||||||
if (read_before>0)
|
if (read_before>0)
|
||||||
{
|
{
|
||||||
byte[] buf=new byte[read_before];
|
byte[] buf=new byte[read_before];
|
||||||
|
@ -325,7 +325,7 @@ public abstract class ContinuationBase
|
||||||
if (suspend_for>0)
|
if (suspend_for>0)
|
||||||
continuation.setTimeout(suspend_for);
|
continuation.setTimeout(suspend_for);
|
||||||
continuation.addContinuationListener(__listener);
|
continuation.addContinuationListener(__listener);
|
||||||
((HttpServletResponse)response).addHeader("history","suspend");
|
response.addHeader("history","suspend");
|
||||||
continuation.suspend(response);
|
continuation.suspend(response);
|
||||||
|
|
||||||
if (complete_after>0)
|
if (complete_after>0)
|
||||||
|
@ -404,7 +404,7 @@ public abstract class ContinuationBase
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
((HttpServletResponse)response).addHeader("history","!initial");
|
response.addHeader("history","!initial");
|
||||||
if (suspend2_for>=0 && request.getAttribute("2nd")==null)
|
if (suspend2_for>=0 && request.getAttribute("2nd")==null)
|
||||||
{
|
{
|
||||||
request.setAttribute("2nd","cycle");
|
request.setAttribute("2nd","cycle");
|
||||||
|
@ -412,7 +412,7 @@ public abstract class ContinuationBase
|
||||||
if (suspend2_for>0)
|
if (suspend2_for>0)
|
||||||
continuation.setTimeout(suspend2_for);
|
continuation.setTimeout(suspend2_for);
|
||||||
// continuation.addContinuationListener(__listener);
|
// continuation.addContinuationListener(__listener);
|
||||||
((HttpServletResponse)response).addHeader("history","suspend");
|
response.addHeader("history","suspend");
|
||||||
continuation.suspend(response);
|
continuation.suspend(response);
|
||||||
|
|
||||||
if (complete2_after>0)
|
if (complete2_after>0)
|
||||||
|
@ -452,7 +452,7 @@ public abstract class ContinuationBase
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
((HttpServletResponse)response).addHeader("history","resume");
|
response.addHeader("history","resume");
|
||||||
continuation.resume();
|
continuation.resume();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -463,7 +463,7 @@ public abstract class ContinuationBase
|
||||||
}
|
}
|
||||||
else if (resume2_after==0)
|
else if (resume2_after==0)
|
||||||
{
|
{
|
||||||
((HttpServletResponse)response).addHeader("history","resume");
|
response.addHeader("history","resume");
|
||||||
continuation.resume();
|
continuation.resume();
|
||||||
}
|
}
|
||||||
if (undispatch)
|
if (undispatch)
|
||||||
|
|
|
@ -23,7 +23,7 @@ import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
import org.junit.Assert;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Connector;
|
import org.eclipse.jetty.server.Connector;
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
|
@ -194,6 +194,7 @@ public class ContinuationTest extends ContinuationBase
|
||||||
|
|
||||||
class Log extends AbstractLifeCycle implements RequestLog
|
class Log extends AbstractLifeCycle implements RequestLog
|
||||||
{
|
{
|
||||||
|
@Override
|
||||||
public void log(Request request, Response response)
|
public void log(Request request, Response response)
|
||||||
{
|
{
|
||||||
_log.add(response.getStatus()+" "+response.getContentCount()+" "+request.getRequestURI());
|
_log.add(response.getStatus()+" "+response.getContentCount()+" "+request.getRequestURI());
|
||||||
|
|
Loading…
Reference in New Issue