Merge remote-tracking branch 'origin/jetty-8'

Conflicts:
	jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java
	jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
	tests/test-continuation/src/test/java/org/eclipse/jetty/continuation/ContinuationTest.java
This commit is contained in:
Greg Wilkins 2013-07-04 15:00:47 +10:00
commit c33db24d94
9 changed files with 198 additions and 63 deletions

View File

@ -25,6 +25,7 @@ import javax.servlet.http.Cookie;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
@ -59,7 +60,6 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
private boolean _logLatency = false;
private boolean _logCookies = false;
private boolean _logServer = false;
private boolean _logDispatch = false;
private boolean _preferProxiedForAddress;
private transient DateCache _logDateCache;
private String _logDateFormat = "dd/MMM/yyyy:HH:mm:ss Z";
@ -193,17 +193,10 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
}
}
if (_logDispatch || _logLatency)
if (_logLatency)
{
long now = System.currentTimeMillis();
if (_logDispatch)
{
long d = request.getDispatchTime();
buf.append(' ');
buf.append(now - (d==0 ? request.getTimeStamp():d));
}
if (_logLatency)
{
buf.append(' ');
@ -340,24 +333,18 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
}
/**
* Controls logging of the request dispatch time
*
* @param value true - request dispatch time will be logged
* false - request dispatch time will not be logged
* @deprecated use {@link StatisticsHandler}
*/
public void setLogDispatch(boolean value)
{
_logDispatch = value;
}
/**
* Retrieve request dispatch time logging flag
*
* @return value of the flag
* @deprecated use {@link StatisticsHandler}
*/
public boolean isLogDispatch()
{
return _logDispatch;
return false;
}
/**

View File

@ -38,7 +38,7 @@ public class AsyncContextState implements AsyncContext
_state=state;
}
private HttpChannelState state()
HttpChannelState state()
{
HttpChannelState state=_state;
if (state==null)

View File

@ -203,7 +203,6 @@ public class Request implements HttpServletRequest
private HttpSession _session;
private SessionManager _sessionManager;
private long _timeStamp;
private long _dispatchTime;
private HttpURI _uri;
private MultiPartInputStreamParser _multiPartInputStream; //if the request is a multi-part mime
private AsyncContextState _async;
@ -1395,16 +1394,6 @@ public class Request implements HttpServletRequest
return null;
}
/* ------------------------------------------------------------ */
/**
* Get timestamp of the request dispatch
*
* @return timestamp
*/
public long getDispatchTime()
{
return _dispatchTime;
}
/* ------------------------------------------------------------ */
public boolean isHandled()
@ -1996,18 +1985,6 @@ public class Request implements HttpServletRequest
_scope = scope;
}
/* ------------------------------------------------------------ */
/**
* Set timetstamp of request dispatch
*
* @param value
* timestamp
*/
public void setDispatchTime(long value)
{
_dispatchTime = value;
}
/* ------------------------------------------------------------ */
@Override
public AsyncContext startAsync() throws IllegalStateException

View File

