Merge remote-tracking branch 'origin/jetty-9.4.x' into issue-207
This commit is contained in:
commit
849ad7c917
113
VERSION.txt
113
VERSION.txt
|
@ -1,10 +1,112 @@
|
||||||
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
|
||||||
+ 1047 ReadPendingException and then thread death
|
+ 1047 ReadPendingException and then thread death
|
||||||
+ 1150 Rationalize the session tests
|
+ 1150 Rationalize the session tests
|
||||||
+ 1226 Undefined JETTY_LOGS breaks jetty.sh
|
+ 1226 Undefined JETTY_LOGS breaks jetty.sh
|
||||||
+ 1282 ByteArrayEndPointTest.testIdle() failure
|
+ 1282 ByteArrayEndPointTest.testIdle() failure
|
||||||
+ 1284 IllegalStateException updating session inactive interval
|
+ 1284 IllegalStateException updating session inactive interval
|
||||||
+ 1290 http2-hpack not visible in OSGi
|
+ 1290 http2-hpack not visible in OSGi
|
||||||
|
@ -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
|
||||||
|
@ -860,7 +859,26 @@ 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())
|
||||||
{
|
{
|
||||||
|
|
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,10 +725,20 @@ 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)
|
||||||
someToSuccess(exchange);
|
{
|
||||||
|
// No trailers or content to send, we are done.
|
||||||
|
someToSuccess(exchange);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendTrailers(exchange, lastCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -276,7 +276,17 @@ 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, chunkBuffer, contentBuffer);
|
||||||
endPoint.write(this, headerBuffer, contentBuffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (contentBuffer == null)
|
|
||||||
endPoint.write(this, headerBuffer, chunkBuffer);
|
|
||||||
else
|
|
||||||
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;
|
||||||
|
@ -138,8 +137,10 @@ 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.
|
||||||
|
|
|
@ -70,7 +70,7 @@ Logging API::
|
||||||
Slf4j Binding JAR::
|
Slf4j Binding JAR::
|
||||||
* Special JARs, created and maintained by the Slf4j project, that pretend to be the various Logging API implementation classes, but instead just route that Logging API's events to Slf4j to handle.
|
* Special JARs, created and maintained by the Slf4j project, that pretend to be the various Logging API implementation classes, but instead just route that Logging API's events to Slf4j to handle.
|
||||||
* There MAY be multiple Slf4j binding JARs present on the classpath at the same time.
|
* There MAY be multiple Slf4j binding JARs present on the classpath at the same time.
|
||||||
|
|
||||||
* For a single logging API, if you choose to use the Slf4j binding JAR, then you MUST NOT include the SLf4j adapter JAR or underlying logging framework in the classpath as well.
|
* For a single logging API, if you choose to use the Slf4j binding JAR, then you MUST NOT include the SLf4j adapter JAR or underlying logging framework in the classpath as well.
|
||||||
Slf4j Adapter Jar::
|
Slf4j Adapter Jar::
|
||||||
* These JARs are created and maintained by the Slf4j project and route Slf4j logging events to a specific underlying logging framework.
|
* These JARs are created and maintained by the Slf4j project and route Slf4j logging events to a specific underlying logging framework.
|
||||||
|
@ -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,10 +16,10 @@
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
//
|
//
|
||||||
|
|
||||||
package org.eclipse.jetty.server;
|
package org.eclipse.jetty.http;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The compliance for Cookie handling.
|
* The compliance for Cookie handling.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public enum CookieCompliance { RFC6265, RFC2965 }
|
public enum CookieCompliance { RFC6265, RFC2965 }
|
|
@ -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
|
||||||
|
|
|
@ -31,6 +31,14 @@ public class HttpStatusCodeTest
|
||||||
assertNull("Invalid code: 800", HttpStatus.getCode(800));
|
assertNull("Invalid code: 800", HttpStatus.getCode(800));
|
||||||
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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
@ -100,33 +99,6 @@ public class HttpURITest
|
||||||
assertThat(uri.getHost(),is("foo"));
|
assertThat(uri.getHost(),is("foo"));
|
||||||
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