Merged branch 'master' into 'jetty-http2'.

This commit is contained in:
Simone Bordet 2014-06-16 16:08:40 +02:00
commit adaeeefe32
20 changed files with 2377 additions and 53 deletions

View File

@ -1,6 +1,37 @@
jetty-10.0.0-SNAPSHOT
jetty-9.2.0-SNAPSHOT
jetty-9.2.2-SNAPSHOT
jetty-9.2.1.v20140609 - 09 June 2014
+ 347110 Supprt ClassFileTransormers in WebAppClassLoader
+ 432192 jetty-start / Allow JETTY_LOGS use for start-log-file
+ 432321 jetty-start / Allow defining extra start directories for common
configurations
+ 435322 Improved debug
+ 436029 GzipFilter errors on asynchronous methods with message to
AsyncGzipFilter
+ 436345 Refactor AbstractSession to minimize burden on subclasses to
implement behaviour
+ 436388 Allow case-insensitive STOP.KEY and STOP.PORT use
+ 436405 ${jetty.base}/resources not on classpath with default configuration
+ 436520 Start / Allow https and file urls in jetty-start's module download
mechanism
+ 436524 Start / Downloadable [files] references in modules cannot use ":"
themselves
jetty-9.2.0.v20140526 - 26 May 2014
+ 429390 Decoders and Encoders are not registered for non-annotated
ClientEndpoint
+ 434810 better handling of bad messages
+ 435086 ${jetty.base}/resources not on classpath when using
--module=resources
+ 435088 lib/npn packaging of jetty-distribution is off
+ 435206 Can't add Cookie header on websocket ClientUpgradeRequest
+ 435217 Remove deprecated TagLibConfiguration
+ 435223 High cpu usage in
FCGIHttpParser.parseContent(ResponseContentParser.java:314).
+ 435338 Incorrect handling of asynchronous content.
+ 435412 Make AbstractSession.access() more amenable to customization
jetty-9.2.0.RC0 - 15 May 2014
+ 419972 Support sending forms (application/x-www-form-urlencoded).

View File

@ -302,7 +302,7 @@
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<excludeGroupIds>org.eclipse.jetty.orbit,org.eclipse.jetty.spdy,org.eclipse.jetty.websocket,org.eclipse.jetty.fcgi,org.eclipse.jetty.toolchain,org.apache.taglibs</excludeGroupIds>
<excludeArtifactIds>jetty-all,jetty-jsp,apache-jsp,jetty-start,jetty-monitor</excludeArtifactIds>
<excludeArtifactIds>jetty-all,jetty-jsp,apache-jsp,jetty-start,jetty-monitor,jetty-spring</excludeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</configuration>
@ -332,6 +332,19 @@
<outputDirectory>${assembly-directory}/lib/fcgi</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-lib-spring-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<includeArtifactIds>jetty-spring</includeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib/spring</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-lib-monitor-deps</id>
<phase>generate-resources</phase>
@ -765,6 +778,11 @@
<artifactId>fcgi-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-spring</artifactId>
<version>${project.version}</version>
</dependency>
<!--
<dependency>
<groupId>org.eclipse.jetty</groupId>

View File

@ -141,6 +141,7 @@ src=application/x-wais-source
sv4cpio=application/x-sv4cpio
sv4crc=application/x-sv4crc
svg=image/svg+xml
svgz=image/svg+xml
swf=application/x-shockwave-flash
t=application/x-troff
tar=application/x-tar

View File

@ -25,8 +25,12 @@ import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.servlet.AsyncContext;
import javax.servlet.RequestDispatcher;
@ -125,6 +129,9 @@ import org.eclipse.jetty.util.resource.ResourceFactory;
*
* cacheControl If set, all static content will have this value set as the cache-control
* header.
*
* otherGzipFileExtensions
* Other file extensions that signify that a file is gzip compressed. Eg ".svgz"
*
*
* </PRE>
@ -164,6 +171,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
private String _relativeResourceBase;
private ServletHandler _servletHandler;
private ServletHolder _defaultHolder;
private List<String> _gzipEquivalentFileExtensions;
/* ------------------------------------------------------------ */
@Override
@ -273,6 +281,24 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
LOG.warn(Log.EXCEPTION,e);
throw new UnavailableException(e.toString());
}
_gzipEquivalentFileExtensions = new ArrayList<String>();
String otherGzipExtensions = getInitParameter("otherGzipFileExtensions");
if (otherGzipExtensions != null)
{
//comma separated list
StringTokenizer tok = new StringTokenizer(otherGzipExtensions,",",false);
while (tok.hasMoreTokens())
{
String s = tok.nextToken().trim();
_gzipEquivalentFileExtensions.add((s.charAt(0)=='.'?s:"."+s));
}
}
else
{
//.svgz files are gzipped svg files and must be served with Content-Encoding:gzip
_gzipEquivalentFileExtensions.add(".svgz");
}
_servletHandler= _contextHandler.getChildHandlerByClass(ServletHandler.class);
for (ServletHolder h :_servletHandler.getServlets())
@ -496,7 +522,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
{
if (gzip)
if (gzip || isGzippedContent(pathInContext))
{
response.setHeader(HttpHeader.CONTENT_ENCODING.asString(),"gzip");
String mt=_servletContext.getMimeType(pathInContext);
@ -585,6 +611,20 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
}
/**
* @param resource
* @return
*/
protected boolean isGzippedContent(String path)
{
if (path == null) return false;
for (String suffix:_gzipEquivalentFileExtensions)
if (path.endsWith(suffix))
return true;
return false;
}
/* ------------------------------------------------------------ */
private boolean hasDefinedRange(Enumeration<String> reqRanges)
{

View File

@ -1632,25 +1632,20 @@ public class ServletHandler extends ScopedHandler
{
LOG.debug("call filter {}", _filterHolder);
Filter filter= _filterHolder.getFilter();
if (_filterHolder.isAsyncSupported())
filter.doFilter(request, response, _next);
else
//if the request already does not support async, then the setting for the filter
//is irrelevant. However if the request supports async but this filter does not
//temporarily turn it off for the execution of the filter
boolean requestAsyncSupported = baseRequest.isAsyncSupported();
try
{
final boolean suspendable=baseRequest.isAsyncSupported();
if (suspendable)
{
try
{
baseRequest.setAsyncSupported(false);
filter.doFilter(request, response, _next);
}
finally
{
baseRequest.setAsyncSupported(true);
}
}
else
filter.doFilter(request, response, _next);
if (!_filterHolder.isAsyncSupported() && requestAsyncSupported)
baseRequest.setAsyncSupported(false);
filter.doFilter(request, response, _next);
}
finally
{
baseRequest.setAsyncSupported(requestAsyncSupported);
}
return;
}
@ -1711,23 +1706,20 @@ public class ServletHandler extends ScopedHandler
LOG.debug("call filter " + holder);
Filter filter= holder.getFilter();
if (holder.isAsyncSupported() || !_baseRequest.isAsyncSupported())
//if the request already does not support async, then the setting for the filter
//is irrelevant. However if the request supports async but this filter does not
//temporarily turn it off for the execution of the filter
boolean requestAsyncSupported = _baseRequest.isAsyncSupported();
try
{
if (!holder.isAsyncSupported() && requestAsyncSupported)
_baseRequest.setAsyncSupported(false);
filter.doFilter(request, response, this);
}
else
finally
{
try
{
_baseRequest.setAsyncSupported(false);
filter.doFilter(request, response, this);
}
finally
{
_baseRequest.setAsyncSupported(true);
}
_baseRequest.setAsyncSupported(requestAsyncSupported);
}
return;
}

View File

@ -209,14 +209,16 @@ public class AsyncGzipFilter extends UserAgentFilter implements GzipFactory
{
for (String type:MimeTypes.getKnownMimeTypes())
{
if (type.equals("image/svg+xml")) //always compressable (unless .svgz file)
continue;
if (type.startsWith("image/")||
type.startsWith("audio/")||
type.startsWith("video/"))
_mimeTypes.add(type);
_mimeTypes.add("application/compress");
_mimeTypes.add("application/zip");
_mimeTypes.add("application/gzip");
}
_mimeTypes.add("application/compress");
_mimeTypes.add("application/zip");
_mimeTypes.add("application/gzip");
}
else
{
@ -317,11 +319,11 @@ public class AsyncGzipFilter extends UserAgentFilter implements GzipFactory
}
// Exclude non compressible mime-types known from URI extension. - no Vary because no matter what client, this URI is always excluded
if (_mimeTypes.size()>0)
if (_mimeTypes.size()>0 && _excludeMimeTypes)
{
String mimeType = _context.getMimeType(request.getRequestURI());
if (mimeType!=null && _mimeTypes.contains(mimeType)==_excludeMimeTypes)
if (mimeType!=null && _mimeTypes.contains(mimeType))
{
LOG.debug("{} excluded by path suffix {}",this,request);
// handle normally without setting vary header
@ -330,6 +332,13 @@ public class AsyncGzipFilter extends UserAgentFilter implements GzipFactory
}
}
//If the Content-Encoding is already set, then we won't compress
if (response.getHeader("Content-Encoding") != null)
{
super.doFilter(request,response,chain);
return;
}
if (_checkGzExists && request.getServletContext()!=null)
{
String path=request.getServletContext().getRealPath(URIUtil.addPaths(request.getServletPath(),request.getPathInfo()));

View File

@ -208,14 +208,16 @@ public class GzipFilter extends UserAgentFilter
{
for (String type:MimeTypes.getKnownMimeTypes())
{
if (type.equals("image/svg+xml")) //always compressable (unless .svgz file)
continue;
if (type.startsWith("image/")||
type.startsWith("audio/")||
type.startsWith("video/"))
_mimeTypes.add(type);
_mimeTypes.add("application/compress");
_mimeTypes.add("application/zip");
_mimeTypes.add("application/gzip");
}
_mimeTypes.add("application/compress");
_mimeTypes.add("application/zip");
_mimeTypes.add("application/gzip");
}
else
{
@ -300,17 +302,24 @@ public class GzipFilter extends UserAgentFilter
}
// Exclude non compressible mime-types known from URI extension. - no Vary because no matter what client, this URI is always excluded
if (_mimeTypes.size()>0)
if (_mimeTypes.size()>0 && _excludeMimeTypes)
{
String mimeType = _context.getMimeType(request.getRequestURI());
if (mimeType!=null && _mimeTypes.contains(mimeType)==_excludeMimeTypes)
if (mimeType!=null && _mimeTypes.contains(mimeType))
{
// handle normally without setting vary header
super.doFilter(request,response,chain);
return;
}
}
//If the Content-Encoding is already set, then we won't compress
if (response.getHeader("Content-Encoding") != null)
{
super.doFilter(request,response,chain);
return;
}
if (_checkGzExists && request.getServletContext()!=null)
{

View File

@ -151,6 +151,16 @@ public class GzipHttpOutput extends HttpOutput
}
}
// Has the Content-Encoding header already been set?
String ce=getHttpChannel().getResponse().getHeader("Content-Encoding");
if (ce != null)
{
LOG.debug("{} exclude by content-encoding {}",this,ce);
noCompression();
super.write(content,complete,callback);
return;
}
// Are we the thread that commits?
if (_state.compareAndSet(GZState.MIGHT_COMPRESS,GZState.COMMITTING))
{
@ -188,6 +198,7 @@ public class GzipHttpOutput extends HttpOutput
gzip(content,complete,callback);
}
// TODO else ?
}
public void noCompression()

