Merge remote-tracking branch 'origin/jetty-9.4.x' into issue-207
This commit is contained in:
commit
849ad7c917
111
VERSION.txt
111
VERSION.txt
|
@ -1,4 +1,106 @@
|
||||||
jetty-9.4.3-SNAPSHOT
|
jetty-9.4.5-SNAPSHOT
|
||||||
|
|
||||||
|
jetty-9.4.4.v20170414 - 14 April 2017
|
||||||
|
+ 612 Support HTTP Trailer
|
||||||
|
+ 877 Programmatic servlet mappings cannot override mappings from
|
||||||
|
webdefault.xml using quickstart
|
||||||
|
+ 1201 X-Forwarded-For incorrectly set in jetty-http-forwarded.xml
|
||||||
|
+ 1334 Dispatcher.commitResponse() failure is unreported
|
||||||
|
+ 1386 Optimise session writes
|
||||||
|
+ 1411 Use short-circuit operator in websocket Frame
|
||||||
|
+ 1417 Improve classloader dumping
|
||||||
|
+ 1418 setWriteListener causes race
|
||||||
|
+ 1423 Update to gcloud datastore 0.10.0-beta
|
||||||
|
+ 1433 Wrong status message for code 417
|
||||||
|
+ 1434 Improve properties in jetty-gzip.xml
|
||||||
|
+ 1435 Apply setCharacterEncoding to static content without an assumed encoding
|
||||||
|
+ 1436 NullPointerException when calling changeSessionId
|
||||||
|
+ 1439 Allow UNC paths to function as Resource bases
|
||||||
|
+ 1440 Improve lock contention for low resources scheduling strategy
|
||||||
|
+ 1444 Deprecate Continuations
|
||||||
|
+ 1448 StackOverflowError when using URLStreamHandlerFactory in
|
||||||
|
WebAppClassloader
|
||||||
|
+ 1449 Unable to find the JVM Lib directory in WebAppContext
|
||||||
|
+ 1450 JMX does not export session statistics
|
||||||
|
+ 1452 Add tests for [want|need]ClientAuth
|
||||||
|
+ 1454 CachedContentFactory locks filesystem after first read of file
|
||||||
|
+ 1456 Error dispatch race with async write
|
||||||
|
+ 1463 SSL Renegotiate limit
|
||||||
|
+ 1466 Only use ServletContainerInitializers from server path for web.xml <
|
||||||
|
3.0
|
||||||
|
+ 1467 Change default for WebAppContext.isConfiguredDiscovered to false
|
||||||
|
+ 1469 IllegalStateException in RolloverFileOutputStream
|
||||||
|
+ 1472 Broken *.gz symlinks cause NPE in DefaultServlet.
|
||||||
|
+ 1475 SIOOBE in ContextHandler startup
|
||||||
|
|
||||||
|
jetty-9.4.3.v20170317 - 17 March 2017
|
||||||
|
+ 329 Javadoc for HttpTester and ServletTester needs to reference limited HTTP
|
||||||
|
version scope
|
||||||
|
+ 609 websocket ClientCloseTest testServerNoCloseHandshake is failing
|
||||||
|
+ 856 Add server/port and auth configuration for mongo sessions
|
||||||
|
+ 1015 Ensure jetty-distribution excludes git / temp files
|
||||||
|
+ 1049 test-jetty-osgi test exits/crashes the surefire forked JVM
|
||||||
|
+ 1184 IllegalStateException for HEAD requests responded with 404
|
||||||
|
+ 1340 PushCacheFilter question
|
||||||
|
+ 1351 StringIndexOutOfBoundsException thrown on incomplete Accept-Language
|
||||||
|
header
|
||||||
|
+ 1353 A Large ClasspathPattern results in infinite loop
|
||||||
|
+ 1357 RolloverFileOutputStream: No rollout performed at midnight
|
||||||
|
+ 1363 HttpInput.read deadlock (async mode)
|
||||||
|
+ 1374 When `Server.start` fails, beans ought to be stopped
|
||||||
|
+ 1375 Support pushed resources in HTTP client
|
||||||
|
+ 1378 Slow TLS clients may hang the server
|
||||||
|
+ 1379 Misleading javadoc for initialization of SessionIdPathParameterName
|
||||||
|
+ 1383 javadoc build on JDK 8u121 fails due to scripts
|
||||||
|
+ 1384 Expose StatisticsServlet to webapp
|
||||||
|
+ 1387 Windows and paxexam failure due to "renaming bundle"
|
||||||
|
+ 1389 Update to gcloud datastore-0.9.4-beta
|
||||||
|
+ 1390 HashLoginService and "this.web-inf.url" property are incompatible
|
||||||
|
+ 1394 Default OS Locale/Encoding/Charset can cause test failures
|
||||||
|
+ 1396 Set-Cookie produced by Jetty is invalid for RFC6265 and Chrome
|
||||||
|
+ 1398 Ensure all SessionDataStores store lastsaved time
|
||||||
|
+ 1399 SlowClientTest is failing on CI
|
||||||
|
+ 1401 HttpOutput.recycle() does not clear the write listener
|
||||||
|
+ 1402 Move RFC syntax validation to jetty-http Syntax class
|
||||||
|
+ 1403 Move new CookieCompliance class to jetty-http
|
||||||
|
+ 1405 Cookie name cannot be blank or null
|
||||||
|
|
||||||
|
jetty-9.3.18.v20170406 - 06 April 2017
|
||||||
|
+ 877 Programmatic servlet mappings cannot override mappings from
|
||||||
|
webdefault.xml using quickstart
|
||||||
|
+ 1201 X-Forwarded-For incorrectly set in jetty-http-forwarded.xml
|
||||||
|
+ 1417 Improve classloader dumping
|
||||||
|
+ 1439 Allow UNC paths to function as Resource bases
|
||||||
|
|
||||||
|
jetty-9.3.17.v20170317 - 17 March 2017
|
||||||
|
+ 329 Javadoc for HttpTester and ServletTester needs to reference limited HTTP
|
||||||
|
version scope
|
||||||
|
+ 609 websocket ClientCloseTest testServerNoCloseHandshake is failing
|
||||||
|
+ 1015 Ensure jetty-distribution excludes git / temp files
|
||||||
|
+ 1047 ReadPendingException and then thread death
|
||||||
|
+ 1049 test-jetty-osgi test exits/crashes the surefire forked JVM
|
||||||
|
+ 1282 ByteArrayEndPointTest.testIdle() failure
|
||||||
|
+ 1296 Introduce HTTP parser "content complete" event
|
||||||
|
+ 1326 Jetty shutdown command got NullPointerException (http2 module added to
|
||||||
|
start)
|
||||||
|
+ 1328 Response.setBufferSize(int) ISE should be more clear on reason
|
||||||
|
+ 1340 PushCacheFilter question
|
||||||
|
+ 1342 Improve ByteBufferPool scalability
|
||||||
|
+ 1351 StringIndexOutOfBoundsException thrown on incomplete Accept-Language
|
||||||
|
header
|
||||||
|
+ 1357 RolloverFileOutputStream: No rollout performed at midnight
|
||||||
|
+ 1374 When `Server.start` fails, beans ought to be stopped
|
||||||
|
+ 1375 Support pushed resources in HTTP client
|
||||||
|
+ 1378 Slow TLS clients may hang the server
|
||||||
|
+ 1383 javadoc build on JDK 8u121 fails due to scripts
|
||||||
|
+ 1384 Expose StatisticsServlet to webapp
|
||||||
|
+ 1387 Windows and paxexam failure due to "renaming bundle"
|
||||||
|
+ 1389 Update to gcloud datastore-0.9.4-beta
|
||||||
|
+ 1390 HashLoginService and "this.web-inf.url" property are incompatible
|
||||||
|
+ 1394 Default OS Locale/Encoding/Charset can cause test failures
|
||||||
|
+ 1396 Set-Cookie produced by Jetty is invalid for RFC6265 and Chrome
|
||||||
|
+ 1399 SlowClientTest is failing on CI
|
||||||
|
+ 1401 HttpOutput.recycle() does not clear the write listener
|
||||||
|
|
||||||
jetty-9.4.2.v20170220 - 20 February 2017
|
jetty-9.4.2.v20170220 - 20 February 2017
|
||||||
+ 612 Support HTTP Trailer
|
+ 612 Support HTTP Trailer
|
||||||
|
@ -206,6 +308,13 @@ jetty-9.3.15.v20161220 - 20 December 2016
|
||||||
+ 1186 Where can i find SocketConnector .java and
|
+ 1186 Where can i find SocketConnector .java and
|
||||||
BlockingChannelConnector.java etc?
|
BlockingChannelConnector.java etc?
|
||||||
|
|
||||||
|
jetty-9.2.21.v20170120 - 20 January 2017
|
||||||
|
+ 592 Support no-value Host header in HttpParser
|
||||||
|
+ 1229 ClassLoader constraint issue when using NativeWebSocketConfiguration
|
||||||
|
with WEB-INF/lib/jetty-http.jar present
|
||||||
|
+ 1267 Request.getRemoteUser can throw undeclared IllegalStateException via
|
||||||
|
DeferredAuthentication & FormAuthenticator
|
||||||
|
|
||||||
jetty-9.4.0.RC3 - 05 December 2016
|
jetty-9.4.0.RC3 - 05 December 2016
|
||||||
+ 1051 NCSARequestLog/RolloverFileOutputStream does not roll day after DST
|
+ 1051 NCSARequestLog/RolloverFileOutputStream does not roll day after DST
|
||||||
ends
|
ends
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>apache-jsp</artifactId>
|
<artifactId>apache-jsp</artifactId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>apache-jstl</artifactId>
|
<artifactId>apache-jstl</artifactId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>example-async-rest</artifactId>
|
<artifactId>example-async-rest</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.eclipse.jetty.example-async-rest</groupId>
|
<groupId>org.eclipse.jetty.example-async-rest</groupId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>example-async-rest</artifactId>
|
<artifactId>example-async-rest</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.eclipse.jetty.example-async-rest</groupId>
|
<groupId>org.eclipse.jetty.example-async-rest</groupId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.examples</groupId>
|
<groupId>org.eclipse.jetty.examples</groupId>
|
||||||
<artifactId>examples-parent</artifactId>
|
<artifactId>examples-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.examples</groupId>
|
<groupId>org.eclipse.jetty.examples</groupId>
|
||||||
<artifactId>examples-parent</artifactId>
|
<artifactId>examples-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -111,8 +111,7 @@ public class FastFileServer
|
||||||
{
|
{
|
||||||
if (!request.getPathInfo().endsWith(URIUtil.SLASH))
|
if (!request.getPathInfo().endsWith(URIUtil.SLASH))
|
||||||
{
|
{
|
||||||
response.sendRedirect(response.encodeRedirectURL(URIUtil
|
response.sendRedirect(response.encodeRedirectURL(request.getRequestURI()+URIUtil.SLASH));
|
||||||
.addPaths(request.getRequestURI(), URIUtil.SLASH)));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String listing = Resource.newResource(file).getListHTML(
|
String listing = Resource.newResource(file).getListHTML(
|
||||||
|
|
|
@ -58,6 +58,7 @@ public class ManyServletContexts
|
||||||
other.addServlet(new ServletHolder(new HelloServlet("YO!")), "*.yo");
|
other.addServlet(new ServletHolder(new HelloServlet("YO!")), "*.yo");
|
||||||
|
|
||||||
server.start();
|
server.start();
|
||||||
|
server.dumpStdErr();
|
||||||
server.join();
|
server.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import java.io.File;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
|
|
||||||
import org.eclipse.jetty.jmx.MBeanContainer;
|
import org.eclipse.jetty.jmx.MBeanContainer;
|
||||||
import org.eclipse.jetty.security.HashLoginService;
|
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker;
|
import org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker;
|
||||||
import org.eclipse.jetty.webapp.WebAppContext;
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
@ -62,6 +61,8 @@ public class OneWebApp
|
||||||
// Start things up!
|
// Start things up!
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
|
server.dumpStdErr();
|
||||||
|
|
||||||
// The use of server.join() the will make the current thread join and
|
// The use of server.join() the will make the current thread join and
|
||||||
// wait until the server is done executing.
|
// wait until the server is done executing.
|
||||||
// See http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join()
|
// See http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join()
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>org.eclipse.jetty.examples</groupId>
|
<groupId>org.eclipse.jetty.examples</groupId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-alpn-parent</artifactId>
|
<artifactId>jetty-alpn-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-alpn-client</artifactId>
|
<artifactId>jetty-alpn-client</artifactId>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-alpn-parent</artifactId>
|
<artifactId>jetty-alpn-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-alpn-parent</artifactId>
|
<artifactId>jetty-alpn-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-alpn-parent</artifactId>
|
<artifactId>jetty-alpn-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-alpn-server</artifactId>
|
<artifactId>jetty-alpn-server</artifactId>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-alpn-parent</artifactId>
|
<artifactId>jetty-alpn-parent</artifactId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-annotations</artifactId>
|
<artifactId>jetty-annotations</artifactId>
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -344,8 +345,6 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
||||||
{
|
{
|
||||||
context.getObjectFactory().addDecorator(new AnnotationDecorator(context));
|
context.getObjectFactory().addDecorator(new AnnotationDecorator(context));
|
||||||
|
|
||||||
//Even if metadata is complete, we still need to scan for ServletContainerInitializers - if there are any
|
|
||||||
|
|
||||||
if (!context.getMetaData().isMetaDataComplete())
|
if (!context.getMetaData().isMetaDataComplete())
|
||||||
{
|
{
|
||||||
//If metadata isn't complete, if this is a servlet 3 webapp or isConfigDiscovered is true, we need to search for annotations
|
//If metadata isn't complete, if this is a servlet 3 webapp or isConfigDiscovered is true, we need to search for annotations
|
||||||
|
@ -862,6 +861,25 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//final pass over the non-excluded SCIs if the webapp version is < 3, in which case
|
||||||
|
//we will only call SCIs that are on the server's classpath
|
||||||
|
if (context.getServletContext().getEffectiveMajorVersion() < 3 && !context.isConfigurationDiscovered())
|
||||||
|
{
|
||||||
|
ListIterator<ServletContainerInitializer> it = nonExcludedInitializers.listIterator();
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
ServletContainerInitializer sci = it.next();
|
||||||
|
if (!isFromContainerClassPath(context, sci))
|
||||||
|
{
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("Ignoring SCI {}: old web.xml version {}.{}", sci.getClass().getName(),
|
||||||
|
context.getServletContext().getEffectiveMajorVersion(),
|
||||||
|
context.getServletContext().getEffectiveMinorVersion());
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
{
|
{
|
||||||
int i=0;
|
int i=0;
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2017 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.annotations;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContainerInitializer;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServerServletContainerInitializer
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ServerServletContainerInitializer implements ServletContainerInitializer
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public ServerServletContainerInitializer()
|
||||||
|
{
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.servlet.ServletContainerInitializer#onStartup(java.util.Set, javax.servlet.ServletContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,11 +19,20 @@
|
||||||
package org.eclipse.jetty.annotations;
|
package org.eclipse.jetty.annotations;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContainerInitializer;
|
||||||
|
|
||||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||||
import org.eclipse.jetty.util.resource.Resource;
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
@ -38,6 +47,148 @@ import org.junit.Test;
|
||||||
*/
|
*/
|
||||||
public class TestAnnotationConfiguration
|
public class TestAnnotationConfiguration
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public class TestableAnnotationConfiguration extends AnnotationConfiguration
|
||||||
|
{
|
||||||
|
public void assertAnnotationDiscovery (boolean b)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!b)
|
||||||
|
assertTrue(_discoverableAnnotationHandlers.isEmpty());
|
||||||
|
else
|
||||||
|
assertFalse(_discoverableAnnotationHandlers.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAnnotationScanControl() throws Exception
|
||||||
|
{
|
||||||
|
File web25 = MavenTestingUtils.getTestResourceFile("web25.xml");
|
||||||
|
File web31true = MavenTestingUtils.getTestResourceFile("web31true.xml");
|
||||||
|
File web31false = MavenTestingUtils.getTestResourceFile("web31false.xml");
|
||||||
|
|
||||||
|
|
||||||
|
//check that a 2.5 webapp won't discover annotations
|
||||||
|
TestableAnnotationConfiguration config25 = new TestableAnnotationConfiguration();
|
||||||
|
WebAppContext context25 = new WebAppContext();
|
||||||
|
context25.setClassLoader(Thread.currentThread().getContextClassLoader());
|
||||||
|
context25.setAttribute(AnnotationConfiguration.MULTI_THREADED, Boolean.FALSE);
|
||||||
|
context25.setAttribute(AnnotationConfiguration.MAX_SCAN_WAIT, new Integer(0));
|
||||||
|
context25.getMetaData().setWebXml(Resource.newResource(web25));
|
||||||
|
context25.getServletContext().setEffectiveMajorVersion(2);
|
||||||
|
context25.getServletContext().setEffectiveMinorVersion(5);
|
||||||
|
config25.configure(context25);
|
||||||
|
config25.assertAnnotationDiscovery(false);
|
||||||
|
|
||||||
|
//check that a 2.5 webapp with configurationDiscovered will discover annotations
|
||||||
|
TestableAnnotationConfiguration config25b = new TestableAnnotationConfiguration();
|
||||||
|
WebAppContext context25b = new WebAppContext();
|
||||||
|
context25b.setClassLoader(Thread.currentThread().getContextClassLoader());
|
||||||
|
context25b.setAttribute(AnnotationConfiguration.MULTI_THREADED, Boolean.FALSE);
|
||||||
|
context25b.setAttribute(AnnotationConfiguration.MAX_SCAN_WAIT, new Integer(0));
|
||||||
|
context25b.setConfigurationDiscovered(true);
|
||||||
|
context25b.getMetaData().setWebXml(Resource.newResource(web25));
|
||||||
|
context25b.getServletContext().setEffectiveMajorVersion(2);
|
||||||
|
context25b.getServletContext().setEffectiveMinorVersion(5);
|
||||||
|
config25b.configure(context25b);
|
||||||
|
config25b.assertAnnotationDiscovery(true);
|
||||||
|
|
||||||
|
//check that a 3.x webapp with metadata true won't discover annotations
|
||||||
|
TestableAnnotationConfiguration config31 = new TestableAnnotationConfiguration();
|
||||||
|
WebAppContext context31 = new WebAppContext();
|
||||||
|
context31.setClassLoader(Thread.currentThread().getContextClassLoader());
|
||||||
|
context31.setAttribute(AnnotationConfiguration.MULTI_THREADED, Boolean.FALSE);
|
||||||
|
context31.setAttribute(AnnotationConfiguration.MAX_SCAN_WAIT, new Integer(0));
|
||||||
|
context31.getMetaData().setWebXml(Resource.newResource(web31true));
|
||||||
|
context31.getServletContext().setEffectiveMajorVersion(3);
|
||||||
|
context31.getServletContext().setEffectiveMinorVersion(1);
|
||||||
|
config31.configure(context31);
|
||||||
|
config31.assertAnnotationDiscovery(false);
|
||||||
|
|
||||||
|
//check that a 3.x webapp with metadata false will discover annotations
|
||||||
|
TestableAnnotationConfiguration config31b = new TestableAnnotationConfiguration();
|
||||||
|
WebAppContext context31b = new WebAppContext();
|
||||||
|
context31b.setClassLoader(Thread.currentThread().getContextClassLoader());
|
||||||
|
context31b.setAttribute(AnnotationConfiguration.MULTI_THREADED, Boolean.FALSE);
|
||||||
|
context31b.setAttribute(AnnotationConfiguration.MAX_SCAN_WAIT, new Integer(0));
|
||||||
|
context31b.getMetaData().setWebXml(Resource.newResource(web31false));
|
||||||
|
context31b.getServletContext().setEffectiveMajorVersion(3);
|
||||||
|
context31b.getServletContext().setEffectiveMinorVersion(1);
|
||||||
|
config31b.configure(context31b);
|
||||||
|
config31b.assertAnnotationDiscovery(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSCIControl ()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
File web25 = MavenTestingUtils.getTestResourceFile("web25.xml");
|
||||||
|
File web31false = MavenTestingUtils.getTestResourceFile("web31false.xml");
|
||||||
|
File web31true = MavenTestingUtils.getTestResourceFile("web31true.xml");
|
||||||
|
Set<String> sciNames = new HashSet<>(Arrays.asList("org.eclipse.jetty.annotations.ServerServletContainerInitializer", "com.acme.initializer.FooInitializer"));
|
||||||
|
|
||||||
|
//prepare an sci that will be on the webapp's classpath
|
||||||
|
File jarDir = new File(MavenTestingUtils.getTestResourcesDir().getParentFile(), "jar");
|
||||||
|
File testSciJar = new File(jarDir, "test-sci.jar");
|
||||||
|
assertTrue(testSciJar.exists());
|
||||||
|
URLClassLoader webAppLoader = new URLClassLoader(new URL[] {testSciJar.toURI().toURL()}, Thread.currentThread().getContextClassLoader());
|
||||||
|
|
||||||
|
//test 3.1 webapp loads both server and app scis
|
||||||
|
AnnotationConfiguration config = new AnnotationConfiguration();
|
||||||
|
WebAppContext context = new WebAppContext();
|
||||||
|
context.setClassLoader(webAppLoader);
|
||||||
|
context.getMetaData().setWebXml(Resource.newResource(web31true));
|
||||||
|
context.getServletContext().setEffectiveMajorVersion(3);
|
||||||
|
context.getServletContext().setEffectiveMinorVersion(1);
|
||||||
|
List<ServletContainerInitializer> scis = config.getNonExcludedInitializers(context);
|
||||||
|
assertNotNull(scis);
|
||||||
|
assertEquals(2, scis.size());
|
||||||
|
assertTrue (sciNames.contains(scis.get(0).getClass().getName()));
|
||||||
|
assertTrue (sciNames.contains(scis.get(1).getClass().getName()));
|
||||||
|
|
||||||
|
//test a 3.1 webapp with metadata-complete=false loads both server and webapp scis
|
||||||
|
config = new AnnotationConfiguration();
|
||||||
|
context = new WebAppContext();
|
||||||
|
context.setClassLoader(webAppLoader);
|
||||||
|
context.getMetaData().setWebXml(Resource.newResource(web31false));
|
||||||
|
context.getServletContext().setEffectiveMajorVersion(3);
|
||||||
|
context.getServletContext().setEffectiveMinorVersion(1);
|
||||||
|
scis = config.getNonExcludedInitializers(context);
|
||||||
|
assertNotNull(scis);
|
||||||
|
assertEquals(2, scis.size());
|
||||||
|
assertTrue (sciNames.contains(scis.get(0).getClass().getName()));
|
||||||
|
assertTrue (sciNames.contains(scis.get(1).getClass().getName()));
|
||||||
|
|
||||||
|
|
||||||
|
//test 2.5 webapp with configurationDiscovered=false loads only server scis
|
||||||
|
config = new AnnotationConfiguration();
|
||||||
|
context = new WebAppContext();
|
||||||
|
context.setClassLoader(webAppLoader);
|
||||||
|
context.getMetaData().setWebXml(Resource.newResource(web25));
|
||||||
|
context.getServletContext().setEffectiveMajorVersion(2);
|
||||||
|
context.getServletContext().setEffectiveMinorVersion(5);
|
||||||
|
scis = config.getNonExcludedInitializers(context);
|
||||||
|
assertNotNull(scis);
|
||||||
|
assertEquals(1, scis.size());
|
||||||
|
assertTrue ("org.eclipse.jetty.annotations.ServerServletContainerInitializer".equals(scis.get(0).getClass().getName()));
|
||||||
|
|
||||||
|
//test 2.5 webapp with configurationDiscovered=true loads both server and webapp scis
|
||||||
|
config = new AnnotationConfiguration();
|
||||||
|
context = new WebAppContext();
|
||||||
|
context.setConfigurationDiscovered(true);
|
||||||
|
context.setClassLoader(webAppLoader);
|
||||||
|
context.getMetaData().setWebXml(Resource.newResource(web25));
|
||||||
|
context.getServletContext().setEffectiveMajorVersion(2);
|
||||||
|
context.getServletContext().setEffectiveMinorVersion(5);
|
||||||
|
scis = config.getNonExcludedInitializers(context);
|
||||||
|
assertNotNull(scis);
|
||||||
|
assertEquals(2, scis.size());
|
||||||
|
assertTrue (sciNames.contains(scis.get(0).getClass().getName()));
|
||||||
|
assertTrue (sciNames.contains(scis.get(1).getClass().getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetFragmentFromJar() throws Exception
|
public void testGetFragmentFromJar() throws Exception
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
org.eclipse.jetty.annotations.ServerServletContainerInitializer
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<web-app
|
||||||
|
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||||
|
version="2.5">
|
||||||
|
|
||||||
|
<display-name>Test 2.5 WebApp</display-name>
|
||||||
|
|
||||||
|
</web-app>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app
|
||||||
|
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||||
|
metadata-complete="false"
|
||||||
|
version="3.1">
|
||||||
|
|
||||||
|
<display-name>Test 31 WebApp</display-name>
|
||||||
|
|
||||||
|
</web-app>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app
|
||||||
|
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||||
|
metadata-complete="true"
|
||||||
|
version="3.1">
|
||||||
|
|
||||||
|
<display-name>Test 31 WebApp</display-name>
|
||||||
|
|
||||||
|
</web-app>
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-ant</artifactId>
|
<artifactId>jetty-ant</artifactId>
|
||||||
|
|
|
@ -0,0 +1,243 @@
|
||||||
|
<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">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-project</artifactId>
|
||||||
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>jetty-bom</artifactId>
|
||||||
|
<name>Jetty :: Bom</name>
|
||||||
|
<description>Jetty BOM artifact</description>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-annotations</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>cdi-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>cdi-full-servlet</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>cdi-servlet</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>cdi-websocket</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-client</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-continuation</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-gcloud-session-manager</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-home</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-http</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-http-spi</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-infinispan</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-io</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jaas</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jaspi</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jmx</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jndi</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-memcached-sessions</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-monitor</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-nosql</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-osgi-boot</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-osgi-boot-jsp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-osgi-boot-warurl</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-plus</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-proxy</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-quickstart</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-rewrite</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-security</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlet</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-servlets</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>
|
||||||
|
<artifactId>jetty-start</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-unixsocket</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-util</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-util-ajax</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-webapp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>javax-websocket-client-impl</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>javax-websocket-server-impl</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>javax-websocket-api</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>javax-websocket-client</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>javax-websocket-common</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>javax-websocket-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>javax-websocket-servlet</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-xml</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
</project>
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||||
<artifactId>jetty-cdi-parent</artifactId>
|
<artifactId>jetty-cdi-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>cdi-core</artifactId>
|
<artifactId>cdi-core</artifactId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||||
<artifactId>jetty-cdi-parent</artifactId>
|
<artifactId>jetty-cdi-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>cdi-full-servlet</artifactId>
|
<artifactId>cdi-full-servlet</artifactId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||||
<artifactId>jetty-cdi-parent</artifactId>
|
<artifactId>jetty-cdi-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>cdi-servlet</artifactId>
|
<artifactId>cdi-servlet</artifactId>
|
||||||
|
|
|
@ -13,14 +13,13 @@ lib/cdi/
|
||||||
maven://javax.enterprise/cdi-api/1.2|lib/cdi/javax.enterprise.cdi-api-1.2.jar
|
maven://javax.enterprise/cdi-api/1.2|lib/cdi/javax.enterprise.cdi-api-1.2.jar
|
||||||
maven://javax.interceptor/javax.interceptor-api/1.2|lib/cdi/javax.interceptor-api-1.2.jar
|
maven://javax.interceptor/javax.interceptor-api/1.2|lib/cdi/javax.interceptor-api-1.2.jar
|
||||||
maven://javax.inject/javax.inject/1|lib/cdi/javax.inject-1.0.jar
|
maven://javax.inject/javax.inject/1|lib/cdi/javax.inject-1.0.jar
|
||||||
maven://org.jboss.weld.servlet/weld-servlet-core/2.2.9.Final|lib/cdi/weld-servlet-core-2.2.9.Final.jar
|
maven://org.jboss.weld.servlet/weld-servlet-core/2.4.3.Final|lib/cdi/weld-servlet-core-2.4.3.Final.jar
|
||||||
maven://org.jboss.weld.environment/weld-environment-common/2.2.9.Final|lib/cdi/weld-environment-common-2.2.9.Final.jar
|
maven://org.jboss.weld.environment/weld-environment-common/2.4.3.Final|lib/cdi/weld-environment-common-2.4.3.Final.jar
|
||||||
maven://org.jboss.weld/weld-core-impl/2.2.9.Final|lib/cdi/weld-core-impl-2.2.9.Final.jar
|
maven://org.jboss.weld/weld-core-impl/2.4.3.Final|lib/cdi/weld-core-impl-2.4.3.Final.jar
|
||||||
maven://org.jboss.classfilewriter/jboss-classfilewriter/1.0.5.Final|lib/cdi/jboss-classfilewriter-1.0.5.Final.jar
|
maven://org.jboss.classfilewriter/jboss-classfilewriter/1.1.2.Final|lib/cdi/jboss-classfilewriter-1.1.2.Final.jar
|
||||||
maven://com.google.guava/guava/13.0.1|lib/cdi/com.google.guava.guava-13.0.1.jar
|
maven://org.jboss.weld/weld-spi/2.4.SP1|lib/cdi/weld-spi-2.4.SP1.jar
|
||||||
maven://org.jboss.weld/weld-spi/2.2.SP3|lib/cdi/weld-spi-2.2.SP3.jar
|
maven://org.jboss.weld/weld-api/2.4.SP1|lib/cdi/weld-api-2.4.SP1.jar
|
||||||
maven://org.jboss.weld/weld-api/2.2.SP3|lib/cdi/weld-api-2.2.SP3.jar
|
maven://org.jboss.logging/jboss-logging/3.2.1.Final|lib/cdi/jboss-logging-3.2.1.Final.jar
|
||||||
maven://org.jboss.logging/jboss-logging/3.1.3.GA|lib/cdi/jboss-logging-3.1.3.GA.jar
|
|
||||||
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||||
<artifactId>jetty-cdi-parent</artifactId>
|
<artifactId>jetty-cdi-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>cdi-websocket</artifactId>
|
<artifactId>cdi-websocket</artifactId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
<url>http://www.eclipse.org/jetty</url>
|
<url>http://www.eclipse.org/jetty</url>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<properties>
|
<properties>
|
||||||
<weld.version>2.2.9.Final</weld.version>
|
<weld.version>2.4.3.Final</weld.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.cdi</groupId>
|
<groupId>org.eclipse.jetty.cdi</groupId>
|
||||||
<artifactId>jetty-cdi-parent</artifactId>
|
<artifactId>jetty-cdi-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>test-cdi-webapp</artifactId>
|
<artifactId>test-cdi-webapp</artifactId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -41,6 +41,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.api.ContentProvider;
|
import org.eclipse.jetty.client.api.ContentProvider;
|
||||||
import org.eclipse.jetty.client.api.ContentResponse;
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
|
@ -83,6 +84,7 @@ public class HttpRequest implements Request
|
||||||
private Map<String, Object> attributes;
|
private Map<String, Object> attributes;
|
||||||
private List<RequestListener> requestListeners;
|
private List<RequestListener> requestListeners;
|
||||||
private BiFunction<Request, Request, Response.CompleteListener> pushListener;
|
private BiFunction<Request, Request, Response.CompleteListener> pushListener;
|
||||||
|
private Supplier<HttpFields> trailers;
|
||||||
|
|
||||||
protected HttpRequest(HttpClient client, HttpConversation conversation, URI uri)
|
protected HttpRequest(HttpClient client, HttpConversation conversation, URI uri)
|
||||||
{
|
{
|
||||||
|
@ -589,6 +591,12 @@ public class HttpRequest implements Request
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpRequest trailers(Supplier<HttpFields> trailers)
|
||||||
|
{
|
||||||
|
this.trailers = trailers;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ContentProvider getContent()
|
public ContentProvider getContent()
|
||||||
{
|
{
|
||||||
|
@ -725,6 +733,11 @@ public class HttpRequest implements Request
|
||||||
return pushListener;
|
return pushListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Supplier<HttpFields> getTrailers()
|
||||||
|
{
|
||||||
|
return trailers;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean abort(Throwable cause)
|
public boolean abort(Throwable cause)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.api.Request;
|
import org.eclipse.jetty.client.api.Request;
|
||||||
import org.eclipse.jetty.client.api.Response;
|
import org.eclipse.jetty.client.api.Response;
|
||||||
|
import org.eclipse.jetty.http.HttpField;
|
||||||
import org.eclipse.jetty.http.HttpFields;
|
import org.eclipse.jetty.http.HttpFields;
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ public class HttpResponse implements Response
|
||||||
private HttpVersion version;
|
private HttpVersion version;
|
||||||
private int status;
|
private int status;
|
||||||
private String reason;
|
private String reason;
|
||||||
|
private HttpFields trailers;
|
||||||
|
|
||||||
public HttpResponse(Request request, List<ResponseListener> listeners)
|
public HttpResponse(Request request, List<ResponseListener> listeners)
|
||||||
{
|
{
|
||||||
|
@ -97,6 +99,19 @@ public class HttpResponse implements Response
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpFields getTrailers()
|
||||||
|
{
|
||||||
|
return trailers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpResponse trailer(HttpField trailer)
|
||||||
|
{
|
||||||
|
if (trailers == null)
|
||||||
|
trailers = new HttpFields();
|
||||||
|
trailers.add(trailer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean abort(Throwable cause)
|
public boolean abort(Throwable cause)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,10 +20,12 @@ package org.eclipse.jetty.client;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.api.ContentProvider;
|
import org.eclipse.jetty.client.api.ContentProvider;
|
||||||
import org.eclipse.jetty.client.api.Request;
|
import org.eclipse.jetty.client.api.Request;
|
||||||
import org.eclipse.jetty.client.api.Result;
|
import org.eclipse.jetty.client.api.Result;
|
||||||
|
import org.eclipse.jetty.http.HttpFields;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
import org.eclipse.jetty.http.HttpHeaderValue;
|
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
|
@ -31,7 +33,6 @@ import org.eclipse.jetty.util.Callback;
|
||||||
import org.eclipse.jetty.util.IteratingCallback;
|
import org.eclipse.jetty.util.IteratingCallback;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.util.thread.Invocable.InvocationType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link HttpSender} abstracts the algorithm to send HTTP requests, so that subclasses only implement
|
* {@link HttpSender} abstracts the algorithm to send HTTP requests, so that subclasses only implement
|
||||||
|
@ -42,9 +43,9 @@ import org.eclipse.jetty.util.thread.Invocable.InvocationType;
|
||||||
* {@link HttpSender} governs two state machines.
|
* {@link HttpSender} governs two state machines.
|
||||||
* <p>
|
* <p>
|
||||||
* The request state machine is updated by {@link HttpSender} as the various steps of sending a request
|
* The request state machine is updated by {@link HttpSender} as the various steps of sending a request
|
||||||
* are executed, see <code>RequestState</code>.
|
* are executed, see {@code RequestState}.
|
||||||
* At any point in time, a user thread may abort the request, which may (if the request has not been
|
* At any point in time, a user thread may abort the request, which may (if the request has not been
|
||||||
* completely sent yet) move the request state machine to <code>RequestState#FAILURE</code>.
|
* completely sent yet) move the request state machine to {@code RequestState#FAILURE}.
|
||||||
* The request state machine guarantees that the request steps are executed (by I/O threads) only if
|
* The request state machine guarantees that the request steps are executed (by I/O threads) only if
|
||||||
* the request has not been failed already.
|
* the request has not been failed already.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -64,7 +65,8 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
|
||||||
private final AtomicReference<SenderState> senderState = new AtomicReference<>(SenderState.IDLE);
|
private final AtomicReference<SenderState> senderState = new AtomicReference<>(SenderState.IDLE);
|
||||||
private final Callback commitCallback = new CommitCallback();
|
private final Callback commitCallback = new CommitCallback();
|
||||||
private final IteratingCallback contentCallback = new ContentCallback();
|
private final IteratingCallback contentCallback = new ContentCallback();
|
||||||
private final Callback lastCallback = new LastContentCallback();
|
private final Callback trailersCallback = new TrailersCallback();
|
||||||
|
private final Callback lastCallback = new LastCallback();
|
||||||
private final HttpChannel channel;
|
private final HttpChannel channel;
|
||||||
private HttpContent content;
|
private HttpContent content;
|
||||||
private Throwable failure;
|
private Throwable failure;
|
||||||
|
@ -407,7 +409,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
|
||||||
/**
|
/**
|
||||||
* Implementations should send the content at the {@link HttpContent} cursor position over the wire.
|
* Implementations should send the content at the {@link HttpContent} cursor position over the wire.
|
||||||
* <p>
|
* <p>
|
||||||
* The {@link HttpContent} cursor is advanced by {@link HttpSender} at the right time, and if more
|
* The {@link HttpContent} cursor is advanced by HttpSender at the right time, and if more
|
||||||
* content needs to be sent, this method is invoked again; subclasses need only to send the content
|
* content needs to be sent, this method is invoked again; subclasses need only to send the content
|
||||||
* at the {@link HttpContent} cursor position.
|
* at the {@link HttpContent} cursor position.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -422,6 +424,15 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
|
||||||
*/
|
*/
|
||||||
protected abstract void sendContent(HttpExchange exchange, HttpContent content, Callback callback);
|
protected abstract void sendContent(HttpExchange exchange, HttpContent content, Callback callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementations should send the HTTP trailers and notify the given {@code callback} of the
|
||||||
|
* result of this operation.
|
||||||
|
*
|
||||||
|
* @param exchange the exchange to send
|
||||||
|
* @param callback the callback to notify
|
||||||
|
*/
|
||||||
|
protected abstract void sendTrailers(HttpExchange exchange, Callback callback);
|
||||||
|
|
||||||
protected void reset()
|
protected void reset()
|
||||||
{
|
{
|
||||||
HttpContent content = this.content;
|
HttpContent content = this.content;
|
||||||
|
@ -674,13 +685,6 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
|
||||||
|
|
||||||
private class CommitCallback implements Callback
|
private class CommitCallback implements Callback
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
|
||||||
public InvocationType getInvocationType()
|
|
||||||
{
|
|
||||||
return content.getInvocationType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void succeeded()
|
public void succeeded()
|
||||||
{
|
{
|
||||||
|
@ -721,12 +725,22 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
|
||||||
if (content == null)
|
if (content == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!content.hasContent())
|
HttpRequest request = exchange.getRequest();
|
||||||
|
Supplier<HttpFields> trailers = request.getTrailers();
|
||||||
|
boolean hasContent = content.hasContent();
|
||||||
|
if (!hasContent)
|
||||||
{
|
{
|
||||||
// No content to send, we are done.
|
if (trailers == null)
|
||||||
|
{
|
||||||
|
// No trailers or content to send, we are done.
|
||||||
someToSuccess(exchange);
|
someToSuccess(exchange);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
sendTrailers(exchange, lastCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// Was any content sent while committing ?
|
// Was any content sent while committing ?
|
||||||
ByteBuffer contentBuffer = content.getContent();
|
ByteBuffer contentBuffer = content.getContent();
|
||||||
|
@ -825,7 +839,9 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
|
||||||
|
|
||||||
if (lastContent)
|
if (lastContent)
|
||||||
{
|
{
|
||||||
sendContent(exchange, content, lastCallback);
|
HttpRequest request = exchange.getRequest();
|
||||||
|
Supplier<HttpFields> trailers = request.getTrailers();
|
||||||
|
sendContent(exchange, content, trailers == null ? lastCallback : trailersCallback);
|
||||||
return Action.IDLE;
|
return Action.IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -884,19 +900,35 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
|
||||||
@Override
|
@Override
|
||||||
protected void onCompleteSuccess()
|
protected void onCompleteSuccess()
|
||||||
{
|
{
|
||||||
// Nothing to do, since we always return false from process().
|
// Nothing to do, since we always return IDLE from process().
|
||||||
// Termination is obtained via LastContentCallback.
|
// Termination is obtained via LastCallback.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LastContentCallback implements Callback
|
private class TrailersCallback implements Callback
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public InvocationType getInvocationType()
|
public void succeeded()
|
||||||
{
|
{
|
||||||
return content.getInvocationType();
|
HttpExchange exchange = getHttpExchange();
|
||||||
|
if (exchange == null)
|
||||||
|
return;
|
||||||
|
sendTrailers(exchange, lastCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void failed(Throwable x)
|
||||||
|
{
|
||||||
|
HttpContent content = HttpSender.this.content;
|
||||||
|
if (content == null)
|
||||||
|
return;
|
||||||
|
content.failed(x);
|
||||||
|
anyToFailure(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LastCallback implements Callback
|
||||||
|
{
|
||||||
@Override
|
@Override
|
||||||
public void succeeded()
|
public void succeeded()
|
||||||
{
|
{
|
||||||
|
|
|
@ -277,6 +277,16 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parsedTrailer(HttpField trailer)
|
||||||
|
{
|
||||||
|
HttpExchange exchange = getHttpExchange();
|
||||||
|
if (exchange == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
exchange.getResponse().trailer(trailer);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean messageComplete()
|
public boolean messageComplete()
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,26 +23,29 @@ import java.nio.ByteBuffer;
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.eclipse.jetty.client.HttpContent;
|
import org.eclipse.jetty.client.HttpContent;
|
||||||
import org.eclipse.jetty.client.HttpExchange;
|
import org.eclipse.jetty.client.HttpExchange;
|
||||||
|
import org.eclipse.jetty.client.HttpRequest;
|
||||||
import org.eclipse.jetty.client.HttpRequestException;
|
import org.eclipse.jetty.client.HttpRequestException;
|
||||||
import org.eclipse.jetty.client.HttpSender;
|
import org.eclipse.jetty.client.HttpSender;
|
||||||
import org.eclipse.jetty.client.api.ContentProvider;
|
import org.eclipse.jetty.client.api.ContentProvider;
|
||||||
import org.eclipse.jetty.client.api.Request;
|
|
||||||
import org.eclipse.jetty.http.HttpGenerator;
|
import org.eclipse.jetty.http.HttpGenerator;
|
||||||
import org.eclipse.jetty.http.HttpURI;
|
import org.eclipse.jetty.http.HttpURI;
|
||||||
import org.eclipse.jetty.http.MetaData;
|
import org.eclipse.jetty.http.MetaData;
|
||||||
import org.eclipse.jetty.io.ByteBufferPool;
|
import org.eclipse.jetty.io.ByteBufferPool;
|
||||||
import org.eclipse.jetty.io.EndPoint;
|
import org.eclipse.jetty.io.EndPoint;
|
||||||
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.eclipse.jetty.util.Callback;
|
import org.eclipse.jetty.util.Callback;
|
||||||
import org.eclipse.jetty.util.IteratingCallback;
|
import org.eclipse.jetty.util.IteratingCallback;
|
||||||
|
|
||||||
public class HttpSenderOverHTTP extends HttpSender
|
public class HttpSenderOverHTTP extends HttpSender
|
||||||
{
|
{
|
||||||
private final HttpGenerator generator = new HttpGenerator();
|
private final HttpGenerator generator = new HttpGenerator();
|
||||||
|
private final HttpClient httpClient;
|
||||||
private boolean shutdown;
|
private boolean shutdown;
|
||||||
|
|
||||||
public HttpSenderOverHTTP(HttpChannelOverHTTP channel)
|
public HttpSenderOverHTTP(HttpChannelOverHTTP channel)
|
||||||
{
|
{
|
||||||
super(channel);
|
super(channel);
|
||||||
|
httpClient = channel.getHttpDestination().getHttpClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -71,8 +74,7 @@ public class HttpSenderOverHTTP extends HttpSender
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpClient client = getHttpChannel().getHttpDestination().getHttpClient();
|
ByteBufferPool bufferPool = httpClient.getByteBufferPool();
|
||||||
ByteBufferPool bufferPool = client.getByteBufferPool();
|
|
||||||
ByteBuffer chunk = null;
|
ByteBuffer chunk = null;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -90,6 +92,11 @@ public class HttpSenderOverHTTP extends HttpSender
|
||||||
chunk = bufferPool.acquire(HttpGenerator.CHUNK_SIZE, false);
|
chunk = bufferPool.acquire(HttpGenerator.CHUNK_SIZE, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NEED_CHUNK_TRAILER:
|
||||||
|
{
|
||||||
|
callback.succeeded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
case FLUSH:
|
case FLUSH:
|
||||||
{
|
{
|
||||||
EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint();
|
EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint();
|
||||||
|
@ -131,6 +138,21 @@ public class HttpSenderOverHTTP extends HttpSender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void sendTrailers(HttpExchange exchange, Callback callback)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new TrailersCallback(callback).iterate();
|
||||||
|
}
|
||||||
|
catch (Throwable x)
|
||||||
|
{
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug(x);
|
||||||
|
callback.failed(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void reset()
|
protected void reset()
|
||||||
{
|
{
|
||||||
|
@ -181,7 +203,7 @@ public class HttpSenderOverHTTP extends HttpSender
|
||||||
this.exchange = exchange;
|
this.exchange = exchange;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
|
|
||||||
Request request = exchange.getRequest();
|
HttpRequest request = exchange.getRequest();
|
||||||
ContentProvider requestContent = request.getContent();
|
ContentProvider requestContent = request.getContent();
|
||||||
long contentLength = requestContent == null ? -1 : requestContent.getLength();
|
long contentLength = requestContent == null ? -1 : requestContent.getLength();
|
||||||
String path = request.getPath();
|
String path = request.getPath();
|
||||||
|
@ -189,6 +211,7 @@ public class HttpSenderOverHTTP extends HttpSender
|
||||||
if (query != null)
|
if (query != null)
|
||||||
path += "?" + query;
|
path += "?" + query;
|
||||||
metaData = new MetaData.Request(request.getMethod(), new HttpURI(path), request.getVersion(), request.getHeaders(), contentLength);
|
metaData = new MetaData.Request(request.getMethod(), new HttpURI(path), request.getVersion(), request.getHeaders(), contentLength);
|
||||||
|
metaData.setTrailerSupplier(request.getTrailers());
|
||||||
|
|
||||||
if (!expects100Continue(request))
|
if (!expects100Continue(request))
|
||||||
{
|
{
|
||||||
|
@ -201,9 +224,6 @@ public class HttpSenderOverHTTP extends HttpSender
|
||||||
@Override
|
@Override
|
||||||
protected Action process() throws Exception
|
protected Action process() throws Exception
|
||||||
{
|
{
|
||||||
HttpClient client = getHttpChannel().getHttpDestination().getHttpClient();
|
|
||||||
ByteBufferPool bufferPool = client.getByteBufferPool();
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
HttpGenerator.Result result = generator.generateRequest(metaData, headerBuffer, chunkBuffer, contentBuffer, lastContent);
|
HttpGenerator.Result result = generator.generateRequest(metaData, headerBuffer, chunkBuffer, contentBuffer, lastContent);
|
||||||
|
@ -217,31 +237,28 @@ public class HttpSenderOverHTTP extends HttpSender
|
||||||
{
|
{
|
||||||
case NEED_HEADER:
|
case NEED_HEADER:
|
||||||
{
|
{
|
||||||
headerBuffer = bufferPool.acquire(client.getRequestBufferSize(), false);
|
headerBuffer = httpClient.getByteBufferPool().acquire(httpClient.getRequestBufferSize(), false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NEED_CHUNK:
|
case NEED_CHUNK:
|
||||||
{
|
{
|
||||||
chunkBuffer = bufferPool.acquire(HttpGenerator.CHUNK_SIZE, false);
|
chunkBuffer = httpClient.getByteBufferPool().acquire(HttpGenerator.CHUNK_SIZE, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NEED_CHUNK_TRAILER:
|
||||||
|
{
|
||||||
|
return Action.SUCCEEDED;
|
||||||
|
}
|
||||||
case FLUSH:
|
case FLUSH:
|
||||||
{
|
{
|
||||||
EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint();
|
EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint();
|
||||||
|
if (headerBuffer == null)
|
||||||
|
headerBuffer = BufferUtil.EMPTY_BUFFER;
|
||||||
if (chunkBuffer == null)
|
if (chunkBuffer == null)
|
||||||
{
|
chunkBuffer = BufferUtil.EMPTY_BUFFER;
|
||||||
if (contentBuffer == null)
|
if (contentBuffer == null)
|
||||||
endPoint.write(this, headerBuffer);
|
contentBuffer = BufferUtil.EMPTY_BUFFER;
|
||||||
else
|
|
||||||
endPoint.write(this, headerBuffer, contentBuffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (contentBuffer == null)
|
|
||||||
endPoint.write(this, headerBuffer, chunkBuffer);
|
|
||||||
else
|
|
||||||
endPoint.write(this, headerBuffer, chunkBuffer, contentBuffer);
|
endPoint.write(this, headerBuffer, chunkBuffer, contentBuffer);
|
||||||
}
|
|
||||||
generated = true;
|
generated = true;
|
||||||
return Action.SCHEDULED;
|
return Action.SCHEDULED;
|
||||||
}
|
}
|
||||||
|
@ -296,13 +313,91 @@ public class HttpSenderOverHTTP extends HttpSender
|
||||||
|
|
||||||
private void release()
|
private void release()
|
||||||
{
|
{
|
||||||
HttpClient client = getHttpChannel().getHttpDestination().getHttpClient();
|
ByteBufferPool bufferPool = httpClient.getByteBufferPool();
|
||||||
ByteBufferPool bufferPool = client.getByteBufferPool();
|
if (headerBuffer != BufferUtil.EMPTY_BUFFER)
|
||||||
bufferPool.release(headerBuffer);
|
bufferPool.release(headerBuffer);
|
||||||
headerBuffer = null;
|
headerBuffer = null;
|
||||||
if (chunkBuffer != null)
|
if (chunkBuffer != BufferUtil.EMPTY_BUFFER)
|
||||||
bufferPool.release(chunkBuffer);
|
bufferPool.release(chunkBuffer);
|
||||||
chunkBuffer = null;
|
chunkBuffer = null;
|
||||||
|
contentBuffer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TrailersCallback extends IteratingCallback
|
||||||
|
{
|
||||||
|
private final Callback callback;
|
||||||
|
private ByteBuffer chunkBuffer;
|
||||||
|
|
||||||
|
public TrailersCallback(Callback callback)
|
||||||
|
{
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Action process() throws Throwable
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
HttpGenerator.Result result = generator.generateRequest(null, null, chunkBuffer, null, true);
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("Generated trailers {}/{}", result, generator);
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case NEED_CHUNK_TRAILER:
|
||||||
|
{
|
||||||
|
chunkBuffer = httpClient.getByteBufferPool().acquire(httpClient.getRequestBufferSize(), false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FLUSH:
|
||||||
|
{
|
||||||
|
EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint();
|
||||||
|
endPoint.write(this, chunkBuffer);
|
||||||
|
return Action.SCHEDULED;
|
||||||
|
}
|
||||||
|
case SHUTDOWN_OUT:
|
||||||
|
{
|
||||||
|
shutdownOutput();
|
||||||
|
return Action.SUCCEEDED;
|
||||||
|
}
|
||||||
|
case DONE:
|
||||||
|
{
|
||||||
|
return Action.SUCCEEDED;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(result.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void succeeded()
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
super.succeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void failed(Throwable x)
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
callback.failed(x);
|
||||||
|
super.failed(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCompleteSuccess()
|
||||||
|
{
|
||||||
|
super.onCompleteSuccess();
|
||||||
|
callback.succeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void release()
|
||||||
|
{
|
||||||
|
httpClient.getByteBufferPool().release(chunkBuffer);
|
||||||
|
chunkBuffer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,6 @@ public abstract class AbstractHttpClientServerTest
|
||||||
sslContextFactory.setEndpointIdentificationAlgorithm("");
|
sslContextFactory.setEndpointIdentificationAlgorithm("");
|
||||||
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
|
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
|
||||||
sslContextFactory.setKeyStorePassword("storepwd");
|
sslContextFactory.setKeyStorePassword("storepwd");
|
||||||
sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");
|
|
||||||
sslContextFactory.setTrustStorePassword("storepwd");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server == null)
|
if (server == null)
|
||||||
|
|
|
@ -72,8 +72,6 @@ public class HttpClientTLSTest
|
||||||
sslContextFactory.setEndpointIdentificationAlgorithm("");
|
sslContextFactory.setEndpointIdentificationAlgorithm("");
|
||||||
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
|
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
|
||||||
sslContextFactory.setKeyStorePassword("storepwd");
|
sslContextFactory.setKeyStorePassword("storepwd");
|
||||||
sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");
|
|
||||||
sslContextFactory.setTrustStorePassword("storepwd");
|
|
||||||
return sslContextFactory;
|
return sslContextFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,6 @@ public class TLSServerConnectionCloseTest
|
||||||
sslContextFactory.setEndpointIdentificationAlgorithm("");
|
sslContextFactory.setEndpointIdentificationAlgorithm("");
|
||||||
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
|
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
|
||||||
sslContextFactory.setKeyStorePassword("storepwd");
|
sslContextFactory.setKeyStorePassword("storepwd");
|
||||||
sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");
|
|
||||||
sslContextFactory.setTrustStorePassword("storepwd");
|
|
||||||
|
|
||||||
QueuedThreadPool clientThreads = new QueuedThreadPool();
|
QueuedThreadPool clientThreads = new QueuedThreadPool();
|
||||||
clientThreads.setName("client");
|
clientThreads.setName("client");
|
||||||
|
|
|
@ -0,0 +1,233 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2017 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.client.ssl;
|
||||||
|
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.EmptyServerHandler;
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
|
import org.eclipse.jetty.io.ssl.SslHandshakeListener;
|
||||||
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In order to work, client authentication needs a certificate
|
||||||
|
* signed by a CA that also signed the server certificate.
|
||||||
|
* <p>
|
||||||
|
* For this test, the client certificate is signed with the server
|
||||||
|
* certificate, and the server certificate is self-signed.
|
||||||
|
*/
|
||||||
|
public class NeedWantClientAuthTest
|
||||||
|
{
|
||||||
|
private Server server;
|
||||||
|
private ServerConnector connector;
|
||||||
|
private HttpClient client;
|
||||||
|
|
||||||
|
private void startServer(SslContextFactory sslContextFactory, Handler handler) throws Exception
|
||||||
|
{
|
||||||
|
QueuedThreadPool serverThreads = new QueuedThreadPool();
|
||||||
|
serverThreads.setName("server");
|
||||||
|
server = new Server(serverThreads);
|
||||||
|
|
||||||
|
connector = new ServerConnector(server, sslContextFactory);
|
||||||
|
server.addConnector(connector);
|
||||||
|
|
||||||
|
server.setHandler(handler);
|
||||||
|
server.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startClient(SslContextFactory sslContextFactory) throws Exception
|
||||||
|
{
|
||||||
|
QueuedThreadPool clientThreads = new QueuedThreadPool();
|
||||||
|
clientThreads.setName("client");
|
||||||
|
client = new HttpClient(sslContextFactory);
|
||||||
|
client.setExecutor(clientThreads);
|
||||||
|
client.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SslContextFactory createSslContextFactory()
|
||||||
|
{
|
||||||
|
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||||
|
sslContextFactory.setEndpointIdentificationAlgorithm("");
|
||||||
|
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
|
||||||
|
sslContextFactory.setKeyStorePassword("storepwd");
|
||||||
|
return sslContextFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void dispose() throws Exception
|
||||||
|
{
|
||||||
|
if (client != null)
|
||||||
|
client.stop();
|
||||||
|
if (server != null)
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWantClientAuthWithoutAuth() throws Exception
|
||||||
|
{
|
||||||
|
SslContextFactory serverSSL = new SslContextFactory();
|
||||||
|
serverSSL.setKeyStorePath("src/test/resources/keystore.jks");
|
||||||
|
serverSSL.setKeyStorePassword("storepwd");
|
||||||
|
serverSSL.setWantClientAuth(true);
|
||||||
|
startServer(serverSSL, new EmptyServerHandler());
|
||||||
|
|
||||||
|
SslContextFactory clientSSL = new SslContextFactory(true);
|
||||||
|
startClient(clientSSL);
|
||||||
|
|
||||||
|
ContentResponse response = client.newRequest("https://localhost:" + connector.getLocalPort())
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWantClientAuthWithAuth() throws Exception
|
||||||
|
{
|
||||||
|
SslContextFactory serverSSL = new SslContextFactory();
|
||||||
|
serverSSL.setKeyStorePath("src/test/resources/keystore.jks");
|
||||||
|
serverSSL.setKeyStorePassword("storepwd");
|
||||||
|
serverSSL.setWantClientAuth(true);
|
||||||
|
startServer(serverSSL, new EmptyServerHandler());
|
||||||
|
CountDownLatch handshakeLatch = new CountDownLatch(1);
|
||||||
|
connector.addBean(new SslHandshakeListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void handshakeSucceeded(Event event)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SSLSession session = event.getSSLEngine().getSession();
|
||||||
|
Certificate[] clientCerts = session.getPeerCertificates();
|
||||||
|
Assert.assertNotNull(clientCerts);
|
||||||
|
Assert.assertThat(clientCerts.length, Matchers.greaterThan(0));
|
||||||
|
handshakeLatch.countDown();
|
||||||
|
}
|
||||||
|
catch (Throwable x)
|
||||||
|
{
|
||||||
|
x.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
SslContextFactory clientSSL = new SslContextFactory(true);
|
||||||
|
clientSSL.setKeyStorePath("src/test/resources/client_keystore.jks");
|
||||||
|
clientSSL.setKeyStorePassword("storepwd");
|
||||||
|
startClient(clientSSL);
|
||||||
|
|
||||||
|
ContentResponse response = client.newRequest("https://localhost:" + connector.getLocalPort())
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||||
|
Assert.assertTrue(handshakeLatch.await(5, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNeedClientAuthWithoutAuth() throws Exception
|
||||||
|
{
|
||||||
|
SslContextFactory serverSSL = new SslContextFactory();
|
||||||
|
serverSSL.setKeyStorePath("src/test/resources/keystore.jks");
|
||||||
|
serverSSL.setKeyStorePassword("storepwd");
|
||||||
|
serverSSL.setNeedClientAuth(true);
|
||||||
|
startServer(serverSSL, new EmptyServerHandler());
|
||||||
|
|
||||||
|
SslContextFactory clientSSL = new SslContextFactory(true);
|
||||||
|
startClient(clientSSL);
|
||||||
|
CountDownLatch handshakeLatch = new CountDownLatch(1);
|
||||||
|
client.addBean(new SslHandshakeListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void handshakeFailed(Event event, Throwable failure)
|
||||||
|
{
|
||||||
|
Assert.assertThat(failure, Matchers.instanceOf(SSLHandshakeException.class));
|
||||||
|
handshakeLatch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
client.newRequest("https://localhost:" + connector.getLocalPort())
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send(result ->
|
||||||
|
{
|
||||||
|
if (result.isFailed())
|
||||||
|
latch.countDown();
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.assertTrue(handshakeLatch.await(5, TimeUnit.SECONDS));
|
||||||
|
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNeedClientAuthWithAuth() throws Exception
|
||||||
|
{
|
||||||
|
SslContextFactory serverSSL = new SslContextFactory();
|
||||||
|
serverSSL.setKeyStorePath("src/test/resources/keystore.jks");
|
||||||
|
serverSSL.setKeyStorePassword("storepwd");
|
||||||
|
serverSSL.setNeedClientAuth(true);
|
||||||
|
startServer(serverSSL, new EmptyServerHandler());
|
||||||
|
CountDownLatch handshakeLatch = new CountDownLatch(1);
|
||||||
|
connector.addBean(new SslHandshakeListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void handshakeSucceeded(Event event)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SSLSession session = event.getSSLEngine().getSession();
|
||||||
|
Certificate[] clientCerts = session.getPeerCertificates();
|
||||||
|
Assert.assertNotNull(clientCerts);
|
||||||
|
Assert.assertThat(clientCerts.length, Matchers.greaterThan(0));
|
||||||
|
handshakeLatch.countDown();
|
||||||
|
}
|
||||||
|
catch (Throwable x)
|
||||||
|
{
|
||||||
|
x.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
SslContextFactory clientSSL = new SslContextFactory(true);
|
||||||
|
clientSSL.setKeyStorePath("src/test/resources/client_keystore.jks");
|
||||||
|
clientSSL.setKeyStorePassword("storepwd");
|
||||||
|
startClient(clientSSL);
|
||||||
|
|
||||||
|
ContentResponse response = client.newRequest("https://localhost:" + connector.getLocalPort())
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||||
|
Assert.assertTrue(handshakeLatch.await(5, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-continuation</artifactId>
|
<artifactId>jetty-continuation</artifactId>
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
package org.eclipse.jetty.continuation;
|
package org.eclipse.jetty.continuation;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.Servlet;
|
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import javax.servlet.ServletResponseWrapper;
|
import javax.servlet.ServletResponseWrapper;
|
||||||
|
@ -139,7 +138,9 @@ import javax.servlet.ServletResponseWrapper;
|
||||||
* @see ContinuationSupport
|
* @see ContinuationSupport
|
||||||
* @see ContinuationListener
|
* @see ContinuationListener
|
||||||
*
|
*
|
||||||
|
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public interface Continuation
|
public interface Continuation
|
||||||
{
|
{
|
||||||
public final static String ATTRIBUTE = "org.eclipse.jetty.continuation";
|
public final static String ATTRIBUTE = "org.eclipse.jetty.continuation";
|
||||||
|
|
|
@ -48,7 +48,9 @@ import javax.servlet.ServletResponse;
|
||||||
* {@link Continuation#complete()} is called.</p>
|
* {@link Continuation#complete()} is called.</p>
|
||||||
* <p>Faux continuations are not threadless continuations (they are "faux" - fake - for this reason)
|
* <p>Faux continuations are not threadless continuations (they are "faux" - fake - for this reason)
|
||||||
* and as such they will scale less than proper continuations.</p>
|
* and as such they will scale less than proper continuations.</p>
|
||||||
|
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class ContinuationFilter implements Filter
|
public class ContinuationFilter implements Filter
|
||||||
{
|
{
|
||||||
static boolean _initialized;
|
static boolean _initialized;
|
||||||
|
@ -60,6 +62,7 @@ public class ContinuationFilter implements Filter
|
||||||
|
|
||||||
public void init(FilterConfig filterConfig) throws ServletException
|
public void init(FilterConfig filterConfig) throws ServletException
|
||||||
{
|
{
|
||||||
|
filterConfig.getServletContext().log("WARNING: " + this.getClass().getName() + " is now DEPRECATED, use Servlet 3.0 AsyncContext instead.");
|
||||||
boolean jetty_7_or_greater="org.eclipse.jetty.servlet".equals(filterConfig.getClass().getPackage().getName());
|
boolean jetty_7_or_greater="org.eclipse.jetty.servlet".equals(filterConfig.getClass().getPackage().getName());
|
||||||
_context = filterConfig.getServletContext();
|
_context = filterConfig.getServletContext();
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,9 @@ import javax.servlet.ServletRequestListener;
|
||||||
* <p>
|
* <p>
|
||||||
* A ContinuationListener may be registered with a call to
|
* A ContinuationListener may be registered with a call to
|
||||||
* {@link Continuation#addContinuationListener(ContinuationListener)}.
|
* {@link Continuation#addContinuationListener(ContinuationListener)}.
|
||||||
|
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public interface ContinuationListener extends EventListener
|
public interface ContinuationListener extends EventListener
|
||||||
{
|
{
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
|
|
@ -29,7 +29,9 @@ import javax.servlet.ServletResponse;
|
||||||
*
|
*
|
||||||
* Factory class for accessing Continuation instances, which with either be
|
* Factory class for accessing Continuation instances, which with either be
|
||||||
* a servlet 3.0 or a faux continuation.
|
* a servlet 3.0 or a faux continuation.
|
||||||
|
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class ContinuationSupport
|
public class ContinuationSupport
|
||||||
{
|
{
|
||||||
static final boolean __servlet3;
|
static final boolean __servlet3;
|
||||||
|
|
|
@ -41,7 +41,9 @@ package org.eclipse.jetty.continuation;
|
||||||
* to be uncaught (or rethrown) by a Filter/Servlet. A ContinuationThrowable
|
* to be uncaught (or rethrown) by a Filter/Servlet. A ContinuationThrowable
|
||||||
* does not represent and error condition.
|
* does not represent and error condition.
|
||||||
* </p>
|
* </p>
|
||||||
|
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class ContinuationThrowable extends Error
|
public class ContinuationThrowable extends Error
|
||||||
{
|
{
|
||||||
public ContinuationThrowable()
|
public ContinuationThrowable()
|
||||||
|
|
|
@ -33,7 +33,9 @@ import org.eclipse.jetty.continuation.ContinuationFilter.FilteredContinuation;
|
||||||
* A blocking implementation of Continuation.
|
* A blocking implementation of Continuation.
|
||||||
* This implementation of Continuation is used by the {@link ContinuationFilter}
|
* This implementation of Continuation is used by the {@link ContinuationFilter}
|
||||||
* when there are is no native or asynchronous continuation type available.
|
* when there are is no native or asynchronous continuation type available.
|
||||||
|
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
class FauxContinuation implements FilteredContinuation
|
class FauxContinuation implements FilteredContinuation
|
||||||
{
|
{
|
||||||
// common exception used for all continuations.
|
// common exception used for all continuations.
|
||||||
|
|
|
@ -36,7 +36,9 @@ import javax.servlet.ServletResponseWrapper;
|
||||||
* This implementation of Continuation is used by {@link ContinuationSupport}
|
* This implementation of Continuation is used by {@link ContinuationSupport}
|
||||||
* when it detects that the application has been deployed in a Servlet 3
|
* when it detects that the application has been deployed in a Servlet 3
|
||||||
* server.
|
* server.
|
||||||
|
* @deprecated use Servlet 3.0 {@link javax.servlet.AsyncContext} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class Servlet3Continuation implements Continuation, AsyncListener
|
public class Servlet3Continuation implements Continuation, AsyncListener
|
||||||
{
|
{
|
||||||
// Exception reused for all continuations
|
// Exception reused for all continuations
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jetty Continuation : Generic Async Servlet Method
|
* Jetty Continuation : <em>DEPRECATED: use Servlet 3.0 {@link javax.servlet.AsyncContext} instead</em>
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
package org.eclipse.jetty.continuation;
|
package org.eclipse.jetty.continuation;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-deploy</artifactId>
|
<artifactId>jetty-deploy</artifactId>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-distribution</artifactId>
|
<artifactId>jetty-distribution</artifactId>
|
||||||
|
|
|
@ -14,6 +14,36 @@
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/META-INF/**</exclude>
|
<exclude>**/META-INF/**</exclude>
|
||||||
<exclude>*-config.jar</exclude>
|
<exclude>*-config.jar</exclude>
|
||||||
|
<!-- common OS detritus -->
|
||||||
|
<exclude>**/.DS_Store</exclude>
|
||||||
|
<exclude>**/Thumbs.db</exclude>
|
||||||
|
<exclude>**/desktop.ini</exclude>
|
||||||
|
<!-- common temp files -->
|
||||||
|
<exclude>**/*~</exclude>
|
||||||
|
<exclude>**/*.bak</exclude>
|
||||||
|
<exclude>**/*.backup</exclude>
|
||||||
|
<exclude>**/*.old</exclude>
|
||||||
|
<exclude>**/*.swp</exclude>
|
||||||
|
<exclude>**/*.debug</exclude>
|
||||||
|
<exclude>**/*.dump</exclude>
|
||||||
|
<exclude>**/*.log</exclude>
|
||||||
|
<exclude>**/~*</exclude>
|
||||||
|
<!-- common git/scm files -->
|
||||||
|
<exclude>**/*.orig</exclude>
|
||||||
|
<exclude>**/*.diff</exclude>
|
||||||
|
<exclude>**/*.patch</exclude>
|
||||||
|
<exclude>**/.gitignore</exclude>
|
||||||
|
<!-- various editor files -->
|
||||||
|
<exclude>**/*.iml</exclude>
|
||||||
|
<exclude>**/*.ipr</exclude>
|
||||||
|
<exclude>**/*.iws</exclude>
|
||||||
|
<exclude>**/*.idea</exclude>
|
||||||
|
<exclude>**/.classpath</exclude>
|
||||||
|
<exclude>**/.project</exclude>
|
||||||
|
<exclude>**/.settings</exclude>
|
||||||
|
<!-- maven dust -->
|
||||||
|
<exclude>**/*.versionsBackup</exclude>
|
||||||
|
<exclude>**/*.releaseBackup</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
</fileSets>
|
</fileSets>
|
||||||
|
|
|
@ -12,6 +12,36 @@
|
||||||
</includes>
|
</includes>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/target/**</exclude>
|
<exclude>**/target/**</exclude>
|
||||||
|
<!-- common OS detritus -->
|
||||||
|
<exclude>**/.DS_Store</exclude>
|
||||||
|
<exclude>**/Thumbs.db</exclude>
|
||||||
|
<exclude>**/desktop.ini</exclude>
|
||||||
|
<!-- common temp files -->
|
||||||
|
<exclude>**/*~</exclude>
|
||||||
|
<exclude>**/*.bak</exclude>
|
||||||
|
<exclude>**/*.backup</exclude>
|
||||||
|
<exclude>**/*.old</exclude>
|
||||||
|
<exclude>**/*.swp</exclude>
|
||||||
|
<exclude>**/*.debug</exclude>
|
||||||
|
<exclude>**/*.dump</exclude>
|
||||||
|
<exclude>**/*.log</exclude>
|
||||||
|
<exclude>**/~*</exclude>
|
||||||
|
<!-- common git/scm files -->
|
||||||
|
<exclude>**/*.orig</exclude>
|
||||||
|
<exclude>**/*.diff</exclude>
|
||||||
|
<exclude>**/*.patch</exclude>
|
||||||
|
<exclude>**/.gitignore</exclude>
|
||||||
|
<!-- various editor files -->
|
||||||
|
<exclude>**/*.iml</exclude>
|
||||||
|
<exclude>**/*.ipr</exclude>
|
||||||
|
<exclude>**/*.iws</exclude>
|
||||||
|
<exclude>**/*.idea</exclude>
|
||||||
|
<exclude>**/.classpath</exclude>
|
||||||
|
<exclude>**/.project</exclude>
|
||||||
|
<exclude>**/.settings</exclude>
|
||||||
|
<!-- maven dust -->
|
||||||
|
<exclude>**/*.versionsBackup</exclude>
|
||||||
|
<exclude>**/*.releaseBackup</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
</fileSets>
|
</fileSets>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>jetty-documentation</artifactId>
|
<artifactId>jetty-documentation</artifactId>
|
||||||
<name>Jetty :: Documentation</name>
|
<name>Jetty :: Documentation</name>
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
<allow-uri-read>true</allow-uri-read>
|
<allow-uri-read>true</allow-uri-read>
|
||||||
<toc>true</toc>
|
<toc>true</toc>
|
||||||
<revnumber>${project.version}</revnumber>
|
<revnumber>${project.version}</revnumber>
|
||||||
<JDURL>http://download.eclipse.org/jetty/stable-9/apidocs</JDURL>
|
<JDURL>http://www.eclipse.org/jetty/javadoc/${project.version}</JDURL>
|
||||||
<JXURL>http://download.eclipse.org/jetty/stable-9/xref</JXURL>
|
<JXURL>http://download.eclipse.org/jetty/stable-9/xref</JXURL>
|
||||||
<SRCDIR>${basedir}/..</SRCDIR>
|
<SRCDIR>${basedir}/..</SRCDIR>
|
||||||
<GITBROWSEURL>https://github.com/eclipse/jetty.project/tree/jetty-9.4.x</GITBROWSEURL>
|
<GITBROWSEURL>https://github.com/eclipse/jetty.project/tree/jetty-9.4.x</GITBROWSEURL>
|
||||||
|
|
|
@ -34,9 +34,9 @@ Jetty currently has two levels of request statistic collection:
|
||||||
* Subclasses of `AbstractConnector` class optionally can collect statistics about connections as well as number of requests.
|
* Subclasses of `AbstractConnector` class optionally can collect statistics about connections as well as number of requests.
|
||||||
* The `StatisticsHandler` class may be used to collect request statistics.
|
* The `StatisticsHandler` class may be used to collect request statistics.
|
||||||
|
|
||||||
In addition to these, subclasses of the `AbstractSessionHandler` class optionally can collect session statistics.
|
In addition to these, subclasses of the `SessionHandler` and `DefaultSessionCache` classes optionally can collect session statistics.
|
||||||
|
|
||||||
`AbstractConnector` and `AbstractSessionHandler` statistics are turned off by default and must either be configured manually for each instance or turned on via JMX interface.
|
`AbstractConnector`, `SessionHandler` and `DefaultSessionCache` statistics are turned off by default and must either be configured manually for each instance or turned on via JMX interface.
|
||||||
The `StatisticsHandler` is not included in default Jetty configuration, and needs to be configured manually.
|
The `StatisticsHandler` is not included in default Jetty configuration, and needs to be configured manually.
|
||||||
|
|
||||||
_____
|
_____
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
This chapter discusses various options for configuring logging.
|
This chapter discusses various options for configuring logging.
|
||||||
|
|
||||||
include::configuring-jetty-logging.adoc[]
|
//include::configuring-jetty-logging.adoc[]
|
||||||
include::default-logging-with-stderrlog.adoc[]
|
include::default-logging-with-stderrlog.adoc[]
|
||||||
include::configuring-jetty-request-logs.adoc[]
|
include::configuring-jetty-request-logs.adoc[]
|
||||||
include::configuring-logging-modules.adoc[]
|
include::configuring-logging-modules.adoc[]
|
||||||
|
|
|
@ -58,6 +58,12 @@ INFO: Base directory was modified
|
||||||
|
|
||||||
The above command will add a new `requestlog.ini` file to your link:#start-vs-startd[`{$jetty.base}/start.d` directory].
|
The above command will add a new `requestlog.ini` file to your link:#start-vs-startd[`{$jetty.base}/start.d` directory].
|
||||||
|
|
||||||
|
____
|
||||||
|
[NOTE]
|
||||||
|
By default, request logs are not set to be appended, meaning a the log file is wiped clean upon sever restart.
|
||||||
|
You can change this setting by editing the `requestlog.ini` and un-commenting the line that reads `jetty.requestlog.append=true`.
|
||||||
|
____
|
||||||
|
|
||||||
The equivalent code for embedded usages of Jetty is:
|
The equivalent code for embedded usages of Jetty is:
|
||||||
|
|
||||||
[source, java, subs="{sub-order}"]
|
[source, java, subs="{sub-order}"]
|
||||||
|
|
|
@ -45,6 +45,13 @@ INFO : Base directory was modified
|
||||||
|
|
||||||
The default configuration for logging output will create a file `${jetty.base}/logs/yyyy_mm_dd.stderrout.log` which allows configuration of the output directory by setting the `jetty.logs` property.
|
The default configuration for logging output will create a file `${jetty.base}/logs/yyyy_mm_dd.stderrout.log` which allows configuration of the output directory by setting the `jetty.logs` property.
|
||||||
|
|
||||||
|
____
|
||||||
|
[NOTE]
|
||||||
|
By default, logs are not set to be appended, meaning a the log file is wiped clean upon sever restart.
|
||||||
|
You can change this setting by editing the `console-capture.ini` and un-commenting the line that reads `jetty.console-capture.append=true`.
|
||||||
|
____
|
||||||
|
|
||||||
|
|
||||||
Just enabling the `console-capture` will simply output the values of STDERR and STDOUT to a log file.
|
Just enabling the `console-capture` will simply output the values of STDERR and STDOUT to a log file.
|
||||||
To customize the log further, a module named `logging-jetty` is available to provides a default properties file to configure.
|
To customize the log further, a module named `logging-jetty` is available to provides a default properties file to configure.
|
||||||
As with `console-capture`, you activate the `logging-jetty` on the command line.
|
As with `console-capture`, you activate the `logging-jetty` on the command line.
|
||||||
|
|
|
@ -51,7 +51,7 @@ INFO: resources enabled in ${jetty.base}/start.ini
|
||||||
The replacement `logging.mod` performs a number of tasks.
|
The replacement `logging.mod` performs a number of tasks.
|
||||||
|
|
||||||
. `mybase` is a `${jetty.base}` directory
|
. `mybase` is a `${jetty.base}` directory
|
||||||
. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/ `and becomes the `${jetty.home}` directory for this demonstration.
|
. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/` and becomes the `${jetty.home}` directory for this demonstration.
|
||||||
. The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by `mybase` only.
|
. The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by `mybase` only.
|
||||||
. The `start.jar --add-to-start=logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration.
|
. The `start.jar --add-to-start=logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration.
|
||||||
.. The `--module=logging` command is added to the `${jetty.base}/start.ini` configuration.
|
.. The `--module=logging` command is added to the `${jetty.base}/start.ini` configuration.
|
||||||
|
|
|
@ -81,7 +81,7 @@ INFO: resources enabled in ${jetty.base}/start.ini
|
||||||
The replacement `logging.mod` performs a number of tasks.
|
The replacement `logging.mod` performs a number of tasks.
|
||||||
|
|
||||||
. `mybase` is a `${jetty.base}` directory.
|
. `mybase` is a `${jetty.base}` directory.
|
||||||
. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/ `and becomes the `${jetty.home}` directory for this demonstration.
|
. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/` and becomes the `${jetty.home}` directory for this demonstration.
|
||||||
. The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by mybase only.
|
. The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by mybase only.
|
||||||
. The `start.jar --add-to-start=logging,webapp-logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration.
|
. The `start.jar --add-to-start=logging,webapp-logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration.
|
||||||
.. Several entries are added to the `${jetty.base}/start.ini` configuration.
|
.. Several entries are added to the `${jetty.base}/start.ini` configuration.
|
||||||
|
|
|
@ -47,7 +47,7 @@ DOWNLOAD: https://raw.githubusercontent.com/jetty-project/logging-modules/master
|
||||||
The replacement `logging.mod` performs a number of tasks.
|
The replacement `logging.mod` performs a number of tasks.
|
||||||
|
|
||||||
. `mybase` is a `${jetty.base}` directory.
|
. `mybase` is a `${jetty.base}` directory.
|
||||||
. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/ `and becomes the `${jetty.home}` directory for this demonstration.
|
. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/` and becomes the `${jetty.home}` directory for this demonstration.
|
||||||
. The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by `mybase` only.
|
. The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by `mybase` only.
|
||||||
. The `start.jar --add-to-start=logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration.
|
. The `start.jar --add-to-start=logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration.
|
||||||
.. The `--module=logging` command is added to the `${jetty.base}/start.ini` configuration.
|
.. The `--module=logging` command is added to the `${jetty.base}/start.ini` configuration.
|
||||||
|
|
|
@ -118,7 +118,7 @@ INFO: resources enabled in ${jetty.base}/start.ini
|
||||||
The replacement `logging.mod` performs a number of tasks.
|
The replacement `logging.mod` performs a number of tasks.
|
||||||
|
|
||||||
. `mybase` is a `${jetty.base}` directory.
|
. `mybase` is a `${jetty.base}` directory.
|
||||||
. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/ `and becomes the `${jetty.home}` directory for this demonstration.
|
. The jetty-distribution is unpacked (and untouched) into `/opt/jetty-dist/` and becomes the `${jetty.home}` directory for this demonstration.
|
||||||
. The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by `mybase` only.
|
. The `curl` command downloads the replacement `logging.mod` and puts it into the `${jetty.base}/modules/` directory for use by `mybase` only.
|
||||||
. The `start.jar --add-to-start=logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration.
|
. The `start.jar --add-to-start=logging` command performs a number of steps to make the logging module available to the `${jetty.base}` configuration.
|
||||||
.. The `--module=logging` command is added to the `${jetty.base}/start.ini` configuration.
|
.. The `--module=logging` command is added to the `${jetty.base}/start.ini` configuration.
|
||||||
|
|
|
@ -52,7 +52,7 @@ META-INF/web-fragment.xml
|
||||||
|
|
||||||
===== Anatomy of a Configuration Class
|
===== Anatomy of a Configuration Class
|
||||||
|
|
||||||
A Configuration class is called 5 times in different phases of the link:http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/webapp/WebAppContext.html[`WebAppContext's`] lifecycle:
|
A Configuration class is called 5 times in different phases of the link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[`WebAppContext's`] lifecycle:
|
||||||
|
|
||||||
preConfigure::
|
preConfigure::
|
||||||
As the `WebAppContext` is starting up this phase is executed.
|
As the `WebAppContext` is starting up this phase is executed.
|
||||||
|
|
|
@ -27,9 +27,9 @@ Authorization::
|
||||||
|
|
||||||
==== Configuring an Authentication mechanism
|
==== Configuring an Authentication mechanism
|
||||||
|
|
||||||
The jetty server supports several standard authentication mechanisms: http://en.wikipedia.org/wiki/Basic_access_authentication[BASIC]; http://en.wikipedia.org/wiki/Digest_authentication[DIGEST]; http://en.wikipedia.org/wiki/Form-based_authentication[FORM]; CLIENT-CERT; and other mechanisms can be plugged in using the extensible http://docs.oracle.com/cd/E19462-01/819-6717/gcszc/index.html[JASPI] or http://en.wikipedia.org/wiki/SPNEGO[SPNEGO] mechanisms.
|
Jetty server supports several standard authentication mechanisms: http://en.wikipedia.org/wiki/Basic_access_authentication[BASIC]; http://en.wikipedia.org/wiki/Digest_authentication[DIGEST]; http://en.wikipedia.org/wiki/Form-based_authentication[FORM]; CLIENT-CERT; and other mechanisms can be plugged in using the extensible http://docs.oracle.com/cd/E19462-01/819-6717/gcszc/index.html[JASPI] or http://en.wikipedia.org/wiki/SPNEGO[SPNEGO] mechanisms.
|
||||||
|
|
||||||
Internally, configuring an authentication mechanism is done by setting an instance of a the link:{JDURL}/org/eclipse/jetty/security/Authenticator.html[Authenticator] interface onto the link:{JDURL}/org/eclipse/jetty/security/SecurityHandler.html[SecurityHandler] of the context, but in most cases it is done by declaring a `< login-config>` element in the standard web.xml descriptor or via annotations.
|
Internally, configuring an authentication mechanism is done by setting an instance of a the link:{JDURL}/org/eclipse/jetty/security/Authenticator.html[Authenticator] interface onto the link:{JDURL}/org/eclipse/jetty/security/SecurityHandler.html[SecurityHandler] of the context, but in most cases it is done by declaring a `<login-config>` element in the standard web.xml descriptor or via annotations.
|
||||||
|
|
||||||
Below is an example taken from the link:{GITBROWSEURL}/tests/test-webapps/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml?h=release-9[jetty-test-webapp web.xml] that configures BASIC authentication:
|
Below is an example taken from the link:{GITBROWSEURL}/tests/test-webapps/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml?h=release-9[jetty-test-webapp web.xml] that configures BASIC authentication:
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ When a request is received for a protected resource, the web container checks if
|
||||||
The Servlet Specification does not address how the static security information in the `WEB-INF/web.xml` file is mapped to the runtime environment of the container.
|
The Servlet Specification does not address how the static security information in the `WEB-INF/web.xml` file is mapped to the runtime environment of the container.
|
||||||
For Jetty, the link:{JDURL}/org/eclipse/jetty/security/LoginService.html[LoginService] performs this function.
|
For Jetty, the link:{JDURL}/org/eclipse/jetty/security/LoginService.html[LoginService] performs this function.
|
||||||
|
|
||||||
A LoginService has a unique name, and gives access to information about a set of users.
|
A `LoginService` has a unique name, and gives access to information about a set of users.
|
||||||
Each user has authentication information (e.g. a password) and a set of roles associated with him/herself.
|
Each user has authentication information (e.g. a password) and a set of roles associated with him/herself.
|
||||||
|
|
||||||
You may configure one or many different LoginServices depending on your needs.
|
You may configure one or many different LoginServices depending on your needs.
|
||||||
|
@ -114,7 +114,8 @@ When a request to a web application requires authentication or authorization, Je
|
||||||
|
|
||||||
==== Scoping Security Realms
|
==== Scoping Security Realms
|
||||||
|
|
||||||
A LoginService has a unique name, and is composed of a set of users. Each user has authentication information (for example, a password) and a set of roles associated with him/herself.
|
A `LoginService` has a unique name, and is composed of a set of users.
|
||||||
|
Each user has authentication information (for example, a password) and a set of roles associated with him/herself.
|
||||||
You can configure one or many different realms depending on your needs.
|
You can configure one or many different realms depending on your needs.
|
||||||
|
|
||||||
* Configure a single LoginService to share common security information across all of your web applications.
|
* Configure a single LoginService to share common security information across all of your web applications.
|
||||||
|
@ -144,8 +145,8 @@ Here's an example of an xml file that defines an in-memory type of LoginService
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
If you define more than one LoginService on a Server, you will need to specify which one you want used for each context.
|
If you define more than one `LoginService` on a Server, you will need to specify which one you want used for each context.
|
||||||
You can do that by telling the context the name of the LoginService, or passing it the LoginService instance.
|
You can do that by telling the context the name of the `LoginService`, or passing it the `LoginService` instance.
|
||||||
Here's an example of doing both of these, using a link:#deployable-descriptor-file[context xml file]:
|
Here's an example of doing both of these, using a link:#deployable-descriptor-file[context xml file]:
|
||||||
|
|
||||||
[source, xml, subs="{sub-order}"]
|
[source, xml, subs="{sub-order}"]
|
||||||
|
@ -170,7 +171,7 @@ Here's an example of doing both of these, using a link:#deployable-descriptor-fi
|
||||||
|
|
||||||
===== Per-Webapp Scoped
|
===== Per-Webapp Scoped
|
||||||
|
|
||||||
Alternatively, you can define a LoginService for just a single web application.
|
Alternatively, you can define a `LoginService` for just a single web application.
|
||||||
Here's how to define the same HashLoginService, but inside a link:#deployable-descriptor-file[context xml file]:
|
Here's how to define the same HashLoginService, but inside a link:#deployable-descriptor-file[context xml file]:
|
||||||
|
|
||||||
[source, xml, subs="{sub-order}"]
|
[source, xml, subs="{sub-order}"]
|
||||||
|
@ -192,12 +193,12 @@ Here's how to define the same HashLoginService, but inside a link:#deployable-de
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
Jetty provides a number of different LoginService types which can be seen in the next section.
|
Jetty provides a number of different `LoginService` types which can be seen in the next section.
|
||||||
|
|
||||||
[[configuring-login-service]]
|
[[configuring-login-service]]
|
||||||
==== Configuring a LoginService
|
==== Configuring a LoginService
|
||||||
|
|
||||||
A link:{JDURL}/org/eclipse/jetty/security/LoginService.html[LoginService] instance is required by each context/webapp that has a authentication mechanism, which is used to check the validity of the username and credentials collected by the authentication mechanism. Jetty provides the following implementations of LoginService:
|
A link:{JDURL}/org/eclipse/jetty/security/LoginService.html[`LoginService`] instance is required by each context/webapp that has a authentication mechanism, which is used to check the validity of the username and credentials collected by the authentication mechanism. Jetty provides the following implementations of `LoginService`:
|
||||||
|
|
||||||
link:{JDURL}/org/eclipse/jetty/security/HashLoginService.html[HashLoginService]::
|
link:{JDURL}/org/eclipse/jetty/security/HashLoginService.html[HashLoginService]::
|
||||||
A user realm that is backed by a hash map that is filled either programatically or from a Java properties file.
|
A user realm that is backed by a hash map that is filled either programatically or from a Java properties file.
|
||||||
|
@ -211,16 +212,16 @@ link:{JDURL}/org/eclipse/jetty/jaas/JAASLoginService.html[JAASLoginService]::
|
||||||
link:{JDURL}/org/eclipse/jetty/security/SpnegoLoginService.html[SpnegoLoginService]::
|
link:{JDURL}/org/eclipse/jetty/security/SpnegoLoginService.html[SpnegoLoginService]::
|
||||||
http://en.wikipedia.org/wiki/SPNEGO[SPNEGO] Authentication; see the section on link:#spnego-support[SPNEGO support] for more information.
|
http://en.wikipedia.org/wiki/SPNEGO[SPNEGO] Authentication; see the section on link:#spnego-support[SPNEGO support] for more information.
|
||||||
|
|
||||||
An instance of a LoginService can be matched to a context/webapp by:
|
An instance of a `LoginService` can be matched to a context/webapp by:
|
||||||
|
|
||||||
* A LoginService instance may be set directly on the SecurityHandler instance via embedded code or IoC XML
|
* A `LoginService` instance may be set directly on the `SecurityHandler` instance via embedded code or IoC XML
|
||||||
* Matching the realm-name defined in web.xml with the name of a LoginService instance that has been added to the Server instance as a dependent bean
|
* Matching the realm-name defined in web.xml with the name of a `LoginService` instance that has been added to the Server instance as a dependent bean
|
||||||
* If only a single LoginService instance has been set on the Server then it is used as the login service for the context
|
* If only a single `LoginService` instance has been set on the Server then it is used as the login service for the context
|
||||||
|
|
||||||
[[hash-login-service]]
|
[[hash-login-service]]
|
||||||
===== HashLoginService
|
===== HashLoginService
|
||||||
|
|
||||||
The HashLoginService is a simple and efficient login service that loads usernames, credentials and roles from a Java properties file in the format:
|
The `HashLoginService` is a simple and efficient login service that loads usernames, credentials and roles from a Java properties file in the format:
|
||||||
|
|
||||||
[source,properties]
|
[source,properties]
|
||||||
----
|
----
|
||||||
|
@ -249,7 +250,7 @@ guest: guest,read-only
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
You configure the HashLoginService with a name and a reference to the location of the properties file:
|
You configure the `HashLoginService` with a name and a reference to the location of the properties file:
|
||||||
|
|
||||||
[source, xml, subs="{sub-order}"]
|
[source, xml, subs="{sub-order}"]
|
||||||
----
|
----
|
||||||
|
@ -378,12 +379,12 @@ When a user requests a resource that is access protected, the LoginService will
|
||||||
|
|
||||||
Until Servlet 3.1, role-based authorization could define:
|
Until Servlet 3.1, role-based authorization could define:
|
||||||
|
|
||||||
* access granted to a set of named roles
|
* Access granted to a set of named roles
|
||||||
* access totally forbidden, regardless of role
|
* Access totally forbidden, regardless of role
|
||||||
* access granted to a user in any of the roles defined in the effective web.xml.
|
* Access granted to a user in any of the roles defined in the effective web.xml.
|
||||||
This is indicated by the special value of "*" for the `<role-name>` of a `<auth-constraint> `in the `<security-constraint>`
|
This is indicated by the special value of `*` for the `<role-name>` of a `<auth-constraint>` in the `<security-constraint>`
|
||||||
|
|
||||||
With the advent of Servlet 3.1, there is now another authorization:
|
With the advent of Servlet 3.1, there is now another authorization:
|
||||||
|
|
||||||
* access granted to any user who is authenticated, regardless of roles.
|
* Access granted to any user who is authenticated, regardless of roles.
|
||||||
This is indicated by the special value of "**" for the `<role-name>` of a `<auth-constraint>` in the `<security-constraint>`
|
This is indicated by the special value of `**` for the `<role-name>` of a `<auth-constraint>` in the `<security-constraint>`
|
||||||
|
|
|
@ -226,10 +226,10 @@ As `LoginModules` are free to use their own implementation of the JAAS Principal
|
||||||
|
|
||||||
===== Sample LoginModules
|
===== Sample LoginModules
|
||||||
|
|
||||||
* link:{JXURL}/org/eclipse/jetty/jaas/spi/JDBCLoginModule.html[`org.eclipse.jetty.jaas.spi.JDBCLoginModule`]
|
* link:{JDURL}/org/eclipse/jetty/jaas/spi/JDBCLoginModule.html[`org.eclipse.jetty.jaas.spi.JDBCLoginModule`]
|
||||||
* link:{JXURL}/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.html[`org.eclipse.jetty.jaas.spi.PropertyFileLoginModule`]
|
* link:{JDURL}/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.html[`org.eclipse.jetty.jaas.spi.PropertyFileLoginModule`]
|
||||||
* link:{JXURL}/org/eclipse/jetty/jaas/spi/DataSourceLoginModule.html[`org.eclipse.jetty.jaas.spi.DataSourceLoginModule`]
|
* link:{JDURL}/org/eclipse/jetty/jaas/spi/DataSourceLoginModule.html[`org.eclipse.jetty.jaas.spi.DataSourceLoginModule`]
|
||||||
* link:{JXURL}/org/eclipse/jetty/jaas/spi/LdapLoginModule.html[`org.eclipse.jetty.jaas.ldap.LdapLoginModule`]
|
* link:{JDURL}/org/eclipse/jetty/jaas/spi/LdapLoginModule.html[`org.eclipse.jetty.jaas.ldap.LdapLoginModule`]
|
||||||
|
|
||||||
____
|
____
|
||||||
[NOTE]
|
[NOTE]
|
||||||
|
|
|
@ -30,6 +30,12 @@ When you download and unpack the binary, it is extracted into a directory called
|
||||||
Put this directory in a convenient location.
|
Put this directory in a convenient location.
|
||||||
The rest of the instructions in this documentation refer to this location as either `JETTY_HOME` or as `$(jetty.home).`
|
The rest of the instructions in this documentation refer to this location as either `JETTY_HOME` or as `$(jetty.home).`
|
||||||
|
|
||||||
|
_____
|
||||||
|
[IMPORTANT]
|
||||||
|
It is important that only stable releases are used in production environments.
|
||||||
|
Versions that have been deprecated or are released as Milestones (M) or Release Candidates (RC) are not suitable for production as they may contain security flaws or incomplete/non-functioning feature sets.
|
||||||
|
_____
|
||||||
|
|
||||||
[[distribution-content]]
|
[[distribution-content]]
|
||||||
==== Distribution Content
|
==== Distribution Content
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,12 @@
|
||||||
[[quickstart-jetty-coordinates]]
|
[[quickstart-jetty-coordinates]]
|
||||||
=== Finding Jetty in Maven
|
=== Finding Jetty in Maven
|
||||||
|
|
||||||
|
_____
|
||||||
|
[IMPORTANT]
|
||||||
|
It is important that only stable releases are used in production environments.
|
||||||
|
Versions that have been deprecated or are released as Milestones (M) or Release Candidates (RC) are not suitable for production as they may contain security flaws or incomplete/non-functioning feature sets.
|
||||||
|
_____
|
||||||
|
|
||||||
==== Maven Coordinates
|
==== Maven Coordinates
|
||||||
|
|
||||||
Jetty has existed in Maven Central almost since its inception, though the coordinates have changed over the years.
|
Jetty has existed in Maven Central almost since its inception, though the coordinates have changed over the years.
|
||||||
|
@ -34,7 +40,7 @@ The top level Project Object Model (POM) for the Jetty project is located under
|
||||||
</dependency>
|
</dependency>
|
||||||
----
|
----
|
||||||
|
|
||||||
==== Changelogs in Central
|
==== Changelogs in Maven Central
|
||||||
|
|
||||||
The changes between versions of Jetty are tracked in a file called VERSIONS.txt, which is under source control and is generated on release.
|
The changes between versions of Jetty are tracked in a file called VERSIONS.txt, which is under source control and is generated on release.
|
||||||
Those generated files are also uploaded into Maven Central during the release of the top level POM. You can find them as a classifier marked artifact.
|
Those generated files are also uploaded into Maven Central during the release of the top level POM. You can find them as a classifier marked artifact.
|
||||||
|
|
|
@ -21,6 +21,12 @@ Jetty 9 is the most recent version of Jetty and has a great many improvements ov
|
||||||
This documentation which focuses on Jetty 9.
|
This documentation which focuses on Jetty 9.
|
||||||
While many people continue to use older versions of Jetty, we generally recommend using Jetty 9 as it represents the version of Jetty that we will actively maintain and improve over the next few years.
|
While many people continue to use older versions of Jetty, we generally recommend using Jetty 9 as it represents the version of Jetty that we will actively maintain and improve over the next few years.
|
||||||
|
|
||||||
|
_____
|
||||||
|
[IMPORTANT]
|
||||||
|
It is important that only stable releases are used in production environments.
|
||||||
|
Versions that have been deprecated or are released as Milestones (M) or Release Candidates (RC) are not suitable for production as they may contain security flaws or incomplete/non-functioning feature sets.
|
||||||
|
_____
|
||||||
|
|
||||||
.Jetty Versions
|
.Jetty Versions
|
||||||
[width="100%",cols="12%,9%,15%,6%,21%,10%,6%,21%",options="header",]
|
[width="100%",cols="12%,9%,15%,6%,21%,10%,6%,21%",options="header",]
|
||||||
|=======================================================================
|
|=======================================================================
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||||
<artifactId>fcgi-parent</artifactId>
|
<artifactId>fcgi-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -125,4 +125,10 @@ public class HttpSenderOverFCGI extends HttpSender
|
||||||
getHttpChannel().flush(result);
|
getHttpChannel().flush(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void sendTrailers(HttpExchange exchange, Callback callback)
|
||||||
|
{
|
||||||
|
callback.succeeded();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.fcgi</groupId>
|
<groupId>org.eclipse.jetty.fcgi</groupId>
|
||||||
<artifactId>fcgi-parent</artifactId>
|
<artifactId>fcgi-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.gcloud</groupId>
|
<groupId>org.eclipse.jetty.gcloud</groupId>
|
||||||
<artifactId>gcloud-parent</artifactId>
|
<artifactId>gcloud-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
<Arg>
|
<Arg>
|
||||||
<New id="sessionDataStoreFactory" class="org.eclipse.jetty.gcloud.session.GCloudSessionDataStoreFactory">
|
<New id="sessionDataStoreFactory" class="org.eclipse.jetty.gcloud.session.GCloudSessionDataStoreFactory">
|
||||||
<Set name="gracePeriodSec"><Property name="jetty.session.gracePeriod.seconds" default="3600" /></Set>
|
<Set name="gracePeriodSec"><Property name="jetty.session.gracePeriod.seconds" default="3600" /></Set>
|
||||||
|
<Set name="savePeriodSec"><Property name="jetty.session.savePeriod.seconds" default="0" /></Set>
|
||||||
<Set name="maxRetries"><Property name="jetty.session.gcloud.maxRetries" default="5"/></Set>
|
<Set name="maxRetries"><Property name="jetty.session.gcloud.maxRetries" default="5"/></Set>
|
||||||
<Set name="backoffMs"><Property name="jetty.session.gcloud.backoffMs" default="1000"/></Set>
|
<Set name="backoffMs"><Property name="jetty.session.gcloud.backoffMs" default="1000"/></Set>
|
||||||
<Set name="namespace"><Property name="jetty.session.gcloud.namespace" default=""/></Set>
|
<Set name="namespace"><Property name="jetty.session.gcloud.namespace" default=""/></Set>
|
||||||
|
|
|
@ -26,6 +26,8 @@ etc/sessions/gcloud/session-store.xml
|
||||||
[ini-template]
|
[ini-template]
|
||||||
|
|
||||||
## GCloudDatastore Session config
|
## GCloudDatastore Session config
|
||||||
|
#jetty.session.gracePeriod.seconds=3600
|
||||||
|
#jetty.session.savePeriod.seconds=0
|
||||||
#jetty.session.gcloud.maxRetries=5
|
#jetty.session.gcloud.maxRetries=5
|
||||||
#jetty.session.gcloud.backoffMs=1000
|
#jetty.session.gcloud.backoffMs=1000
|
||||||
#jetty.session.gcloud.namespace=
|
#jetty.session.gcloud.namespace=
|
||||||
|
|
|
@ -33,6 +33,8 @@ import org.eclipse.jetty.server.session.UnreadableSessionDataException;
|
||||||
import org.eclipse.jetty.server.session.UnwriteableSessionDataException;
|
import org.eclipse.jetty.server.session.UnwriteableSessionDataException;
|
||||||
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
|
||||||
|
@ -55,6 +57,7 @@ import com.google.cloud.datastore.StructuredQuery.PropertyFilter;
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ManagedObject
|
||||||
public class GCloudSessionDataStore extends AbstractSessionDataStore
|
public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
{
|
{
|
||||||
private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
|
private final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
|
||||||
|
@ -98,6 +101,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
public static final String EXPIRY = "expiry";
|
public static final String EXPIRY = "expiry";
|
||||||
public static final String MAXINACTIVE = "maxInactive";
|
public static final String MAXINACTIVE = "maxInactive";
|
||||||
public static final String ATTRIBUTES = "attributes";
|
public static final String ATTRIBUTES = "attributes";
|
||||||
|
public static final String LASTSAVED = "lastSaved";
|
||||||
|
|
||||||
public static final String KIND = "GCloudSession";
|
public static final String KIND = "GCloudSession";
|
||||||
protected String _kind = KIND;
|
protected String _kind = KIND;
|
||||||
|
@ -107,6 +111,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
protected String _accessed = ACCESSED;
|
protected String _accessed = ACCESSED;
|
||||||
protected String _lastAccessed = LASTACCESSED;
|
protected String _lastAccessed = LASTACCESSED;
|
||||||
protected String _lastNode = LASTNODE;
|
protected String _lastNode = LASTNODE;
|
||||||
|
protected String _lastSaved = LASTSAVED;
|
||||||
protected String _createTime = CREATETIME;
|
protected String _createTime = CREATETIME;
|
||||||
protected String _cookieSetTime = COOKIESETTIME;
|
protected String _cookieSetTime = COOKIESETTIME;
|
||||||
protected String _expiry = EXPIRY;
|
protected String _expiry = EXPIRY;
|
||||||
|
@ -302,6 +307,23 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
_attributes = attributes;
|
_attributes = attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the lastSaved
|
||||||
|
*/
|
||||||
|
public String getLastSaved()
|
||||||
|
{
|
||||||
|
return _lastSaved;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lastSaved the lastSaved to set
|
||||||
|
*/
|
||||||
|
public void setLastSaved(String lastSaved)
|
||||||
|
{
|
||||||
|
checkNotNull(lastSaved);
|
||||||
|
_lastSaved = lastSaved;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see java.lang.Object#toString()
|
* @see java.lang.Object#toString()
|
||||||
*/
|
*/
|
||||||
|
@ -391,11 +413,13 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
_namespace = namespace;
|
_namespace = namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute(value="gclound namespace", readonly=true)
|
||||||
public String getNamespace ()
|
public String getNamespace ()
|
||||||
{
|
{
|
||||||
return _namespace;
|
return _namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute(value="unit in ms of exponential backoff")
|
||||||
public int getBackoffMs ()
|
public int getBackoffMs ()
|
||||||
{
|
{
|
||||||
return _backoff;
|
return _backoff;
|
||||||
|
@ -407,7 +431,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
_maxRetries = retries;
|
_maxRetries = retries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute(value="max number of retries for failed writes")
|
||||||
public int getMaxRetries ()
|
public int getMaxRetries ()
|
||||||
{
|
{
|
||||||
return _maxRetries;
|
return _maxRetries;
|
||||||
|
@ -461,6 +485,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
_dsProvided = true;
|
_dsProvided = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute(value="max number of results to return from gcloud searches")
|
||||||
public int getMaxResults()
|
public int getMaxResults()
|
||||||
{
|
{
|
||||||
return _maxResults;
|
return _maxResults;
|
||||||
|
@ -529,11 +554,15 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
for (ExpiryInfo item:info)
|
for (ExpiryInfo item:info)
|
||||||
{
|
{
|
||||||
if (StringUtil.isBlank(item.getLastNode()))
|
if (StringUtil.isBlank(item.getLastNode()))
|
||||||
|
{
|
||||||
expired.add(item.getId()); //nobody managing it
|
expired.add(item.getId()); //nobody managing it
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_context.getWorkerName().equals(item.getLastNode()))
|
if (_context.getWorkerName().equals(item.getLastNode()))
|
||||||
|
{
|
||||||
expired.add(item.getId()); //we're managing it, we can expire it
|
expired.add(item.getId()); //we're managing it, we can expire it
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_lastExpiryCheckTime <= 0)
|
if (_lastExpiryCheckTime <= 0)
|
||||||
|
@ -541,8 +570,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
//our first check, just look for sessions that we managed by another node that
|
//our first check, just look for sessions that we managed by another node that
|
||||||
//expired at least 3 graceperiods ago
|
//expired at least 3 graceperiods ago
|
||||||
if (item.getExpiry() < (now - (1000L * (3 * _gracePeriodSec))))
|
if (item.getExpiry() < (now - (1000L * (3 * _gracePeriodSec))))
|
||||||
expired.add(item.getId());
|
expired.add(item.getId()); }
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//another node was last managing it, only expire it if it expired a graceperiod ago
|
//another node was last managing it, only expire it if it expired a graceperiod ago
|
||||||
|
@ -636,11 +664,12 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
*/
|
*/
|
||||||
protected Set<ExpiryInfo> queryExpiryByIndex () throws Exception
|
protected Set<ExpiryInfo> queryExpiryByIndex () throws Exception
|
||||||
{
|
{
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
Set<ExpiryInfo> info = new HashSet<>();
|
Set<ExpiryInfo> info = new HashSet<>();
|
||||||
Query<ProjectionEntity> query = Query.newProjectionEntityQueryBuilder()
|
Query<ProjectionEntity> query = Query.newProjectionEntityQueryBuilder()
|
||||||
.setKind(_model.getKind())
|
.setKind(_model.getKind())
|
||||||
.setProjection(_model.getId(), _model.getLastNode(), _model.getExpiry())
|
.setProjection(_model.getId(), _model.getLastNode(), _model.getExpiry())
|
||||||
.setFilter(CompositeFilter.and(PropertyFilter.gt(_model.getExpiry(), 0), PropertyFilter.le(_model.getExpiry(), System.currentTimeMillis())))
|
.setFilter(CompositeFilter.and(PropertyFilter.gt(_model.getExpiry(), 0), PropertyFilter.le(_model.getExpiry(), now)))
|
||||||
.setLimit(_maxResults)
|
.setLimit(_maxResults)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -746,7 +775,6 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
public void doStore(String id, SessionData data, long lastSaveTime) throws Exception
|
public void doStore(String id, SessionData data, long lastSaveTime) throws Exception
|
||||||
{
|
{
|
||||||
if (LOG.isDebugEnabled()) LOG.debug("Writing session {} to DataStore", data.getId());
|
if (LOG.isDebugEnabled()) LOG.debug("Writing session {} to DataStore", data.getId());
|
||||||
|
|
||||||
Entity entity = entityFromSession(data, makeKey(id, _context));
|
Entity entity = entityFromSession(data, makeKey(id, _context));
|
||||||
|
|
||||||
//attempt the update with exponential back-off
|
//attempt the update with exponential back-off
|
||||||
|
@ -868,6 +896,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
.set(_model.getLastNode(),session.getLastNode())
|
.set(_model.getLastNode(),session.getLastNode())
|
||||||
.set(_model.getExpiry(), session.getExpiry())
|
.set(_model.getExpiry(), session.getExpiry())
|
||||||
.set(_model.getMaxInactive(), session.getMaxInactiveMs())
|
.set(_model.getMaxInactive(), session.getMaxInactiveMs())
|
||||||
|
.set(_model.getLastSaved(), session.getLastSaved())
|
||||||
.set(_model.getAttributes(), BlobValue.newBuilder(Blob.copyFrom(baos.toByteArray())).setExcludeFromIndexes(true).build()).build();
|
.set(_model.getAttributes(), BlobValue.newBuilder(Blob.copyFrom(baos.toByteArray())).setExcludeFromIndexes(true).build()).build();
|
||||||
|
|
||||||
|
|
||||||
|
@ -902,6 +931,17 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
long createTime = entity.getLong(_model.getCreateTime());
|
long createTime = entity.getLong(_model.getCreateTime());
|
||||||
long cookieSet = entity.getLong(_model.getCookieSetTime());
|
long cookieSet = entity.getLong(_model.getCookieSetTime());
|
||||||
String lastNode = entity.getString(_model.getLastNode());
|
String lastNode = entity.getString(_model.getLastNode());
|
||||||
|
|
||||||
|
long lastSaved = 0;
|
||||||
|
//for compatibility with previously saved sessions, lastSaved may not be present
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lastSaved = entity.getLong(_model.getLastSaved());
|
||||||
|
}
|
||||||
|
catch (DatastoreException e)
|
||||||
|
{
|
||||||
|
LOG.ignore(e);
|
||||||
|
}
|
||||||
long expiry = entity.getLong(_model.getExpiry());
|
long expiry = entity.getLong(_model.getExpiry());
|
||||||
long maxInactive = entity.getLong(_model.getMaxInactive());
|
long maxInactive = entity.getLong(_model.getMaxInactive());
|
||||||
Blob blob = (Blob) entity.getBlob(_model.getAttributes());
|
Blob blob = (Blob) entity.getBlob(_model.getAttributes());
|
||||||
|
@ -912,6 +952,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
session.setVhost(vhost);
|
session.setVhost(vhost);
|
||||||
session.setCookieSet(cookieSet);
|
session.setCookieSet(cookieSet);
|
||||||
session.setLastNode(lastNode);
|
session.setLastNode(lastNode);
|
||||||
|
session.setLastSaved(lastSaved);
|
||||||
session.setExpiry(expiry);
|
session.setExpiry(expiry);
|
||||||
try (ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(blob.asInputStream()))
|
try (ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(blob.asInputStream()))
|
||||||
{
|
{
|
||||||
|
@ -943,6 +984,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
||||||
/**
|
/**
|
||||||
* @see org.eclipse.jetty.server.session.SessionDataStore#isPassivating()
|
* @see org.eclipse.jetty.server.session.SessionDataStore#isPassivating()
|
||||||
*/
|
*/
|
||||||
|
@ManagedAttribute(value="does gcloud serialize session data", readonly=true)
|
||||||
@Override
|
@Override
|
||||||
public boolean isPassivating()
|
public boolean isPassivating()
|
||||||
{
|
{
|
||||||
|
|
|
@ -94,6 +94,7 @@ public class GCloudSessionDataStoreFactory extends AbstractSessionDataStoreFacto
|
||||||
ds.setMaxRetries(getMaxRetries());
|
ds.setMaxRetries(getMaxRetries());
|
||||||
ds.setGracePeriodSec(getGracePeriodSec());
|
ds.setGracePeriodSec(getGracePeriodSec());
|
||||||
ds.setNamespace(_namespace);
|
ds.setNamespace(_namespace);
|
||||||
|
ds.setSavePeriodSec(getSavePeriodSec());
|
||||||
return ds;
|
return ds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
<name>Jetty :: GCloud</name>
|
<name>Jetty :: GCloud</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<gcloud.version>0.9.4-beta</gcloud.version>
|
<gcloud.version>0.10.0-beta</gcloud.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-home</artifactId>
|
<artifactId>jetty-home</artifactId>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-http-spi</artifactId>
|
<artifactId>jetty-http-spi</artifactId>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>jetty-project</artifactId>
|
<artifactId>jetty-project</artifactId>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>jetty-http</artifactId>
|
<artifactId>jetty-http</artifactId>
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
<extensions>true</extensions>
|
<extensions>true</extensions>
|
||||||
<configuration>
|
<configuration>
|
||||||
<instructions>
|
<instructions>
|
||||||
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.http.HttpFieldPreEncoder)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)";resolution:=optional, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.http.HttpFieldPreEncoder)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)";resolution:=optional, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
|
||||||
<!--
|
<!--
|
||||||
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
|
||||||
-->
|
-->
|
||||||
|
|
|
@ -45,6 +45,11 @@ public class BadMessageException extends RuntimeException
|
||||||
this(400,reason);
|
this(400,reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BadMessageException(String reason, Throwable cause)
|
||||||
|
{
|
||||||
|
this(400, reason, cause);
|
||||||
|
}
|
||||||
|
|
||||||
public BadMessageException(int code, String reason)
|
public BadMessageException(int code, String reason)
|
||||||
{
|
{
|
||||||
super(code+": "+reason);
|
super(code+": "+reason);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
//
|
//
|
||||||
|
|
||||||
package org.eclipse.jetty.server;
|
package org.eclipse.jetty.http;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The compliance for Cookie handling.
|
* The compliance for Cookie handling.
|
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.http;
|
package org.eclipse.jetty.http;
|
||||||
|
|
||||||
import static org.eclipse.jetty.http.HttpStatus.INTERNAL_SERVER_ERROR_500;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.BufferOverflowException;
|
import java.nio.BufferOverflowException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
@ -34,6 +32,8 @@ import org.eclipse.jetty.util.Trie;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
|
||||||
|
import static org.eclipse.jetty.http.HttpStatus.INTERNAL_SERVER_ERROR_500;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HttpGenerator. Builds HTTP Messages.
|
* HttpGenerator. Builds HTTP Messages.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -764,7 +764,7 @@ public class HttpGenerator
|
||||||
}
|
}
|
||||||
// Else if we are HTTP/1.1 and the content length is unknown and we are either persistent
|
// Else if we are HTTP/1.1 and the content length is unknown and we are either persistent
|
||||||
// or it is a request with content (which cannot EOF) or the app has requested chunking
|
// or it is a request with content (which cannot EOF) or the app has requested chunking
|
||||||
else if (http11 && content_length<0 && (_persistent || assumed_content_request || chunked_hint))
|
else if (http11 && (chunked_hint || content_length<0 && (_persistent || assumed_content_request)))
|
||||||
{
|
{
|
||||||
// we use chunking
|
// we use chunking
|
||||||
_endOfContent = EndOfContent.CHUNKED_CONTENT;
|
_endOfContent = EndOfContent.CHUNKED_CONTENT;
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class HttpStatus
|
||||||
public final static int REQUESTED_RANGE_NOT_SATISFIABLE_416 = 416;
|
public final static int REQUESTED_RANGE_NOT_SATISFIABLE_416 = 416;
|
||||||
public final static int RANGE_NOT_SATISFIABLE_416 = 416;
|
public final static int RANGE_NOT_SATISFIABLE_416 = 416;
|
||||||
public final static int EXPECTATION_FAILED_417 = 417;
|
public final static int EXPECTATION_FAILED_417 = 417;
|
||||||
public final static int IM_A_TEAPOT_418 = 417;
|
public final static int IM_A_TEAPOT_418 = 418;
|
||||||
public final static int ENHANCE_YOUR_CALM_420 = 420;
|
public final static int ENHANCE_YOUR_CALM_420 = 420;
|
||||||
public final static int MISDIRECTED_REQUEST_421 = 421;
|
public final static int MISDIRECTED_REQUEST_421 = 421;
|
||||||
public final static int UNPROCESSABLE_ENTITY_422 = 422;
|
public final static int UNPROCESSABLE_ENTITY_422 = 422;
|
||||||
|
@ -153,7 +153,7 @@ public class HttpStatus
|
||||||
UNSUPPORTED_MEDIA_TYPE(UNSUPPORTED_MEDIA_TYPE_415, "Unsupported Media Type"),
|
UNSUPPORTED_MEDIA_TYPE(UNSUPPORTED_MEDIA_TYPE_415, "Unsupported Media Type"),
|
||||||
RANGE_NOT_SATISFIABLE(RANGE_NOT_SATISFIABLE_416, "Range Not Satisfiable"),
|
RANGE_NOT_SATISFIABLE(RANGE_NOT_SATISFIABLE_416, "Range Not Satisfiable"),
|
||||||
EXPECTATION_FAILED(EXPECTATION_FAILED_417, "Expectation Failed"),
|
EXPECTATION_FAILED(EXPECTATION_FAILED_417, "Expectation Failed"),
|
||||||
IM_A_TEAPOT(IM_A_TEAPOT_418, "Im a Teapot"),
|
IM_A_TEAPOT(IM_A_TEAPOT_418, "I'm a Teapot"),
|
||||||
ENHANCE_YOUR_CALM(ENHANCE_YOUR_CALM_420, "Enhance your Calm"),
|
ENHANCE_YOUR_CALM(ENHANCE_YOUR_CALM_420, "Enhance your Calm"),
|
||||||
MISDIRECTED_REQUEST(MISDIRECTED_REQUEST_421, "Misdirected Request"),
|
MISDIRECTED_REQUEST(MISDIRECTED_REQUEST_421, "Misdirected Request"),
|
||||||
UNPROCESSABLE_ENTITY(UNPROCESSABLE_ENTITY_422, "Unprocessable Entity"),
|
UNPROCESSABLE_ENTITY(UNPROCESSABLE_ENTITY_422, "Unprocessable Entity"),
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2017 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.http;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of Syntax validation methods.
|
||||||
|
* <p>
|
||||||
|
* Use in a similar way as you would {@link java.util.Objects#requireNonNull(Object)}
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public final class Syntax
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Per RFC2616: Section 2.2, a token follows these syntax rules
|
||||||
|
* <pre>
|
||||||
|
* token = 1*<any CHAR except CTLs or separators>
|
||||||
|
* CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||||
|
* CTL = <any US-ASCII control character
|
||||||
|
* (octets 0 - 31) and DEL (127)>
|
||||||
|
* separators = "(" | ")" | "<" | ">" | "@"
|
||||||
|
* | "," | ";" | ":" | "\" | <">
|
||||||
|
* | "/" | "[" | "]" | "?" | "="
|
||||||
|
* | "{" | "}" | SP | HT
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param value the value to test
|
||||||
|
* @param msg the message to be prefixed if an {@link IllegalArgumentException} is thrown.
|
||||||
|
* @throws IllegalArgumentException if the value is invalid per spec
|
||||||
|
*/
|
||||||
|
public static void requireValidRFC2616Token(String value, String msg)
|
||||||
|
{
|
||||||
|
Objects.requireNonNull(msg, "msg cannot be null");
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int valueLen = value.length();
|
||||||
|
if (valueLen == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < valueLen; i++)
|
||||||
|
{
|
||||||
|
char c = value.charAt(i);
|
||||||
|
|
||||||
|
// 0x00 - 0x1F are low order control characters
|
||||||
|
// 0x7F is the DEL control character
|
||||||
|
if ((c <= 0x1F) || (c == 0x7F))
|
||||||
|
throw new IllegalArgumentException(msg + ": RFC2616 tokens may not contain control characters");
|
||||||
|
if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@'
|
||||||
|
|| c == ',' || c == ';' || c == ':' || c == '\\' || c == '"'
|
||||||
|
|| c == '/' || c == '[' || c == ']' || c == '?' || c == '='
|
||||||
|
|| c == '{' || c == '}' || c == ' ')
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException(msg + ": RFC2616 tokens may not contain separator character: [" + c + "]");
|
||||||
|
}
|
||||||
|
if (c >= 0x80)
|
||||||
|
throw new IllegalArgumentException(msg + ": RFC2616 tokens characters restricted to US-ASCII: 0x" + Integer.toHexString(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Per RFC6265, Cookie.value follows these syntax rules
|
||||||
|
* <pre>
|
||||||
|
* cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
|
||||||
|
* cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
|
||||||
|
* ; US-ASCII characters excluding CTLs,
|
||||||
|
* ; whitespace DQUOTE, comma, semicolon,
|
||||||
|
* ; and backslash
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param value the value to test
|
||||||
|
* @throws IllegalArgumentException if the value is invalid per spec
|
||||||
|
*/
|
||||||
|
public static void requireValidRFC6265CookieValue(String value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int valueLen = value.length();
|
||||||
|
if (valueLen == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
if (value.charAt(0) == '"')
|
||||||
|
{
|
||||||
|
// Has starting DQUOTE
|
||||||
|
if (valueLen <= 1 || (value.charAt(valueLen - 1) != '"'))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("RFC6265 Cookie values must have balanced DQUOTES (if used)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjust search range to exclude DQUOTES
|
||||||
|
i++;
|
||||||
|
valueLen--;
|
||||||
|
}
|
||||||
|
for (; i < valueLen; i++)
|
||||||
|
{
|
||||||
|
char c = value.charAt(i);
|
||||||
|
|
||||||
|
// 0x00 - 0x1F are low order control characters
|
||||||
|
// 0x7F is the DEL control character
|
||||||
|
if ((c <= 0x1F) || (c == 0x7F))
|
||||||
|
throw new IllegalArgumentException("RFC6265 Cookie values may not contain control characters");
|
||||||
|
if ((c == ' ' /* 0x20 */) ||
|
||||||
|
(c == '"' /* 0x2C */) ||
|
||||||
|
(c == ';' /* 0x3B */) ||
|
||||||
|
(c == '\\' /* 0x5C */))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("RFC6265 Cookie values may not contain character: [" + c + "]");
|
||||||
|
}
|
||||||
|
if (c >= 0x80)
|
||||||
|
throw new IllegalArgumentException("RFC6265 Cookie values characters restricted to US-ASCII: 0x" + Integer.toHexString(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ doc=application/msword
|
||||||
dtd=application/xml-dtd
|
dtd=application/xml-dtd
|
||||||
dvi=application/x-dvi
|
dvi=application/x-dvi
|
||||||
dxr=application/x-director
|
dxr=application/x-director
|
||||||
|
eot=application/vnd.ms-fontobject
|
||||||
eps=application/postscript
|
eps=application/postscript
|
||||||
etx=text/x-setext
|
etx=text/x-setext
|
||||||
exe=application/octet-stream
|
exe=application/octet-stream
|
||||||
|
@ -171,6 +172,8 @@ wml=text/vnd.wap.wml
|
||||||
wmlc=application/vnd.wap.wmlc
|
wmlc=application/vnd.wap.wmlc
|
||||||
wmls=text/vnd.wap.wmlscript
|
wmls=text/vnd.wap.wmlscript
|
||||||
wmlsc=application/vnd.wap.wmlscriptc
|
wmlsc=application/vnd.wap.wmlscriptc
|
||||||
|
woff=application/font-woff
|
||||||
|
woff2=font/woff2
|
||||||
wrl=model/vrml
|
wrl=model/vrml
|
||||||
wtls-ca-certificate=application/vnd.wap.wtls-ca-certificate
|
wtls-ca-certificate=application/vnd.wap.wtls-ca-certificate
|
||||||
xbm=image/x-xbitmap
|
xbm=image/x-xbitmap
|
||||||
|
|
|
@ -32,6 +32,14 @@ public class HttpStatusCodeTest
|
||||||
assertNull("Invalid code: 190", HttpStatus.getCode(190));
|
assertNull("Invalid code: 190", HttpStatus.getCode(190));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testImATeapot()
|
||||||
|
{
|
||||||
|
assertEquals("I'm a Teapot", HttpStatus.getMessage(418));
|
||||||
|
assertEquals("Expectation Failed", HttpStatus.getMessage(417));
|
||||||
|
}
|
||||||
|
|
||||||
public void testHttpMethod()
|
public void testHttpMethod()
|
||||||
{
|
{
|
||||||
assertEquals("GET",HttpMethod.GET.toString());
|
assertEquals("GET",HttpMethod.GET.toString());
|
||||||
|
|
|
@ -21,16 +21,15 @@ package org.eclipse.jetty.http;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.MultiMap;
|
import org.eclipse.jetty.util.MultiMap;
|
||||||
import org.eclipse.jetty.util.Utf8Appendable;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class HttpURITest
|
public class HttpURITest
|
||||||
|
@ -101,33 +100,6 @@ public class HttpURITest
|
||||||
assertThat(uri.getPath(),is("/bar"));
|
assertThat(uri.getPath(),is("/bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUnicodeErrors() throws UnsupportedEncodingException
|
|
||||||
{
|
|
||||||
String uri="http://server/path?invalid=data%uXXXXhere%u000";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
URLDecoder.decode(uri,"UTF-8");
|
|
||||||
Assert.assertTrue(false);
|
|
||||||
}
|
|
||||||
catch (IllegalArgumentException e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpURI huri=new HttpURI(uri);
|
|
||||||
MultiMap<String> params = new MultiMap<>();
|
|
||||||
huri.decodeQueryTo(params);
|
|
||||||
assertEquals("data"+Utf8Appendable.REPLACEMENT+"here"+Utf8Appendable.REPLACEMENT,params.getValue("invalid",0));
|
|
||||||
|
|
||||||
huri=new HttpURI(uri);
|
|
||||||
params = new MultiMap<>();
|
|
||||||
huri.decodeQueryTo(params,StandardCharsets.UTF_8);
|
|
||||||
assertEquals("data"+Utf8Appendable.REPLACEMENT+"here"+Utf8Appendable.REPLACEMENT,params.getValue("invalid",0));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExtB() throws Exception
|
public void testExtB() throws Exception
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2017 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.http;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.allOf;
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class SyntaxTest
|
||||||
|
{
|
||||||
|
@Test
|
||||||
|
public void testRequireValidRFC2616Token_Good()
|
||||||
|
{
|
||||||
|
String tokens[] = {
|
||||||
|
"name",
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
"n.a.m.e",
|
||||||
|
"na-me",
|
||||||
|
"+name",
|
||||||
|
"na*me",
|
||||||
|
"na$me",
|
||||||
|
"#name"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (String token : tokens)
|
||||||
|
{
|
||||||
|
Syntax.requireValidRFC2616Token(token, "Test Based");
|
||||||
|
// No exception should occur here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequireValidRFC2616Token_Bad()
|
||||||
|
{
|
||||||
|
String tokens[] = {
|
||||||
|
"\"name\"",
|
||||||
|
"name\t",
|
||||||
|
"na me",
|
||||||
|
"name\u0082",
|
||||||
|
"na\tme",
|
||||||
|
"na;me",
|
||||||
|
"{name}",
|
||||||
|
"[name]",
|
||||||
|
"\""
|
||||||
|
};
|
||||||
|
|
||||||
|
for (String token : tokens)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Syntax.requireValidRFC2616Token(token, "Test Based");
|
||||||
|
fail("RFC2616 Token [" + token + "] Should have thrown " + IllegalArgumentException.class.getName());
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
assertThat("Testing Bad RFC2616 Token [" + token + "]", e.getMessage(),
|
||||||
|
allOf(containsString("Test Based"),
|
||||||
|
containsString("RFC2616")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequireValidRFC6265CookieValue_Good()
|
||||||
|
{
|
||||||
|
String values[] = {
|
||||||
|
"value",
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
"val=ue",
|
||||||
|
"val-ue",
|
||||||
|
"\"value\"",
|
||||||
|
"val/ue",
|
||||||
|
"v.a.l.u.e"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (String value : values)
|
||||||
|
{
|
||||||
|
Syntax.requireValidRFC6265CookieValue(value);
|
||||||
|
// No exception should occur here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequireValidRFC6265CookieValue_Bad()
|
||||||
|
{
|
||||||
|
String values[] = {
|
||||||
|
"va\tlue",
|
||||||
|
"\t",
|
||||||
|
"value\u0000",
|
||||||
|
"val\u0082ue",
|
||||||
|
"va lue",
|
||||||
|
"va;lue",
|
||||||
|
"\"value",
|
||||||
|
"value\"",
|
||||||
|
"val\\ue",
|
||||||
|
"val\"ue",
|
||||||
|
"\""
|
||||||
|
};
|
||||||
|
|
||||||
|
for (String value : values)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Syntax.requireValidRFC6265CookieValue(value);
|
||||||
|
fail("RFC6265 Cookie Value [" + value + "] Should have thrown " + IllegalArgumentException.class.getName());
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
assertThat("Testing Bad RFC6265 Cookie Value [" + value + "]", e.getMessage(), containsString("RFC6265"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.http2</groupId>
|
<groupId>org.eclipse.jetty.http2</groupId>
|
||||||
<artifactId>http2-parent</artifactId>
|
<artifactId>http2-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.eclipse.jetty.http2</groupId>
|
<groupId>org.eclipse.jetty.http2</groupId>
|
||||||
<artifactId>http2-parent</artifactId>
|
<artifactId>http2-parent</artifactId>
|
||||||
<version>9.4.3-SNAPSHOT</version>
|
<version>9.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue