Merge remote-tracking branch 'origin/master' into jetty-8
Conflicts: VERSION.txt
This commit is contained in:
commit
6e8afd6795
25
VERSION.txt
25
VERSION.txt
|
@ -11,7 +11,7 @@ jetty-8.0.0.M3 27 May 2011
|
||||||
+ 346180 jsp-2.2 support
|
+ 346180 jsp-2.2 support
|
||||||
+ Updated to jetty-7.4.2.v20110526
|
+ Updated to jetty-7.4.2.v20110526
|
||||||
|
|
||||||
jetty-7.5.0-SNAPSHOT
|
jetty-7.5.0.RC0 August 15th 2011
|
||||||
+ 298502 Handle 200 Connect responses with no content-length
|
+ 298502 Handle 200 Connect responses with no content-length
|
||||||
+ 351516 Refactored sessions to better support nosql session managers
|
+ 351516 Refactored sessions to better support nosql session managers
|
||||||
+ 351576 Do not use deprecated method File.toURL()
|
+ 351576 Do not use deprecated method File.toURL()
|
||||||
|
@ -30,6 +30,7 @@ jetty-7.5.0-SNAPSHOT
|
||||||
+ 353862 Improve performance of QuotedStringTokenizer.quote()
|
+ 353862 Improve performance of QuotedStringTokenizer.quote()
|
||||||
+ 354014 Content-Length is passed to wrapped response in GZipFilter
|
+ 354014 Content-Length is passed to wrapped response in GZipFilter
|
||||||
+ 354204 Charset encodings property file not used
|
+ 354204 Charset encodings property file not used
|
||||||
|
+ 354397 RewriteRegexRule handles special characters in regex group
|
||||||
+ 354466 Typo in example config of jetty-plus.xml
|
+ 354466 Typo in example config of jetty-plus.xml
|
||||||
|
|
||||||
jetty-7.4.4.v20110707 July 7th 2011
|
jetty-7.4.4.v20110707 July 7th 2011
|
||||||
|
@ -2357,7 +2358,7 @@ jetty-6.0.0rc0 - 7 July 2006
|
||||||
+ fixed HttpGenerator convertion of non UTF-8: JETTY-82
|
+ fixed HttpGenerator convertion of non UTF-8: JETTY-82
|
||||||
+ added html module from jetty 5 - but deprecated until maintainer found
|
+ added html module from jetty 5 - but deprecated until maintainer found
|
||||||
|
|
||||||
jetty-6.0.0beta17 - 1/6/2006
|
jetty-6.0.0beta17 - 1 Jun 2006
|
||||||
+ Added config to disable file memory mapped buffers for windows
|
+ Added config to disable file memory mapped buffers for windows
|
||||||
+ Added Request.isHandled()
|
+ Added Request.isHandled()
|
||||||
+ Refactored Synchronization of SelectChannelConnector
|
+ Refactored Synchronization of SelectChannelConnector
|
||||||
|
@ -2373,11 +2374,11 @@ jetty-6.0.0beta17 - 1/6/2006
|
||||||
+ don't reset headers during forward
|
+ don't reset headers during forward
|
||||||
+ BoundedThreadPool.doStop waits for threads to complete
|
+ BoundedThreadPool.doStop waits for threads to complete
|
||||||
|
|
||||||
jetty-6.0.0beta16 - 12/5/2006
|
jetty-6.0.0beta16 - 12 May 2006
|
||||||
+ remove a couple of System.err.printlns
|
+ remove a couple of System.err.printlns
|
||||||
+ replace backwards compativle API in UrlEncoded
|
+ replace backwards compativle API in UrlEncoded
|
||||||
|
|
||||||
jetty-6.0.0beta15 - 11/5/2006
|
jetty-6.0.0beta15 - 11 May 2006
|
||||||
+ Added Server attribute org.mortbay.jetty.Request.maxFormContentSize
|
+ Added Server attribute org.mortbay.jetty.Request.maxFormContentSize
|
||||||
+ Renamed NotFoundHandler to DefaultHandler
|
+ Renamed NotFoundHandler to DefaultHandler
|
||||||
+ Added automatic scan of all WEB-INF/jetty-*.xml files for plugin
|
+ Added automatic scan of all WEB-INF/jetty-*.xml files for plugin
|
||||||
|
@ -2404,7 +2405,7 @@ jetty-6.0.0beta15 - 11/5/2006
|
||||||
+ don't accept partial authority in request line.
|
+ don't accept partial authority in request line.
|
||||||
+ enforce 204 and 304 have no content
|
+ enforce 204 and 304 have no content
|
||||||
|
|
||||||
jetty-6.0.0beta14 - 9/4/2006
|
jetty-6.0.0beta14 - 9 Apr 2006
|
||||||
+ ignore dirs and files that don't exist in plugin scanner
|
+ ignore dirs and files that don't exist in plugin scanner
|
||||||
+ added support for stopping jetty using "java -jar start.jar --stop"
|
+ added support for stopping jetty using "java -jar start.jar --stop"
|
||||||
+ added configurability for webdefault.xml in maven plugin
|
+ added configurability for webdefault.xml in maven plugin
|
||||||
|
@ -2428,7 +2429,7 @@ jetty-6.0.0beta14 - 9/4/2006
|
||||||
+ added reset to Continuation
|
+ added reset to Continuation
|
||||||
|
|
||||||
|
|
||||||
jetty-6.0.0beta12 - 16/3/2006
|
jetty-6.0.0beta12 - 16 Mar 2006
|
||||||
+ Fixed maven plugin JNDI for redeploys
|
+ Fixed maven plugin JNDI for redeploys
|
||||||
+ Fixed tld discovery for plugin (search dependencies)
|
+ Fixed tld discovery for plugin (search dependencies)
|
||||||
+ Fixed JettyPlus for root contexts
|
+ Fixed JettyPlus for root contexts
|
||||||
|
@ -2438,7 +2439,7 @@ jetty-6.0.0beta12 - 16/3/2006
|
||||||
+ Added provider support to SslListener
|
+ Added provider support to SslListener
|
||||||
+ Log ERROR for runtimeExceptions
|
+ Log ERROR for runtimeExceptions
|
||||||
|
|
||||||
jetty-6.0.0beta11 - 14/3/2006
|
jetty-6.0.0beta11 - 14 Mar 2006
|
||||||
+ added JAAS
|
+ added JAAS
|
||||||
+ added webapp-specific JNDI entries
|
+ added webapp-specific JNDI entries
|
||||||
+ added missing Configurations for maven plugin
|
+ added missing Configurations for maven plugin
|
||||||
|
@ -2451,7 +2452,7 @@ jetty-6.0.0beta11 - 14/3/2006
|
||||||
+ Added HttpURI and improved UTF-8 parsing.
|
+ Added HttpURI and improved UTF-8 parsing.
|
||||||
+ refactored writers and improved UTF-8 generation.
|
+ refactored writers and improved UTF-8 generation.
|
||||||
|
|
||||||
jetty-6.0.0beta10 25/2/2006
|
jetty-6.0.0beta10 25 Feb 2006
|
||||||
+ Added support for java:comp/env
|
+ Added support for java:comp/env
|
||||||
+ Added support for pluggable transaction manager
|
+ Added support for pluggable transaction manager
|
||||||
+ Forward masks include attributes and vice versa
|
+ Forward masks include attributes and vice versa
|
||||||
|
@ -2465,7 +2466,7 @@ jetty-6.0.0beta10 25/2/2006
|
||||||
+ Fix http://jira.codehaus.org/browse/JETTY-6. hi byte reader
|
+ Fix http://jira.codehaus.org/browse/JETTY-6. hi byte reader
|
||||||
+ Updates javax to MR2 release
|
+ Updates javax to MR2 release
|
||||||
|
|
||||||
jetty-6.0.0beta9 9/2/2006
|
jetty-6.0.0beta9 9 Feb 2006
|
||||||
+ PathMap for direct context mapping.
|
+ PathMap for direct context mapping.
|
||||||
+ Refactored chat demo and upgraded prototype.js
|
+ Refactored chat demo and upgraded prototype.js
|
||||||
+ Continuation cleanup
|
+ Continuation cleanup
|
||||||
|
@ -2479,7 +2480,7 @@ jetty-6.0.0beta9 9/2/2006
|
||||||
+ fixed setLocale bug sf1426940
|
+ fixed setLocale bug sf1426940
|
||||||
+ Added TLD tag listener handling.
|
+ Added TLD tag listener handling.
|
||||||
|
|
||||||
jetty-6.0.0beta8 24/1/2006
|
jetty-6.0.0beta8 24 Jan 2006
|
||||||
+ fixed dispatch of new session problem. sf:1407090
|
+ fixed dispatch of new session problem. sf:1407090
|
||||||
+ reinstated rfc2616 test harness
|
+ reinstated rfc2616 test harness
|
||||||
+ Handle pipeline requests without hangs
|
+ Handle pipeline requests without hangs
|
||||||
|
@ -3248,7 +3249,7 @@ Jetty-4.2.0 - 16 November 2002
|
||||||
+ Added upload demo to dump servlet.
|
+ Added upload demo to dump servlet.
|
||||||
+ Many more optimizations.
|
+ Many more optimizations.
|
||||||
|
|
||||||
Jetty-4.1.4 - 16 November
|
Jetty-4.1.4 - 16 November 2002
|
||||||
+ Fixed ContextLoader parent delegation bug
|
+ Fixed ContextLoader parent delegation bug
|
||||||
+ Fixed remove SocketListener bug.
|
+ Fixed remove SocketListener bug.
|
||||||
+ Fixed Invoker servlet for RD.include
|
+ Fixed Invoker servlet for RD.include
|
||||||
|
@ -3277,7 +3278,7 @@ Jetty-4.2.0rc0 - 24 October 2002
|
||||||
+ Added authenticator to admin.xml
|
+ Added authenticator to admin.xml
|
||||||
+ Fixed Session timeout NPE.
|
+ Fixed Session timeout NPE.
|
||||||
|
|
||||||
Jetty-4.1.3 - 24 October 2002
|
Jetty-4.1.3 - 24 October 2002
|
||||||
+ Fixed RolloverFileOutputStream without date.
|
+ Fixed RolloverFileOutputStream without date.
|
||||||
+ Fixed SessionManager initialization
|
+ Fixed SessionManager initialization
|
||||||
+ Added authenticator to admin.xml
|
+ Added authenticator to admin.xml
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package org.eclipse.jetty.http;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.io.Buffer;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class MimeTypesTest
|
||||||
|
{
|
||||||
|
@Test
|
||||||
|
public void testGetMimeByExtension_Gzip()
|
||||||
|
{
|
||||||
|
assertMimeTypeByExtension("application/gzip","test.gz");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMimeByExtension_Png()
|
||||||
|
{
|
||||||
|
assertMimeTypeByExtension("image/png","test.png");
|
||||||
|
assertMimeTypeByExtension("image/png","TEST.PNG");
|
||||||
|
assertMimeTypeByExtension("image/png","Test.Png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMimeByExtension_Png_MultiDot()
|
||||||
|
{
|
||||||
|
assertMimeTypeByExtension("image/png","org.eclipse.jetty.Logo.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMimeByExtension_Png_DeepPath()
|
||||||
|
{
|
||||||
|
assertMimeTypeByExtension("image/png","/org/eclipse/jetty/Logo.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMimeByExtension_Text()
|
||||||
|
{
|
||||||
|
assertMimeTypeByExtension("text/plain","test.txt");
|
||||||
|
assertMimeTypeByExtension("text/plain","TEST.TXT");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertMimeTypeByExtension(String expectedMimeType, String filename)
|
||||||
|
{
|
||||||
|
MimeTypes mimetypes = new MimeTypes();
|
||||||
|
Buffer contentType = mimetypes.getMimeByExtension(filename);
|
||||||
|
String prefix = "MimeTypes.getMimeByExtension(" + filename + ")";
|
||||||
|
Assert.assertNotNull(prefix,contentType);
|
||||||
|
Assert.assertEquals(prefix,expectedMimeType,contentType.toString());
|
||||||
|
}
|
||||||
|
}
|
|
@ -119,6 +119,12 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
||||||
_manager.endPointUpgraded(this,old);
|
_manager.endPointUpgraded(this,old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public long getIdleTimestamp()
|
||||||
|
{
|
||||||
|
return _idleTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/** Called by selectSet to schedule handling
|
/** Called by selectSet to schedule handling
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class RewriteRegexRule extends RegexRule implements Rule.ApplyURI
|
||||||
target=_replacement;
|
target=_replacement;
|
||||||
for (int g=1;g<=matcher.groupCount();g++)
|
for (int g=1;g<=matcher.groupCount();g++)
|
||||||
{
|
{
|
||||||
String group = matcher.group(g);
|
String group = Matcher.quoteReplacement(matcher.group(g));
|
||||||
target=target.replaceAll("\\$"+g,group);
|
target=target.replaceAll("\\$"+g,group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ public class RewriteRegexRule extends RegexRule implements Rule.ApplyURI
|
||||||
String uri=_replacement;
|
String uri=_replacement;
|
||||||
for (int g=1;g<=matcher.groupCount();g++)
|
for (int g=1;g<=matcher.groupCount();g++)
|
||||||
{
|
{
|
||||||
String group = matcher.group(g);
|
String group = Matcher.quoteReplacement(matcher.group(g));
|
||||||
uri=uri.replaceAll("\\$"+g,group);
|
uri=uri.replaceAll("\\$"+g,group);
|
||||||
}
|
}
|
||||||
request.setRequestURI(uri);
|
request.setRequestURI(uri);
|
||||||
|
|
|
@ -26,6 +26,8 @@ public class RewriteRegexRuleTest extends AbstractRuleTestCase
|
||||||
{"/foo/bar",".*","/replace","/replace"},
|
{"/foo/bar",".*","/replace","/replace"},
|
||||||
{"/foo/bar","/xxx.*","/replace",null},
|
{"/foo/bar","/xxx.*","/replace",null},
|
||||||
{"/foo/bar","/(.*)/(.*)","/$2/$1/xxx","/bar/foo/xxx"},
|
{"/foo/bar","/(.*)/(.*)","/$2/$1/xxx","/bar/foo/xxx"},
|
||||||
|
{"/foo/$bar",".*","/$replace","/$replace"},
|
||||||
|
{"/foo/$bar","/foo/(.*)","/$1/replace","/$bar/replace"},
|
||||||
};
|
};
|
||||||
private RewriteRegexRule _rule;
|
private RewriteRegexRule _rule;
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,15 @@ import java.util.List;
|
||||||
import javax.servlet.Servlet;
|
import javax.servlet.Servlet;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||||
|
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||||
import org.eclipse.jetty.servlet.FilterHolder;
|
import org.eclipse.jetty.servlet.FilterHolder;
|
||||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
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.TestServletLengthTypeStreamWrite;
|
||||||
import org.eclipse.jetty.servlets.gzip.TestServletStreamLengthTypeWrite;
|
import org.eclipse.jetty.servlets.gzip.TestServletStreamLengthTypeWrite;
|
||||||
import org.eclipse.jetty.servlets.gzip.TestServletStreamTypeLengthWrite;
|
import org.eclipse.jetty.servlets.gzip.TestServletStreamTypeLengthWrite;
|
||||||
import org.eclipse.jetty.servlets.gzip.TestServletTypeLengthStreamWrite;
|
import org.eclipse.jetty.servlets.gzip.TestServletTypeLengthStreamWrite;
|
||||||
|
import org.eclipse.jetty.servlets.gzip.TestServletTypeStreamLengthWrite;
|
||||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -30,11 +33,13 @@ public class GzipFilterContentLengthTest
|
||||||
/**
|
/**
|
||||||
* These are the junit parameters for running this test.
|
* These are the junit parameters for running this test.
|
||||||
* <p>
|
* <p>
|
||||||
* We have 4 test servlets, that arrange the content-length/content-type/get stream in different orders so as to
|
* In addition to Jetty's DefaultServlet we have multiple test
|
||||||
* simulate the real world scenario that caused the bug in <a
|
* servlets that arrange content-length/content-type/get stream
|
||||||
* href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
* in different order so as to simulate the real world scenario
|
||||||
|
* that caused the bug in Eclipse <a href="Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||||
* <p>
|
* <p>
|
||||||
* This test case will be run with each entry in the array below as setup parameters for the test case.
|
* This test case will be run with each of the entries in
|
||||||
|
* the array below as setup parameters for the test case.
|
||||||
*
|
*
|
||||||
* @return the junit parameters
|
* @return the junit parameters
|
||||||
*/
|
*/
|
||||||
|
@ -43,15 +48,19 @@ public class GzipFilterContentLengthTest
|
||||||
{
|
{
|
||||||
return Arrays.asList(new Object[][]
|
return Arrays.asList(new Object[][]
|
||||||
{
|
{
|
||||||
|
{ DefaultServlet.class },
|
||||||
|
{ TestServletLengthStreamTypeWrite.class },
|
||||||
{ TestServletLengthTypeStreamWrite.class },
|
{ TestServletLengthTypeStreamWrite.class },
|
||||||
{ TestServletStreamLengthTypeWrite.class },
|
{ TestServletStreamLengthTypeWrite.class },
|
||||||
{ TestServletStreamTypeLengthWrite.class },
|
{ TestServletStreamTypeLengthWrite.class },
|
||||||
{ TestServletTypeLengthStreamWrite.class } });
|
{ TestServletTypeLengthStreamWrite.class },
|
||||||
|
{ TestServletTypeStreamLengthWrite.class } });
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int LARGE = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 8;
|
private static final int LARGE = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 8;
|
||||||
private static final int MEDIUM = GzipResponseWrapper.DEFAULT_BUFFER_SIZE;
|
private static final int MEDIUM = GzipResponseWrapper.DEFAULT_BUFFER_SIZE;
|
||||||
private static final int SMALL = GzipResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
|
private static final int SMALL = GzipResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
|
||||||
|
private static final int TINY = GzipResponseWrapper.DEFAULT_MIN_GZIP_SIZE / 2;
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public TestingDir testingdir = new TestingDir();
|
public TestingDir testingdir = new TestingDir();
|
||||||
|
@ -63,20 +72,19 @@ public class GzipFilterContentLengthTest
|
||||||
this.testServlet = testServlet;
|
this.testServlet = testServlet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertIsGzipCompressed(Class<? extends Servlet> servletClass, int filesize) throws Exception
|
private void assertIsGzipCompressed(String filename, int filesize) throws Exception
|
||||||
{
|
{
|
||||||
GzipTester tester = new GzipTester(testingdir);
|
GzipTester tester = new GzipTester(testingdir);
|
||||||
|
|
||||||
// Test content that is smaller than the buffer.
|
tester.prepareServerFile(filename,filesize);
|
||||||
tester.prepareServerFile("file.txt",filesize);
|
|
||||||
|
|
||||||
FilterHolder holder = tester.setContentServlet(servletClass);
|
FilterHolder holder = tester.setContentServlet(testServlet);
|
||||||
holder.setInitParameter("mimeTypes","text/plain");
|
holder.setInitParameter("mimeTypes","text/plain");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tester.start();
|
tester.start();
|
||||||
tester.assertIsResponseGzipCompressed("file.txt");
|
tester.assertIsResponseGzipCompressed(filename);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -84,20 +92,19 @@ public class GzipFilterContentLengthTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertIsNotGzipCompressed(Class<? extends Servlet> servletClass, int filesize) throws Exception
|
private void assertIsNotGzipCompressed(String filename, int filesize) throws Exception
|
||||||
{
|
{
|
||||||
GzipTester tester = new GzipTester(testingdir);
|
GzipTester tester = new GzipTester(testingdir);
|
||||||
|
|
||||||
// Test content that is smaller than the buffer.
|
tester.prepareServerFile(filename,filesize);
|
||||||
tester.prepareServerFile("file.mp3",filesize);
|
|
||||||
|
|
||||||
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
|
FilterHolder holder = tester.setContentServlet(testServlet);
|
||||||
holder.setInitParameter("mimeTypes","text/plain");
|
holder.setInitParameter("mimeTypes","text/plain");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tester.start();
|
tester.start();
|
||||||
tester.assertIsResponseNotGzipCompressed("file.mp3",filesize);
|
tester.assertIsResponseNotGzipCompressed(filename,filesize);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -105,42 +112,78 @@ public class GzipFilterContentLengthTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsGzipCompressedTiny() throws Exception
|
|
||||||
{
|
|
||||||
assertIsGzipCompressed(testServlet,SMALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for Length>Type>Stream>Write problems encountered in GzipFilter
|
* Tests gzip compression of a small size file
|
||||||
*
|
*/
|
||||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
@Test
|
||||||
|
public void testIsGzipCompressedSmall() throws Exception
|
||||||
|
{
|
||||||
|
assertIsGzipCompressed("file.txt",SMALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests gzip compression of a medium size file
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testIsGzipCompressedMedium() throws Exception
|
public void testIsGzipCompressedMedium() throws Exception
|
||||||
{
|
{
|
||||||
assertIsGzipCompressed(testServlet,MEDIUM);
|
assertIsGzipCompressed("file.txt",MEDIUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for Length>Type>Stream>Write problems encountered in GzipFilter
|
* Tests gzip compression of a large size file
|
||||||
*
|
|
||||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testIsGzipCompressedLarge() throws Exception
|
public void testIsGzipCompressedLarge() throws Exception
|
||||||
{
|
{
|
||||||
assertIsGzipCompressed(testServlet,LARGE);
|
assertIsGzipCompressed("file.txt",LARGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for Length>Type>Stream>Write problems encountered in GzipFilter
|
* Tests for problems with Content-Length header on small size files
|
||||||
|
* that are not being compressed encountered when using GzipFilter
|
||||||
*
|
*
|
||||||
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testIsNotGzipCompressed() throws Exception
|
public void testIsNotGzipCompressedTiny() throws Exception
|
||||||
{
|
{
|
||||||
assertIsNotGzipCompressed(TestServletLengthTypeStreamWrite.class,LARGE);
|
assertIsNotGzipCompressed("file.txt",TINY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for problems with Content-Length header on small size files
|
||||||
|
* that are not being compressed encountered when using GzipFilter
|
||||||
|
*
|
||||||
|
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testIsNotGzipCompressedSmall() throws Exception
|
||||||
|
{
|
||||||
|
assertIsNotGzipCompressed("file.mp3",SMALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for problems with Content-Length header on medium size files
|
||||||
|
* that are not being compressed encountered when using GzipFilter
|
||||||
|
*
|
||||||
|
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testIsNotGzipCompressedMedium() throws Exception
|
||||||
|
{
|
||||||
|
assertIsNotGzipCompressed("file.mp3",MEDIUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for problems with Content-Length header on large size files
|
||||||
|
* that were not being compressed encountered when using GzipFilter
|
||||||
|
*
|
||||||
|
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testIsNotGzipCompressedLarge() throws Exception
|
||||||
|
{
|
||||||
|
assertIsNotGzipCompressed("file.mp3",LARGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@ import java.util.List;
|
||||||
import org.eclipse.jetty.servlet.DefaultServlet;
|
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||||
import org.eclipse.jetty.servlet.FilterHolder;
|
import org.eclipse.jetty.servlet.FilterHolder;
|
||||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||||
|
import org.eclipse.jetty.servlets.gzip.TestStaticMimeTypeServlet;
|
||||||
import org.eclipse.jetty.toolchain.test.IO;
|
import org.eclipse.jetty.toolchain.test.IO;
|
||||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
@ -19,9 +19,8 @@ import org.junit.runners.Parameterized;
|
||||||
import org.junit.runners.Parameterized.Parameters;
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link GzipFilter} in combination with {@link DefaultServlet} for
|
* Tests {@link GzipFilter} in combination with {@link DefaultServlet} for ability to configure {@link GzipFilter} to
|
||||||
* ability to configure {@link GzipFilter} to ignore recompress situations
|
* ignore recompress situations from upstream.
|
||||||
* from upstream.
|
|
||||||
*/
|
*/
|
||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class GzipFilterDefaultNoRecompressTest
|
public class GzipFilterDefaultNoRecompressTest
|
||||||
|
@ -32,59 +31,52 @@ public class GzipFilterDefaultNoRecompressTest
|
||||||
return Arrays.asList(new Object[][]
|
return Arrays.asList(new Object[][]
|
||||||
{
|
{
|
||||||
// Some already compressed files
|
// Some already compressed files
|
||||||
{ "test_quotes.gz" },
|
{ "test_quotes.gz", "application/gzip" },
|
||||||
{ "test_quotes.bz2" },
|
{ "test_quotes.bz2", "application/bzip2" },
|
||||||
{ "test_quotes.zip" },
|
{ "test_quotes.zip", "application/zip" },
|
||||||
{ "test_quotes.rar" },
|
{ "test_quotes.rar", "application/octet-stream" },
|
||||||
// Some images (common first)
|
// Some images (common first)
|
||||||
{ "jetty_logo.png" },
|
{ "jetty_logo.png", "image/png" },
|
||||||
{ "jetty_logo.gif" },
|
{ "jetty_logo.gif", "image/gif" },
|
||||||
{ "jetty_logo.jpeg" },
|
{ "jetty_logo.jpeg", "image/jpeg" },
|
||||||
{ "jetty_logo.jpg" },
|
{ "jetty_logo.jpg", "image/jpeg" },
|
||||||
// Lesser encountered images (usually found being requested from non-browser clients)
|
// Lesser encountered images (usually found being requested from non-browser clients)
|
||||||
{ "jetty_logo.bmp" },
|
{ "jetty_logo.bmp", "image/bmp" },
|
||||||
{ "jetty_logo.tga" },
|
{ "jetty_logo.tga", "application/tga" },
|
||||||
{ "jetty_logo.tif" },
|
{ "jetty_logo.tif", "image/tiff" },
|
||||||
{ "jetty_logo.tiff" },
|
{ "jetty_logo.tiff", "image/tiff" },
|
||||||
{ "jetty_logo.xcf" },
|
{ "jetty_logo.xcf", "image/xcf" },
|
||||||
{ "jetty_logo.jp2" } });
|
{ "jetty_logo.jp2", "image/jpeg2000" } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public TestingDir testingdir = new TestingDir();
|
public TestingDir testingdir = new TestingDir();
|
||||||
|
|
||||||
private String alreadyCompressedFilename;
|
private String alreadyCompressedFilename;
|
||||||
|
private String expectedContentType;
|
||||||
public GzipFilterDefaultNoRecompressTest(String testFilename) {
|
|
||||||
|
public GzipFilterDefaultNoRecompressTest(String testFilename, String expectedContentType)
|
||||||
|
{
|
||||||
this.alreadyCompressedFilename = testFilename;
|
this.alreadyCompressedFilename = testFilename;
|
||||||
|
this.expectedContentType = expectedContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("Cannot find a configuration that would allow this to pass")
|
|
||||||
public void testNotGzipFiltered_Default_AlreadyCompressed() throws Exception
|
public void testNotGzipFiltered_Default_AlreadyCompressed() throws Exception
|
||||||
{
|
{
|
||||||
GzipTester tester = new GzipTester(testingdir);
|
GzipTester tester = new GzipTester(testingdir);
|
||||||
|
|
||||||
copyTestFileToServer(alreadyCompressedFilename);
|
copyTestFileToServer(alreadyCompressedFilename);
|
||||||
|
|
||||||
// Using DefaultServlet, with default GzipFilter setup
|
FilterHolder holder = tester.setContentServlet(TestStaticMimeTypeServlet.class);
|
||||||
FilterHolder holder = tester.setContentServlet(DefaultServlet.class);
|
|
||||||
// TODO: find a configuration of the GzipFilter to allow
|
|
||||||
// each of these test cases to pass.
|
|
||||||
|
|
||||||
StringBuilder mimeTypes = new StringBuilder();
|
StringBuilder mimeTypes = new StringBuilder();
|
||||||
mimeTypes.append("images/png");
|
mimeTypes.append("text/plain");
|
||||||
mimeTypes.append(",images/jpeg");
|
holder.setInitParameter("mimeTypes",mimeTypes.toString());
|
||||||
mimeTypes.append(",images/gif");
|
|
||||||
mimeTypes.append(",images/jp2");
|
|
||||||
|
|
||||||
holder.setInitParameter("mimeTypes", mimeTypes.toString());
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tester.start();
|
tester.start();
|
||||||
tester.assertIsResponseNotGzipFiltered(alreadyCompressedFilename,
|
tester.assertIsResponseNotGzipFiltered(alreadyCompressedFilename,alreadyCompressedFilename + ".sha1",expectedContentType);
|
||||||
alreadyCompressedFilename + ".sha1");
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
|
@ -113,8 +113,9 @@ public class GzipTester
|
||||||
* @param testResourceSha1Sum
|
* @param testResourceSha1Sum
|
||||||
* the sha1sum file that contains the SHA1SUM checksum that will be used to verify that the response
|
* the sha1sum file that contains the SHA1SUM checksum that will be used to verify that the response
|
||||||
* contents are what is intended.
|
* contents are what is intended.
|
||||||
|
* @param expectedContentType
|
||||||
*/
|
*/
|
||||||
public void assertIsResponseNotGzipFiltered(String requestedFilename, String testResourceSha1Sum) throws Exception
|
public void assertIsResponseNotGzipFiltered(String requestedFilename, String testResourceSha1Sum, String expectedContentType) throws Exception
|
||||||
{
|
{
|
||||||
System.err.printf("[GzipTester] requesting /context/%s%n",requestedFilename);
|
System.err.printf("[GzipTester] requesting /context/%s%n",requestedFilename);
|
||||||
HttpTester request = new HttpTester();
|
HttpTester request = new HttpTester();
|
||||||
|
@ -135,13 +136,13 @@ public class GzipTester
|
||||||
dumpHeaders(requestedFilename + " / Response Headers",response);
|
dumpHeaders(requestedFilename + " / Response Headers",response);
|
||||||
|
|
||||||
// Assert the response headers
|
// Assert the response headers
|
||||||
Assert.assertThat(requestedFilename + " / Response.method",response.getMethod(),nullValue());
|
String prefix = requestedFilename + " / Response";
|
||||||
Assert.assertThat(requestedFilename + " / Response.status",response.getStatus(),is(HttpServletResponse.SC_OK));
|
Assert.assertThat(prefix + ".method",response.getMethod(),nullValue());
|
||||||
Assert.assertThat(requestedFilename + " / Response.header[Content-Length]",response.getHeader("Content-Length"),notNullValue());
|
Assert.assertThat(prefix + ".status",response.getStatus(),is(HttpServletResponse.SC_OK));
|
||||||
Assert.assertThat(requestedFilename + " / Response.header[Content-Encoding] (should not be recompressed by GzipFilter)",
|
Assert.assertThat(prefix + ".header[Content-Length]",response.getHeader("Content-Length"),notNullValue());
|
||||||
response.getHeader("Content-Encoding"),nullValue());
|
Assert.assertThat(prefix + ".header[Content-Encoding] (should not be recompressed by GzipFilter)",response.getHeader("Content-Encoding"),nullValue());
|
||||||
Assert.assertThat(requestedFilename + " / Response.header[Content-Type] (should have a Content-Type associated with it)",
|
Assert.assertThat(prefix + ".header[Content-Type] (should have a Content-Type associated with it)",response.getHeader("Content-Type"),notNullValue());
|
||||||
response.getHeader("Content-Type"),notNullValue());
|
Assert.assertThat(prefix + ".header[Content-Type]",response.getHeader("Content-Type"),is(expectedContentType));
|
||||||
|
|
||||||
ByteArrayInputStream bais = null;
|
ByteArrayInputStream bais = null;
|
||||||
DigestOutputStream digester = null;
|
DigestOutputStream digester = null;
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
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) set content length
|
||||||
|
* 2) get stream
|
||||||
|
* 3) set content type
|
||||||
|
* 4) write
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class TestServletLengthStreamTypeWrite extends TestDirContentServlet
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
String fileName = request.getServletPath();
|
||||||
|
byte[] dataBytes = loadContentFileBytes(fileName);
|
||||||
|
|
||||||
|
response.setContentLength(dataBytes.length);
|
||||||
|
|
||||||
|
ServletOutputStream out = response.getOutputStream();
|
||||||
|
|
||||||
|
if (fileName.endsWith("txt"))
|
||||||
|
response.setContentType("text/plain");
|
||||||
|
else if (fileName.endsWith("mp3"))
|
||||||
|
response.setContentType("audio/mpeg");
|
||||||
|
|
||||||
|
out.write(dataBytes);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
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) set content type
|
||||||
|
* 2) get stream
|
||||||
|
* 3) set content length
|
||||||
|
* 4) write
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class TestServletTypeStreamLengthWrite extends TestDirContentServlet
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
String fileName = request.getServletPath();
|
||||||
|
byte[] dataBytes = loadContentFileBytes(fileName);
|
||||||
|
|
||||||
|
if (fileName.endsWith("txt"))
|
||||||
|
response.setContentType("text/plain");
|
||||||
|
else if (fileName.endsWith("mp3"))
|
||||||
|
response.setContentType("audio/mpeg");
|
||||||
|
|
||||||
|
ServletOutputStream out = response.getOutputStream();
|
||||||
|
|
||||||
|
response.setContentLength(dataBytes.length);
|
||||||
|
|
||||||
|
out.write(dataBytes);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package org.eclipse.jetty.servlets.gzip;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletOutputStream;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
|
import org.eclipse.jetty.io.Buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test servlet for testing against unusual MimeTypes and Content-Types.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class TestStaticMimeTypeServlet extends TestDirContentServlet
|
||||||
|
{
|
||||||
|
private MimeTypes mimeTypes;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ServletConfig config) throws ServletException
|
||||||
|
{
|
||||||
|
super.init(config);
|
||||||
|
mimeTypes = new MimeTypes();
|
||||||
|
// Some real world, yet not terribly common, mime type mappings.
|
||||||
|
mimeTypes.addMimeMapping("bz2","application/bzip2");
|
||||||
|
mimeTypes.addMimeMapping("bmp","image/bmp");
|
||||||
|
mimeTypes.addMimeMapping("tga","application/tga");
|
||||||
|
mimeTypes.addMimeMapping("xcf","image/xcf");
|
||||||
|
mimeTypes.addMimeMapping("jp2","image/jpeg2000");
|
||||||
|
|
||||||
|
// Some of the other gzip mime-types seen in the wild.
|
||||||
|
// NOTE: Using oddball extensions just so that the calling request can specify
|
||||||
|
// which strange mime type to use.
|
||||||
|
mimeTypes.addMimeMapping("x-gzip","application/x-gzip");
|
||||||
|
mimeTypes.addMimeMapping("x-gunzip","application/x-gunzip");
|
||||||
|
mimeTypes.addMimeMapping("gzipped","application/gzippped");
|
||||||
|
mimeTypes.addMimeMapping("gzip-compressed","application/gzip-compressed");
|
||||||
|
mimeTypes.addMimeMapping("x-compressed","application/x-compressed");
|
||||||
|
mimeTypes.addMimeMapping("x-compress","application/x-compress");
|
||||||
|
mimeTypes.addMimeMapping("gzipdoc","gzip/document");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
String fileName = request.getServletPath();
|
||||||
|
byte[] dataBytes = loadContentFileBytes(fileName);
|
||||||
|
|
||||||
|
response.setContentLength(dataBytes.length);
|
||||||
|
|
||||||
|
Buffer buf = mimeTypes.getMimeByExtension(fileName);
|
||||||
|
if (buf == null)
|
||||||
|
{
|
||||||
|
response.setContentType("application/octet-stream");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.setContentType(buf.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
ServletOutputStream out = response.getOutputStream();
|
||||||
|
out.write(dataBytes);
|
||||||
|
}
|
||||||
|
}
|
|
@ -228,7 +228,7 @@ public class TestClient implements WebSocket.OnFrame
|
||||||
__start=System.currentTimeMillis();
|
__start=System.currentTimeMillis();
|
||||||
for (int i=0;i<clients;i++)
|
for (int i=0;i<clients;i++)
|
||||||
{
|
{
|
||||||
client[i]=new TestClient(host,port,protocol==null?null:protocol,10000);
|
client[i]=new TestClient(host,port,protocol==null?null:protocol,60000);
|
||||||
client[i].open();
|
client[i].open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ public interface WebSocketConnection extends Connection
|
||||||
{
|
{
|
||||||
void fillBuffersFrom(Buffer buffer);
|
void fillBuffersFrom(Buffer buffer);
|
||||||
|
|
||||||
void handshake(HttpServletRequest request, HttpServletResponse response, String origin, String subprotocol) throws IOException;
|
void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException;
|
||||||
|
|
||||||
List<Extension> getExtensions();
|
List<Extension> getExtensions();
|
||||||
|
|
||||||
|
|
|
@ -362,7 +362,7 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
||||||
void access(EndPoint endp);
|
void access(EndPoint endp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String origin, String subprotocol) throws IOException
|
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||||
{
|
{
|
||||||
String uri=request.getRequestURI();
|
String uri=request.getRequestURI();
|
||||||
String query=request.getQueryString();
|
String query=request.getQueryString();
|
||||||
|
@ -370,7 +370,9 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
|
||||||
uri+="?"+query;
|
uri+="?"+query;
|
||||||
String host=request.getHeader("Host");
|
String host=request.getHeader("Host");
|
||||||
|
|
||||||
|
String origin=request.getHeader("Host");
|
||||||
String key1 = request.getHeader("Sec-WebSocket-Key1");
|
String key1 = request.getHeader("Sec-WebSocket-Key1");
|
||||||
|
|
||||||
if (key1!=null)
|
if (key1!=null)
|
||||||
{
|
{
|
||||||
String key2 = request.getHeader("Sec-WebSocket-Key2");
|
String key2 = request.getHeader("Sec-WebSocket-Key2");
|
||||||
|
|
|
@ -710,7 +710,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String origin, String subprotocol) throws IOException
|
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||||
{
|
{
|
||||||
String uri=request.getRequestURI();
|
String uri=request.getRequestURI();
|
||||||
String query=request.getQueryString();
|
String query=request.getQueryString();
|
||||||
|
|
|
@ -90,7 +90,8 @@ public class WebSocketConnectionD10 extends AbstractConnection implements WebSoc
|
||||||
private final String _protocol;
|
private final String _protocol;
|
||||||
private final int _draft;
|
private final int _draft;
|
||||||
private final ClassLoader _context;
|
private final ClassLoader _context;
|
||||||
private int _close;
|
private volatile int _closeCode;
|
||||||
|
private volatile String _closeMessage;
|
||||||
private volatile boolean _closedIn;
|
private volatile boolean _closedIn;
|
||||||
private volatile boolean _closedOut;
|
private volatile boolean _closedOut;
|
||||||
private int _maxTextMessageSize;
|
private int _maxTextMessageSize;
|
||||||
|
@ -275,7 +276,8 @@ public class WebSocketConnectionD10 extends AbstractConnection implements WebSoc
|
||||||
@Override
|
@Override
|
||||||
public void idleExpired()
|
public void idleExpired()
|
||||||
{
|
{
|
||||||
closeOut(WebSocketConnectionD10.CLOSE_NORMAL,"Idle");
|
long idle = System.currentTimeMillis()-((SelectChannelEndPoint)_endp).getIdleTimestamp();
|
||||||
|
closeOut(WebSocketConnectionD10.CLOSE_NORMAL,"Idle for "+idle+"ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
@ -290,9 +292,9 @@ public class WebSocketConnectionD10 extends AbstractConnection implements WebSoc
|
||||||
final boolean closed;
|
final boolean closed;
|
||||||
synchronized (this)
|
synchronized (this)
|
||||||
{
|
{
|
||||||
closed=_close==0;
|
closed=_closeCode==0;
|
||||||
if (closed)
|
if (closed)
|
||||||
_close=WebSocketConnectionD10.CLOSE_NOCLOSE;
|
_closeCode=WebSocketConnectionD10.CLOSE_NOCLOSE;
|
||||||
}
|
}
|
||||||
if (closed)
|
if (closed)
|
||||||
_webSocket.onClose(WebSocketConnectionD10.CLOSE_NOCLOSE,"closed");
|
_webSocket.onClose(WebSocketConnectionD10.CLOSE_NOCLOSE,"closed");
|
||||||
|
@ -309,9 +311,12 @@ public class WebSocketConnectionD10 extends AbstractConnection implements WebSoc
|
||||||
{
|
{
|
||||||
closedOut=_closedOut;
|
closedOut=_closedOut;
|
||||||
_closedIn=true;
|
_closedIn=true;
|
||||||
closed=_close==0;
|
closed=_closeCode==0;
|
||||||
if (closed)
|
if (closed)
|
||||||
_close=code;
|
{
|
||||||
|
_closeCode=code;
|
||||||
|
_closeMessage=message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -346,9 +351,12 @@ public class WebSocketConnectionD10 extends AbstractConnection implements WebSoc
|
||||||
{
|
{
|
||||||
close=_closedIn || _closedOut;
|
close=_closedIn || _closedOut;
|
||||||
_closedOut=true;
|
_closedOut=true;
|
||||||
closed=_close==0;
|
closed=_closeCode==0;
|
||||||
if (closed)
|
if (closed)
|
||||||
_close=code;
|
{
|
||||||
|
_closeCode=code;
|
||||||
|
_closeMessage=message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -409,7 +417,7 @@ public class WebSocketConnectionD10 extends AbstractConnection implements WebSoc
|
||||||
public void sendMessage(String content) throws IOException
|
public void sendMessage(String content) throws IOException
|
||||||
{
|
{
|
||||||
if (_closedOut)
|
if (_closedOut)
|
||||||
throw new IOException("closing");
|
throw new IOException("closedOut "+_closeCode+":"+_closeMessage);
|
||||||
byte[] data = content.getBytes(StringUtil.__UTF8);
|
byte[] data = content.getBytes(StringUtil.__UTF8);
|
||||||
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionD10.OP_TEXT,data,0,data.length);
|
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionD10.OP_TEXT,data,0,data.length);
|
||||||
checkWriteable();
|
checkWriteable();
|
||||||
|
@ -420,7 +428,7 @@ public class WebSocketConnectionD10 extends AbstractConnection implements WebSoc
|
||||||
public void sendMessage(byte[] content, int offset, int length) throws IOException
|
public void sendMessage(byte[] content, int offset, int length) throws IOException
|
||||||
{
|
{
|
||||||
if (_closedOut)
|
if (_closedOut)
|
||||||
throw new IOException("closing");
|
throw new IOException("closedOut "+_closeCode+":"+_closeMessage);
|
||||||
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionD10.OP_BINARY,content,offset,length);
|
_outbound.addFrame((byte)FLAG_FIN,WebSocketConnectionD10.OP_BINARY,content,offset,length);
|
||||||
checkWriteable();
|
checkWriteable();
|
||||||
_idle.access(_endp);
|
_idle.access(_endp);
|
||||||
|
@ -430,7 +438,7 @@ public class WebSocketConnectionD10 extends AbstractConnection implements WebSoc
|
||||||
public void sendFrame(byte flags,byte opcode, byte[] content, int offset, int length) throws IOException
|
public void sendFrame(byte flags,byte opcode, byte[] content, int offset, int length) throws IOException
|
||||||
{
|
{
|
||||||
if (_closedOut)
|
if (_closedOut)
|
||||||
throw new IOException("closing");
|
throw new IOException("closedOut "+_closeCode+":"+_closeMessage);
|
||||||
_outbound.addFrame(flags,opcode,content,offset,length);
|
_outbound.addFrame(flags,opcode,content,offset,length);
|
||||||
checkWriteable();
|
checkWriteable();
|
||||||
_idle.access(_endp);
|
_idle.access(_endp);
|
||||||
|
@ -440,7 +448,7 @@ public class WebSocketConnectionD10 extends AbstractConnection implements WebSoc
|
||||||
public void sendControl(byte ctrl, byte[] data, int offset, int length) throws IOException
|
public void sendControl(byte ctrl, byte[] data, int offset, int length) throws IOException
|
||||||
{
|
{
|
||||||
if (_closedOut)
|
if (_closedOut)
|
||||||
throw new IOException("closing");
|
throw new IOException("closedOut "+_closeCode+":"+_closeMessage);
|
||||||
_outbound.addFrame((byte)FLAG_FIN,ctrl,data,offset,length);
|
_outbound.addFrame((byte)FLAG_FIN,ctrl,data,offset,length);
|
||||||
checkWriteable();
|
checkWriteable();
|
||||||
_idle.access(_endp);
|
_idle.access(_endp);
|
||||||
|
@ -798,7 +806,7 @@ public class WebSocketConnectionD10 extends AbstractConnection implements WebSoc
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
public void handshake(HttpServletRequest request, HttpServletResponse response, String origin, String subprotocol) throws IOException
|
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
|
||||||
{
|
{
|
||||||
String uri=request.getRequestURI();
|
String uri=request.getRequestURI();
|
||||||
String query=request.getQueryString();
|
String query=request.getQueryString();
|
||||||
|
|
|
@ -38,9 +38,21 @@ public class WebSocketFactory
|
||||||
{
|
{
|
||||||
public interface Acceptor
|
public interface Acceptor
|
||||||
{
|
{
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param request
|
||||||
|
* @param protocol
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
WebSocket doWebSocketConnect(HttpServletRequest request, String protocol);
|
WebSocket doWebSocketConnect(HttpServletRequest request, String protocol);
|
||||||
|
|
||||||
String checkOrigin(HttpServletRequest request, String host, String origin);
|
/* ------------------------------------------------------------ */
|
||||||
|
/** Check the origin of an incoming WebSocket handshake request
|
||||||
|
* @param request
|
||||||
|
* @param origin
|
||||||
|
* @return boolean to indicate that the origin is acceptable.
|
||||||
|
*/
|
||||||
|
boolean checkOrigin(HttpServletRequest request, String origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String,Class<? extends Extension>> _extensionClasses = new HashMap<String, Class<? extends Extension>>();
|
private final Map<String,Class<? extends Extension>> _extensionClasses = new HashMap<String, Class<? extends Extension>>();
|
||||||
|
@ -128,7 +140,7 @@ public class WebSocketFactory
|
||||||
* @param protocol The websocket protocol
|
* @param protocol The websocket protocol
|
||||||
* @throws IOException in case of I/O errors
|
* @throws IOException in case of I/O errors
|
||||||
*/
|
*/
|
||||||
public void upgrade(HttpServletRequest request, HttpServletResponse response, WebSocket websocket, String origin, String protocol)
|
public void upgrade(HttpServletRequest request, HttpServletResponse response, WebSocket websocket, String protocol)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
if (!"websocket".equalsIgnoreCase(request.getHeader("Upgrade")))
|
if (!"websocket".equalsIgnoreCase(request.getHeader("Upgrade")))
|
||||||
|
@ -176,7 +188,7 @@ public class WebSocketFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the connection finish processing the handshake
|
// Let the connection finish processing the handshake
|
||||||
connection.handshake(request, response, origin, protocol);
|
connection.handshake(request, response, protocol);
|
||||||
response.flushBuffer();
|
response.flushBuffer();
|
||||||
|
|
||||||
// Give the connection any unused data from the HTTP connection.
|
// Give the connection any unused data from the HTTP connection.
|
||||||
|
@ -205,11 +217,20 @@ public class WebSocketFactory
|
||||||
{
|
{
|
||||||
if ("websocket".equalsIgnoreCase(request.getHeader("Upgrade")))
|
if ("websocket".equalsIgnoreCase(request.getHeader("Upgrade")))
|
||||||
{
|
{
|
||||||
|
String origin = request.getHeader("Sec-WebSocket-Origin");
|
||||||
|
if (origin==null)
|
||||||
|
origin = request.getHeader("Origin");
|
||||||
|
if (!_acceptor.checkOrigin(request,origin))
|
||||||
|
{
|
||||||
|
response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try each requested protocol
|
||||||
|
WebSocket websocket = null;
|
||||||
String protocol = request.getHeader("Sec-WebSocket-Protocol");
|
String protocol = request.getHeader("Sec-WebSocket-Protocol");
|
||||||
if (protocol == null) // TODO remove once draft period is over
|
if (protocol == null) // TODO remove once draft period is over
|
||||||
protocol = request.getHeader("WebSocket-Protocol");
|
protocol = request.getHeader("WebSocket-Protocol");
|
||||||
|
|
||||||
WebSocket websocket = null;
|
|
||||||
for (String p : parseProtocols(protocol))
|
for (String p : parseProtocols(protocol))
|
||||||
{
|
{
|
||||||
websocket = _acceptor.doWebSocketConnect(request, p);
|
websocket = _acceptor.doWebSocketConnect(request, p);
|
||||||
|
@ -220,17 +241,16 @@ public class WebSocketFactory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String host = request.getHeader("Host");
|
// Did we get a websocket?
|
||||||
String origin = request.getHeader("Origin");
|
if (websocket == null)
|
||||||
origin = _acceptor.checkOrigin(request, host, origin);
|
|
||||||
|
|
||||||
if (websocket != null)
|
|
||||||
{
|
{
|
||||||
upgrade(request, response, websocket, origin, protocol);
|
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
|
// Send the upgrade
|
||||||
|
upgrade(request, response, websocket, protocol);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -100,11 +100,9 @@ public abstract class WebSocketHandler extends HandlerWrapper implements WebSock
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
public String checkOrigin(HttpServletRequest request, String host, String origin)
|
public boolean checkOrigin(HttpServletRequest request, String origin)
|
||||||
{
|
{
|
||||||
if (origin==null)
|
return true;
|
||||||
origin=host;
|
|
||||||
return origin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package org.eclipse.jetty.websocket;
|
package org.eclipse.jetty.websocket;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServlet;
|
import javax.servlet.http.HttpServlet;
|
||||||
|
@ -65,11 +67,10 @@ public abstract class WebSocketServlet extends HttpServlet implements WebSocketF
|
||||||
super.service(request,response);
|
super.service(request,response);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String checkOrigin(HttpServletRequest request, String host, String origin)
|
/* ------------------------------------------------------------ */
|
||||||
|
public boolean checkOrigin(HttpServletRequest request, String origin)
|
||||||
{
|
{
|
||||||
if (origin==null)
|
return true;
|
||||||
origin=host;
|
|
||||||
return origin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -745,7 +745,7 @@ public class WebSocketMessageD10Test
|
||||||
lookFor("sent on connect",input);
|
lookFor("sent on connect",input);
|
||||||
|
|
||||||
assertEquals((byte)0x88,(byte)input.read());
|
assertEquals((byte)0x88,(byte)input.read());
|
||||||
assertEquals(0x06,input.read());
|
assertEquals(17,input.read());
|
||||||
assertEquals(1000/0x100,input.read());
|
assertEquals(1000/0x100,input.read());
|
||||||
assertEquals(1000%0x100,input.read());
|
assertEquals(1000%0x100,input.read());
|
||||||
lookFor("Idle",input);
|
lookFor("Idle",input);
|
||||||
|
|
Loading…
Reference in New Issue