View File

@ -273,6 +273,24 @@ public class GzipFilterDefaultTest
}
}
@Test
public void testGzippedIfSVG() throws Exception
{
GzipTester tester = new GzipTester(testingdir, compressionType);
tester.setGzipFilterClass(testFilter);
tester.copyTestServerFile("test.svg");
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
try
{
tester.start();
HttpTester.Response http = tester.assertIsResponseGzipCompressed("GET","test.svg",System.currentTimeMillis()-4000);
Assert.assertEquals("Accept-Encoding",http.get("Vary"));
}
finally
{
tester.stop();
}
}
@Test
public void testNotGzipedIfNotModified() throws Exception
@ -553,4 +571,24 @@ public class GzipFilterDefaultTest
tester.stop();
}
}
@Test
public void testIsNotGzipCompressedSVGZ() throws Exception
{
GzipTester tester = new GzipTester(testingdir,compressionType);
tester.setGzipFilterClass(testFilter);
FilterHolder holder = tester.setContentServlet(DefaultServlet.class);
tester.copyTestServerFile("test.svgz");
try
{
tester.start();
tester.assertIsResponseNotGzipFiltered("test.svgz", "test.svgz.sha1", "image/svg+xml", "gzip");
}
finally
{
tester.stop();
}
}
}

View File