@ -20,11 +20,14 @@ package org.eclipse.jetty.server.handler;
import java.io.IOException;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.AsyncContextState;
import org.eclipse.jetty.server.HttpChannelState;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
@ -43,9 +46,37 @@ import org.eclipse.jetty.util.log.Logger;
*/
public class RequestLogHandler extends HandlerWrapper
{
private static final Logger LOG = Log.getLogger(RequestLogHandler.class);
private RequestLog _requestLog;
private final AsyncListener _listener = new AsyncListener()
{
@Override
public void onTimeout(AsyncEvent event) throws IOException
{
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException
{
event.getAsyncContext().addListener(this);
}
@Override
public void onError(AsyncEvent event) throws IOException
{
}
@Override
public void onComplete(AsyncEvent event) throws IOException
{
AsyncContextState context = (AsyncContextState)event.getAsyncContext();
Request request=context.getHttpChannelState().getBaseRequest();
Response response=request.getResponse();
_requestLog.log(request,response);
}
};
/* ------------------------------------------------------------ */
/*
@ -55,22 +86,19 @@ public class RequestLogHandler extends HandlerWrapper
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
HttpChannelState continuation = baseRequest.getHttpChannelState();
if (!continuation.isInitial())
{
baseRequest.setDispatchTime(System.currentTimeMillis());
}
try
{
super.handle(target, baseRequest, request, response);
}
finally
{
if (_requestLog != null && DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
if (baseRequest.getHttpChannelState().isAsync())
{
_requestLog.log(baseRequest, (Response)response);
if (baseRequest.getHttpChannelState().isInitial())
baseRequest.getAsyncContext().addListener(_listener);
}
else
_requestLog.log(baseRequest, (Response)response);
}
}

View File

@ -21,6 +21,8 @@ package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.AsyncContext;
@ -33,9 +35,14 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
@ -53,15 +60,28 @@ public class AsyncServletTest
protected Server _server = new Server();
protected ServletHandler _servletHandler;
protected ServerConnector _connector;
protected List<String> _log;
protected int _expectedLogs;
protected String _expectedCode;
@Before
public void setUp() throws Exception
{
_connector = new ServerConnector(_server);
_server.setConnectors(new Connector[]{ _connector });
_log=new ArrayList<>();
RequestLog log=new Log();
RequestLogHandler logHandler = new RequestLogHandler();
logHandler.setRequestLog(log);
_server.setHandler(logHandler);
_expectedLogs=1;
_expectedCode="200 ";
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
context.setContextPath("/ctx");
_server.setHandler(context);
logHandler.setHandler(context);
_servletHandler=context.getServletHandler();
ServletHolder holder=new ServletHolder(_servlet);
holder.setAsyncSupported(true);
@ -73,6 +93,8 @@ public class AsyncServletTest
@After
public void tearDown() throws Exception
{
assertEquals(_expectedLogs,_log.size());
Assert.assertThat(_log.get(0),Matchers.containsString(_expectedCode));
_server.stop();
}
@ -105,6 +127,7 @@ public class AsyncServletTest
@Test
public void testSuspend() throws Exception
{
_expectedCode="500 ";
String response=process("suspend=200",null);
assertEquals("HTTP/1.1 500 Async Timeout",response.substring(0,26));
assertContains(
@ -258,6 +281,7 @@ public class AsyncServletTest
@Test
public void testSuspendWaitResumeSuspend() throws Exception
{
_expectedCode="500 ";
String response=process("suspend=1000&resume=10&suspend2=10",null);
assertEquals("HTTP/1.1 500 Async Timeout",response.substring(0,26));
assertContains(
@ -316,6 +340,7 @@ public class AsyncServletTest
@Test
public void testSuspendTimeoutSuspend() throws Exception
{
_expectedCode="500 ";
String response=process("suspend=10&suspend2=10",null);
assertContains(
"history: REQUEST\r\n"+
@ -335,6 +360,7 @@ public class AsyncServletTest
@Test
public void testAsyncRead() throws Exception
{
_expectedLogs=2;
String header="GET /ctx/path/info?suspend=2000&resume=1500 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Content-Length: 10\r\n"+
@ -691,4 +717,13 @@ public class AsyncServletTest
((HttpServletResponse)event.getSuppliedResponse()).addHeader("history","onComplete");
}
};
class Log extends AbstractLifeCycle implements RequestLog
{
@Override
public void log(Request request, Response response)
{
_log.add(response.getStatus()+" "+response.getContentCount()+" "+request.getRequestURI());
}
}
}

View File

@ -32,6 +32,7 @@ import org.eclipse.jetty.servlets.gzip.GzipTester;
import org.eclipse.jetty.servlets.gzip.TestServletLengthStreamTypeWrite;
import org.eclipse.jetty.servlets.gzip.TestServletLengthTypeStreamWrite;
import org.eclipse.jetty.servlets.gzip.TestServletStreamLengthTypeWrite;
import org.eclipse.jetty.servlets.gzip.TestServletStreamLengthTypeWriteWithFlush;
import org.eclipse.jetty.servlets.gzip.TestServletStreamTypeLengthWrite;
import org.eclipse.jetty.servlets.gzip.TestServletTypeLengthStreamWrite;
import org.eclipse.jetty.servlets.gzip.TestServletTypeStreamLengthWrite;
@ -73,12 +74,14 @@ public class GzipFilterContentLengthTest
{ TestServletLengthStreamTypeWrite.class, GzipFilter.GZIP },
{ TestServletLengthTypeStreamWrite.class, GzipFilter.GZIP },
{ TestServletStreamLengthTypeWrite.class, GzipFilter.GZIP },
{ TestServletStreamLengthTypeWriteWithFlush.class, GzipFilter.GZIP },
{ TestServletStreamTypeLengthWrite.class, GzipFilter.GZIP },
{ TestServletTypeLengthStreamWrite.class, GzipFilter.GZIP },
{ TestServletTypeStreamLengthWrite.class, GzipFilter.GZIP },
{ TestServletLengthStreamTypeWrite.class, GzipFilter.DEFLATE },
{ TestServletLengthTypeStreamWrite.class, GzipFilter.DEFLATE },
{ TestServletStreamLengthTypeWrite.class, GzipFilter.DEFLATE },
{ TestServletStreamLengthTypeWriteWithFlush.class, GzipFilter.DEFLATE },
{ TestServletStreamTypeLengthWrite.class, GzipFilter.DEFLATE },
{ TestServletTypeLengthStreamWrite.class, GzipFilter.DEFLATE },
{ TestServletTypeStreamLengthWrite.class, GzipFilter.DEFLATE }

View File

@ -18,13 +18,8 @@
package org.eclipse.jetty.servlets.gzip;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@ -113,7 +108,17 @@ public class GzipTester
// Assert the response headers
// Assert.assertThat("Response.status",response.getStatus(),is(HttpServletResponse.SC_OK));
Assert.assertThat("Response.header[Content-Length]",response.get("Content-Length"),notNullValue());
// Response headers should have either a Transfer-Encoding indicating chunked OR a Content-Length
String contentLength = response.getHeader("Content-Length");
String transferEncoding = response.getHeader("Transfer-Encoding");
boolean chunked = (transferEncoding != null) && (transferEncoding.indexOf("chunk") >= 0);
if(!chunked) {
Assert.assertThat("Response.header[Content-Length]",contentLength,notNullValue());
} else {
Assert.assertThat("Response.header[Transfer-Encoding]",transferEncoding,notNullValue());
}
int qindex = compressionType.indexOf(";");
if (qindex < 0)
Assert.assertThat("Response.header[Content-Encoding]",response.get("Content-Encoding"),containsString(compressionType));

View File

@ -0,0 +1,72 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.servlets.gzip;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.servlets.GzipFilter;
/**
* A sample servlet to serve static content, using a order of construction that has caused problems for
* {@link GzipFilter} in the past.
*
* Using a real-world pattern of:
*
* <pre>
* 1) get stream
* 2) set content length
* 3) set content type
* 4) write and flush
* </pre>
*
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
*/
@SuppressWarnings("serial")
public class TestServletStreamLengthTypeWriteWithFlush extends TestDirContentServlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String fileName = request.getServletPath();
byte[] dataBytes = loadContentFileBytes(fileName);
ServletOutputStream out = response.getOutputStream();
// set content-length of uncompressed content (GzipFilter should handle this)
response.setContentLength(dataBytes.length);
if (fileName.endsWith("txt"))
response.setContentType("text/plain");
else if (fileName.endsWith("mp3"))
response.setContentType("audio/mpeg");
response.setHeader("ETag","W/etag-"+fileName);
for ( int i = 0 ; i < dataBytes.length ; i++)
{
out.write(dataBytes[i]);
// flush using response object (not the stream itself)
response.flushBuffer();
}
}
}