@ -282,6 +282,27 @@ public class GzipTester
* @param expectedContentType
*/
public void assertIsResponseNotGzipFiltered(String requestedFilename, String testResourceSha1Sum, String expectedContentType) throws Exception
{
assertIsResponseNotGzipFiltered(requestedFilename, testResourceSha1Sum, expectedContentType,null);
}
/**
* Makes sure that the response contains an unfiltered file contents.
* <p>
* This is used to test exclusions and passthroughs in the GzipFilter.
* <p>
* An example is to test that it is possible to configure GzipFilter to not recompress content that shouldn't be
* compressed by the GzipFilter.
*
* @param requestedFilename
* the filename used to on the GET request,.
* @param testResourceSha1Sum
* the sha1sum file that contains the SHA1SUM checksum that will be used to verify that the response
* contents are what is intended.
* @param expectedContentType
* @param expectedContentEncoding can be non-null in some circumstances, eg when dealing with pre-gzipped .svgz files
*/
public void assertIsResponseNotGzipFiltered(String requestedFilename, String testResourceSha1Sum, String expectedContentType, String expectedContentEncoding) throws Exception
{
//System.err.printf("[GzipTester] requesting /context/%s%n",requestedFilename);
HttpTester.Request request = HttpTester.newRequest();
@ -304,7 +325,10 @@ public class GzipTester
String prefix = requestedFilename + " / Response";
Assert.assertThat(prefix + ".status",response.getStatus(),is(HttpServletResponse.SC_OK));
Assert.assertThat(prefix + ".header[Content-Length]",response.get("Content-Length"),notNullValue());
Assert.assertThat(prefix + ".header[Content-Encoding] (should not be recompressed by GzipFilter)",response.get("Content-Encoding"),nullValue());
Assert.assertThat(prefix + ".header[Content-Encoding] (should not be recompressed by GzipFilter)",response.get("Content-Encoding"),
expectedContentEncoding == null? nullValue() : notNullValue());
if (expectedContentEncoding != null)
Assert.assertThat(prefix + ".header[Content-Encoding]",response.get("Content-Encoding"),is(expectedContentEncoding));
Assert.assertThat(prefix + ".header[Content-Type] (should have a Content-Type associated with it)",response.get("Content-Type"),notNullValue());
Assert.assertThat(prefix + ".header[Content-Type]",response.get("Content-Type"),is(expectedContentType));
@ -339,7 +363,7 @@ public class GzipTester
{
String name = names.nextElement();
String value = message.get(name);
//System.out.printf(" [%s] = %s%n",name,value);
//System.out.printf(" [%s] = %s%n",name,value);
}
}

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -0,0 +1 @@
1ccb7a0b85585d0e9bdc3863ad093d4e53a9ea68 test.svg

Binary file not shown.

View File

@ -0,0 +1 @@
62df7c3ac6ee6e4462b6abf9ef15b4e916ecf68f test.svgz

View File

@ -24,6 +24,13 @@
</jvmArgs>
<jettyXml>${basedir}/src/main/config/example-jetty-spdy.xml</jettyXml>
<contextPath>/</contextPath>
<excludedGoals>
<excludedGoal>run</excludedGoal>
<excludedGoal>run-war</excludedGoal>
<excludedGoal>deploy</excludedGoal>
<excludedGoal>start</excludedGoal>
<excludedGoal>stop</excludedGoal>
</excludedGoals>
</configuration>
<dependencies>
<dependency>
@ -53,6 +60,13 @@
</jvmArgs>
<jettyXml>${basedir}/src/main/config/example-jetty-spdy-proxy.xml</jettyXml>
<contextPath>/</contextPath>
<excludedGoals>
<excludedGoal>run</excludedGoal>
<excludedGoal>run-war</excludedGoal>
<excludedGoal>deploy</excludedGoal>
<excludedGoal>start</excludedGoal>
<excludedGoal>stop</excludedGoal>
</excludedGoals>
</configuration>
<dependencies>
<dependency>

View File

@ -0,0 +1,8 @@
[name]
protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/npn/npn-boot/1.1.7.v20140316/npn-boot-1.1.7.v20140316.jar|lib/npn/npn-boot-1.1.7.v20140316.jar
[exec]
-Xbootclasspath/p:lib/npn/npn-boot-1.1.7.v20140316.jar

View File

@ -9,7 +9,7 @@
<name>Example :: Jetty Spring</name>
<properties>
<spring-version>3.1.3.RELEASE</spring-version>
<spring-version>3.2.8.RELEASE</spring-version>
<dependencies>target/dependencies</dependencies>
</properties>

View File

@ -0,0 +1,16 @@
#
# Spring
#
[name]
spring
[depend]
server
[lib]
lib/spring/*.jar
[ini-template]
## See http://www.eclipse.org/jetty/documentation/current/frameworks.html#framework-jetty-spring
## for information on how to complete spring configuration

View File

@ -35,6 +35,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.frames.ControlFrame;
import org.eclipse.jetty.websocket.common.message.MessageInputStream;
import org.eclipse.jetty.websocket.common.message.MessageReader;
import org.eclipse.jetty.websocket.jsr356.JsrPongMessage;
@ -235,11 +236,20 @@ public class JsrEndpointEventDriver extends AbstractJsrEventDriver
LOG.debug("No PONG MessageHandler declared");
return;
}
ByteBuffer pongBuf = ByteBuffer.allocate(buffer.remaining());
BufferUtil.put(buffer,pongBuf);
BufferUtil.flipToFlush(pongBuf,0);
ByteBuffer pongBuf = null;
if (BufferUtil.isEmpty(buffer))
{
pongBuf = BufferUtil.EMPTY_BUFFER;
}
else
{
pongBuf = ByteBuffer.allocate(buffer.remaining());
BufferUtil.put(buffer,pongBuf);
BufferUtil.flipToFlush(pongBuf,0);
}
@SuppressWarnings("unchecked")
Whole<PongMessage> pongHandler = (Whole<PongMessage>)wrapper.getHandler();
pongHandler.onMessage(new JsrPongMessage(pongBuf));

View File

@ -458,9 +458,9 @@
<module>jetty-alpn</module>
<module>jetty-npn</module>
<!-- modules that need fixed and added back, or simply dropped and not maintained
<module>jetty-rhttp</module>
-->
<!-- modules that need fixed and added back, or simply dropped and not maintained
<module>jetty-rhttp</module>
-->
<!--<module>jetty-overlay-deployer</module>-->
</modules>
<dependencyManagement>