View File

@ -20,15 +20,24 @@ package org.eclipse.jetty.continuation;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import junit.framework.Assert;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -41,19 +50,27 @@ public class ContinuationTest extends ContinuationBase
protected ServletHandler _servletHandler;
protected ServerConnector _connector;
FilterHolder _filter;
protected List<String> _log = new ArrayList<String>();
@Before
public void setUp() throws Exception
{
_connector = new ServerConnector(_server);
_server.setConnectors(new Connector[]{ _connector });
_log.clear();
RequestLogHandler requestLogHandler = new RequestLogHandler();
requestLogHandler.setRequestLog(new Log());
_server.setHandler(requestLogHandler);
ServletContextHandler servletContext = new ServletContextHandler(ServletContextHandler.NO_SECURITY|ServletContextHandler.NO_SESSIONS);
_server.setHandler(servletContext);
requestLogHandler.setHandler(servletContext);
_servletHandler=servletContext.getServletHandler();
ServletHolder holder=new ServletHolder(_servlet);
holder.setAsyncSupported(true);
_servletHandler.addServletWithMapping(holder,"/");
_server.start();
_port=_connector.getLocalPort();
}
@ -61,6 +78,9 @@ public class ContinuationTest extends ContinuationBase
@After
public void tearDown() throws Exception
{
Assert.assertEquals(1,_log.size());
Assert.assertTrue(_log.get(0).startsWith("200 "));
Assert.assertTrue(_log.get(0).endsWith(" /"));
_server.stop();
}
@ -172,4 +192,12 @@ public class ContinuationTest extends ContinuationBase
return IO.toString(in);
}
class Log extends AbstractLifeCycle implements RequestLog
{
public void log(Request request, Response response)
{
_log.add(response.getStatus()+" "+response.getContentCount()+" "+request.getRequestURI());
}
}
}