Merge branch 'jetty-9.4.x'

This commit is contained in:
WalkerWatch 2017-12-19 12:30:18 -05:00
commit 8bdab72fc0
2 changed files with 66 additions and 148 deletions

View File

@ -17,21 +17,15 @@
[[alpn]]
=== Introducing ALPN
Application Layer Protocol Negotiation (ALPN) is a TLS extension that allows client and
server to negotiate the application protocol that they will use to communicate within
the encryption provided by TLS.
Application Layer Protocol Negotiation (ALPN) is a TLS extension that allows client and server to negotiate the application protocol that they will use to communicate within the encryption provided by TLS.
Any protocol can be negotiated by ALPN within a TLS connection; the protocols that
are most commonly negotiated are HTTP/2 and HTTP/1.1.
Any protocol can be negotiated by ALPN within a TLS connection; the protocols that are most commonly negotiated are HTTP/2 and HTTP/1.1.
In the Jetty project, ALPN is _used_ in two artifacts: `jetty-alpn-client` and
`jetty-alpn-server`, respectively for the client and for the server.
In the Jetty project, ALPN is _used_ in two artifacts: `jetty-alpn-client` and `jetty-alpn-server`, respectively for the client and for the server.
When using Jetty as a standalone server via the Jetty distribution, the `jetty-alpn-server`
artifact is automatically included in the server classpath by the Jetty module system.
When using Jetty as a standalone server via the Jetty distribution, the `jetty-alpn-server` artifact is automatically included in the server classpath by the Jetty module system.
When using Jetty embedded, the `jetty-alpn-client` and `jetty-alpn-server` artifacts
must be included in the classpath, respectively for client and server use cases.
When using Jetty embedded, the `jetty-alpn-client` and `jetty-alpn-server` artifacts must be included in the classpath, respectively for client and server use cases.
ALPN may be _provided_ to these two artifacts with the following three options:
@ -39,69 +33,47 @@ ALPN may be _provided_ to these two artifacts with the following three options:
* For JDK 8 or later, a provider based on the link:#conscrypt[Conscrypt security provider]
* For JDK 8 only, a provider based on modified OpenJDK classes
The latter, although hosted under the umbrella of the Jetty project, is independent of Jetty
(the Servlet Container); you can use it in any other Java network server.
The latter, although hosted under the umbrella of the Jetty project, is independent of Jetty (the Servlet Container); you can use it in any other Java network server.
Each provider above provides a _service_ implementation; Jetty uses the `ServiceLoader`
mechanism to load these service implementations.
The absence of implementations is an error at startup (see also the
link:#alpn-troubleshooting[troubleshooting section]).
Each provider above provides a _service_ implementation; Jetty uses the `ServiceLoader` mechanism to load these service implementations.
The absence of implementations is an error at startup (see also the link:#alpn-troubleshooting[troubleshooting section]).
When a new connection is created, an `SSLEngine` instance is associated to it; each
`SSLEngine` is passed all service implementations, until one accepts it.
When a new connection is created, an `SSLEngine` instance is associated to it; each `SSLEngine` is passed all service implementations, until one accepts it.
It is therefore possible to have multiple providers active at the same time, for example
the JDK 9 provider and the Conscrypt provider, and at runtime the correct one will be
chosen by the Jetty runtime.
It is therefore possible to have multiple providers active at the same time, for example the JDK 9 provider and the Conscrypt provider, and at runtime the correct one will be chosen by the Jetty runtime.
[[alpn-jdk9]]
==== ALPN and JDK 9
When using JDK 9 or later and Jetty as a standalone server via the Jetty distribution,
ALPN support is automatically enabled when the `http2` module is enabled.
This enables transitively the `alpn-9` module which puts the `jetty-alpn-java-server`
artifact in the server classpath, providing the ALPN JDK 9 service implementation.
When using JDK 9 or later and Jetty as a standalone server via the Jetty distribution, ALPN support is automatically enabled when the `http2` module is enabled.
This enables transitively the `alpn-9` module which puts the `jetty-alpn-java-server` artifact in the server classpath, providing the ALPN JDK 9 service implementation.
When using JDK 9 or later and Jetty embedded, the ALPN service implementation is
provided by the `jetty-alpn-java-client` and `jetty-alpn-java-server` artifacts,
respectively for client usage and server usage, and must be added to the classpath.
When using JDK 9 or later and Jetty embedded, the ALPN service implementation is provided by the `jetty-alpn-java-client` and `jetty-alpn-java-server` artifacts, respectively for client usage and server usage, and must be added to the classpath.
[[alpn-conscrypt]]
==== ALPN and Conscrypt
When using JDK 8 or later, you can use the https://conscrypt.org/[Conscrypt] security
provider to provide the ALPN service implementation.
When using JDK 8 or later, you can use the https://conscrypt.org/[Conscrypt] security provider to provide the ALPN service implementation.
Conscrypt binds natively to BoringSSL (a fork of OpenSSL by Google), so ALPN will be
supported via the support provided by BoringSSL (bundled together with Conscrypt).
Conscrypt binds natively to BoringSSL (a fork of OpenSSL by Google), so ALPN will be supported via the support provided by BoringSSL (bundled together with Conscrypt).
When using Jetty as a standalone server via the Jetty distribution, ALPN is enabled
by enabling the `conscrypt` module.
When using Jetty as a standalone server via the Jetty distribution, ALPN is enabled by enabling the `conscrypt` module.
When using Jetty embedded, ALPN is enabled by the `jetty-alpn-conscrypt-client` and
`jetty-alpn-conscrypt-server` artifacts, respectively for client usage and server usage.
In addition, you also need the Conscrypt artifacts, typically the
`org.conscrypt:conscrypt-openjdk-uber` artifact.
When using Jetty embedded, ALPN is enabled by the `jetty-alpn-conscrypt-client` and `jetty-alpn-conscrypt-server` artifacts, respectively for client usage and server usage.
In addition, you also need the Conscrypt artifacts, typically the `org.conscrypt:conscrypt-openjdk-uber` artifact.
All these artifacts must be added to the classpath.
[[alpn-openjdk8]]
==== ALPN and OpenJDK 8
When using JDKs based on OpenJDK 8 (for JDK 9 see link:#alpn-jdk9[above]), and you
do not or cannot use link:#conscrypt[Conscrypt], you can use Jetty's ALPN boot library
to provide the ALPN service implementation, via the `alpn-boot` artifact.
When using JDKs based on OpenJDK 8 (for JDK 9 see link:#alpn-jdk9[above]), and you do not or cannot use link:#conscrypt[Conscrypt], you can use Jetty's ALPN boot library to provide the ALPN service implementation, via the `alpn-boot` artifact.
The Jetty ALPN boot library modifies the relevant OpenJDK classes to add ALPN support
and provides an ALPN API that application can use to enable ALPN.
The Jetty ALPN boot library modifies the relevant OpenJDK classes to add ALPN support and provides an ALPN API that application can use to enable ALPN.
When using Jetty as a standalone server via the Jetty distribution, ALPN support is
automatically enabled when the `http2` module is enabled.
This enables transitively the `alpn-8` module which puts the `jetty-alpn-openjdk8-server`
artifact in the server classpath, providing the ALPN OpenJDK 8 service implementation.
When using Jetty as a standalone server via the Jetty distribution, ALPN support is automatically enabled when the `http2` module is enabled.
This enables transitively the `alpn-8` module which puts the `jetty-alpn-openjdk8-server` artifact in the server classpath, providing the ALPN OpenJDK 8 service implementation.
When using Jetty embedded, the ALPN support is provided by the
`jetty-alpn-openjdk8-client` and `jetty-alpn-openjdk8-server` artifacts, respectively
for client usage and server usage.
When using Jetty embedded, the ALPN support is provided by the `jetty-alpn-openjdk8-client` and `jetty-alpn-openjdk8-server` artifacts, respectively for client usage and server usage.
To get ALPN working with the Jetty ALPN Boot library, you need:
@ -116,27 +88,22 @@ Start the JVM as follows:
java -Xbootclasspath/p:<path_to_alpn_boot_jar> ...
----
Where `path_to_alpn_boot_jar` is the path on the file system for the `alpn-boot` artifact,
such as the one at the Maven coordinates `org.mortbay.jetty.alpn:alpn-boot`.
Where `path_to_alpn_boot_jar` is the path on the file system for the `alpn-boot` artifact, such as the one at the Maven coordinates `org.mortbay.jetty.alpn:alpn-boot`.
Be certain to get the link:#alpn-versions[ALPN boot artifact version that matches the version
of your JRE].
Be certain to get the link:#alpn-versions[ALPN boot artifact version that matches the version of your JRE].
[[alpn-osgi]]
===== Starting in OSGi
To use ALPN in an OSGi environment, in addition to what described above, you will also need
to deploy the `jetty-osgi-alpn` jar.
This jar contains a `Fragment-Host` directive that ensures the ALPN classes will be available
from the system bundle.
To use ALPN in an OSGi environment, in addition to what described above, you will also need to deploy the `jetty-osgi-alpn` jar.
This jar contains a `Fragment-Host` directive that ensures the ALPN classes will be available from the system bundle.
You can download the http://central.maven.org/maven2/org/eclipse/jetty/osgi/jetty-osgi-alpn/[jetty-osgi-alpn jar] from Maven Central.
[[alpn-troubleshooting]]
==== ALPN Troubleshooting
When starting the Jetty server, especially when using Jetty embedded, it may be possible
that you see an error similar to this:
When starting the Jetty server, especially when using Jetty embedded, it may be possible that you see an error similar to this:
[source, plain, subs="{sub-order}"]
----
@ -145,48 +112,34 @@ IllegalStateException: no ALPN processor
The error means that you don't have the ALPN dependencies setup correctly in your classpath.
For example, you may have the `jetty-alpn-java-server` artifact in the classpath (which is
correct when using JDK 9), but run your application with JDK 8.
For example, you may have the `jetty-alpn-java-server` artifact in the classpath (which is correct when using JDK 9), but run your application with JDK 8.
Another example is when you have correctly put the `alpn-boot` artifact in the boot
classpath, but you don't have the `jetty-alpn-openjdk8-server` artifact in the classpath.
Another example is when you have correctly put the `alpn-boot` artifact in the boot classpath, but you don't have the `jetty-alpn-openjdk8-server` artifact in the classpath.
[[alpn-openjdk8-details]]
==== Details about ALPN and OpenJDK 8
The following sections only refer to the API and implementation of ALPN using the Jetty
boot library.
The following sections only refer to the API and implementation of ALPN using the Jetty boot library.
The Jetty ALPN boot library is conceptually made of two parts: the ALPN APIs and the ALPN
implementation.
The Jetty ALPN boot library is conceptually made of two parts: the ALPN APIs and the ALPN implementation.
The ALPN API is provided by the `org.eclipse.jetty.alpn:alpn-api` artifact.
This artifact is only needed by application code that uses the ALPN APIs.
The ALPN implementation is provided by the `org.mortbay.jetty.alpn:alpn-boot` artifact
and consist of modifications to the OpenJDK classes.
The `org.mortbay.jetty.alpn:alpn-boot` artifact contains also the classes present
in the `org.eclipse.jetty.alpn:alpn-api` artifact.
The ALPN implementation is provided by the `org.mortbay.jetty.alpn:alpn-boot` artifact and consist of modifications to the OpenJDK classes.
The `org.mortbay.jetty.alpn:alpn-boot` artifact contains also the classes present in the `org.eclipse.jetty.alpn:alpn-api` artifact.
[[alpn-openjdk8-understanding]]
===== Understanding the ALPN API
Applications need to interact with ALPN TLS extension protocol negotiations.
For example, server applications need to know whether the client supports ALPN,
and client applications needs to know whether the server supports ALPN.
For example, server applications need to know whether the client supports ALPN, and client applications needs to know whether the server supports ALPN.
To implement this interaction, Jetty's ALPN implementation provides an API to
applications, hosted at Maven coordinates `org.eclipse.jetty.alpn:alpn-api`.
You need to declare this dependency as provided, because the `alpn-boot` jar
already includes it (see the previous section), and it is therefore available
from the boot classpath.
To implement this interaction, Jetty's ALPN implementation provides an API to applications, hosted at Maven coordinates `org.eclipse.jetty.alpn:alpn-api`.
You need to declare this dependency as provided, because the `alpn-boot` jar already includes it (see the previous section), and it is therefore available from the boot classpath.
The API consists of a single class, `org.eclipse.jetty.alpn.ALPN`, and applications
need to register instances of `SSLSocket` or `SSLEngine` with a `ClientProvider`
or `ServerProvider` (depending on whether the application is a client application
or server application).
Refer to `ALPN` Javadocs and to the examples below for further details about client
and server provider methods.
The API consists of a single class, `org.eclipse.jetty.alpn.ALPN`, and applications need to register instances of `SSLSocket` or `SSLEngine` with a `ClientProvider` or `ServerProvider` (depending on whether the application is a client application or server application).
Refer to `ALPN` Javadocs and to the examples below for further details about client and server provider methods.
[[alpn-openjdk8-client-example]]
==== Client Example
@ -219,8 +172,7 @@ ALPN.put(sslSocket, new ALPN.ClientProvider()
});
----
The ALPN implementation calls `ALPN.ClientProvider` methods `protocols()`,
`unsupported()` and `selected(String)`, so that the client application can:
The ALPN implementation calls `ALPN.ClientProvider` methods `protocols()`, `unsupported()` and `selected(String)`, so that the client application can:
* Decide whether to support ALPN
* Provide the protocols supported
@ -230,8 +182,7 @@ The ALPN implementation calls `ALPN.ClientProvider` methods `protocols()`,
[[alpn-openjdk8-server-example]]
==== Server Example
The example for `SSLEngine` is identical, and you just need to replace the `SSLSocket`
instance with an `SSLEngine` instance.
The example for `SSLEngine` is identical, and you just need to replace the `SSLSocket` instance with an `SSLEngine` instance.
[source, java, subs="{sub-order}"]
----
@ -253,8 +204,7 @@ ALPN.put(sslEngine, new ALPN.ServerProvider()
});
----
The ALPN implementation calls `ALPN.ServerProvider` methods `unsupported()`, and
`select(List<String>),` so that the server application can:
The ALPN implementation calls `ALPN.ServerProvider` methods `unsupported()`, and `select(List<String>),` so that the server application can:
* know whether the client supports ALPN.
* select one of the protocols the client supports.
@ -262,17 +212,14 @@ The ALPN implementation calls `ALPN.ServerProvider` methods `unsupported()`, and
[[alpn-openjdk8-implementation]]
==== Implementation Details
It is important that implementations of `ALPN.ServerProvider` and `ALPN.ClientProvider`
remove the `sslSocket` or `sslEngine` when the negotiation is complete, like shown in
the examples above.
It is important that implementations of `ALPN.ServerProvider` and `ALPN.ClientProvider` remove the `sslSocket` or `sslEngine` when the negotiation is complete, like shown in the examples above.
Failing to do so will cause a memory leak.
[[alpn-openjdk8-tests]]
==== Unit Tests
You can write and run unit tests that use the ALPN implementation.
The solution that we use with Maven is to specify an additional command line argument
to the Surefire plugin:
The solution that we use with Maven is to specify an additional command line argument to the Surefire plugin:
[source, xml, subs="{sub-order}"]
----
@ -312,25 +259,20 @@ You can enable debug logging for the ALPN implementation in this way:
ALPN.debug = true;
....
Since the ALPN class is in the boot classpath, we chose not to use logging libraries
because we do not want to override application logging library choices; therefore the
logging is performed directly on `System.err`.
Since the ALPN class is in the boot classpath, we chose not to use logging libraries because we do not want to override application logging library choices; therefore thelogging is performed directly on `System.err`.
[[alpn-openjdk8-license-details]]
==== License Details
The ALPN implementation relies on modification of a few OpenJDK classes and on a few
new classes that need to live in the `sun.security.ssl` package.
These classes are released under the same GPLv2+exception license of OpenJDK.
The ALPN implementation relies on modification of a few OpenJDK classes and on a few new classes that need to live in the `sun.security.ssl` package.
These classes are released under the same `GPLv2+exception` license of OpenJDK.
The ALPN class and its nested classes are released under same license as the classes
of the Jetty project.
The ALPN class and its nested classes are released under same license as the classes of the Jetty project.
[[alpn-versions]]
==== Versions
The ALPN implementation, relying on modifications of OpenJDK classes, updates every
time there are updates to the modified OpenJDK classes.
The ALPN implementation, relying on modifications of OpenJDK classes, updates every time there are updates to the modified OpenJDK classes.
.ALPN vs. OpenJDK versions
[cols=",",options="header",]
@ -383,8 +325,7 @@ time there are updates to the modified OpenJDK classes.
[[alpn-build]]
==== How to build ALPN
This section is for Jetty developers that need to update the ALPN implementation with
the OpenJDK versions.
This section is for Jetty developers that need to update the ALPN implementation with the OpenJDK versions.
Clone the OpenJDK repository with the following command:
@ -406,6 +347,4 @@ $ ./make/scripts/hgforest.sh update <tag-name>
The list of OpenJDK tags can be obtained from this page:
http://hg.openjdk.java.net/jdk8u/jdk8u/tags[OpenJDK 8 Tags].
You will then need to compare and incorporate the OpenJDK source changes into the
modified OpenJDK classes at the
https://github.com/jetty-project/jetty-alpn[ALPN GitHub Repository], branch `master`.
You will then need to compare and incorporate the OpenJDK source changes into the modified OpenJDK classes at the https://github.com/jetty-project/jetty-alpn[ALPN GitHub Repository], branch `master`.

View File

@ -17,14 +17,10 @@
[[http2-configuring-push]]
=== Configuring HTTP/2 Push
HTTP/2 Push is a mechanism that allows the server to send multiple resources
to the client for a single client request.
This will reduce the amount of round-trips necessary to retrieve all the
resources that make up a web page and can significantly improve the page load time.
HTTP/2 Push is a mechanism that allows the server to send multiple resources to the client for a single client request.
This will reduce the amount of round-trips necessary to retrieve all the resources that make up a web page and can significantly improve the page load time.
HTTP/2 Push can be automated in your application by configuring a
link:{JDURL}/org/eclipse/jetty/servlets/PushCacheFilter.html[`PushCacheFilter`]
in the `web.xml`, in this way:
HTTP/2 Push can be automated in your application by configuring a link:{JDURL}/org/eclipse/jetty/servlets/PushCacheFilter.html[`PushCacheFilter`] in the `web.xml`, in this way:
[source, xml, subs="{sub-order}"]
----
@ -51,38 +47,21 @@ in the `web.xml`, in this way:
</web-app>
----
`PushCacheFilter` analyzes the HTTP requests for resources that arrive to your web
application.
Some of these requests contain the HTTP `Referer` header that points to a resource
that has been requested previously.
`PushCacheFilter` analyzes the HTTP requests for resources that arrive to your web application.
Some of these requests contain the HTTP `Referer` header that points to a resource that has been requested previously.
This allows the `PushCacheFilter` to organize resources in a tree, for example
a root `index.html` resource having two children resources, `styles.css` and
`application.js`, and `styles.css` having a child resource, `background.png`.
The root resource is called the _primary_ resource, while descendant resources
are called _secondary_ resources.
This allows the `PushCacheFilter` to organize resources in a tree, for example a root `index.html` resource having two children resources, `styles.css` and `application.js`, and `styles.css` having a child resource, `background.png`.
The root resource is called the _primary_ resource, while descendant resources are called _secondary_ resources.
The resource tree is built using a time window so that when a root resource is
requested, only subsequent requests that are made within the time window will
be added to the resource tree.
The resource tree can also be limited in size so that the number of secondary
resources associated to a primary resource is limited.
The resource tree is built using a time window so that when a root resource is requested, only subsequent requests that are made within the time window will be added to the resource tree.
The resource tree can also be limited in size so that the number of secondary resources associated to a primary resource is limited.
By default, only the resource _path_ (without the _query_ string) is used to
associate secondary resources to the primary resource, but you can configure
`PushCacheFilter` to take the query string into account.
By default, only the resource _path_ (without the _query_ string) is used to associate secondary resources to the primary resource, but you can configure `PushCacheFilter` to take the query string into account.
`PushCacheFilter` can be configured with the following `init-params`:
* `associatePeriod`: the time window, in milliseconds, within which a request
for a secondary resource will be associated to a primary resource; defaults to
4000 ms
* `maxAssociations`: the max number of secondary resources that may be
associated to a primary resource; defaults to 16
* `hosts`: a comma separated list of hosts that are allowed in the `Referer`
header; defaults to the host in the `Host` header
* `ports`: a comma separated list of ports that are allowed in the `Referer`
header; defaults to the port in the `Host` header
* `useQueryInKey`: a boolean indicating whether the query string of the
request should be considered when associating secondary resources to
primary resources; defaults to false
* `associatePeriod`: the time window, in milliseconds, within which a request for a secondary resource will be associated to a primary resource; defaults to 4000 ms
* `maxAssociations`: the max number of secondary resources that may be associated to a primary resource; defaults to 16
* `hosts`: a comma separated list of hosts that are allowed in the `Referer` header; defaults to the host in the `Host` header
* `ports`: a comma separated list of ports that are allowed in the `Referer` header; defaults to the port in the `Host` header
* `useQueryInKey`: a boolean indicating whether the query string of the request should be considered when associating secondary resources to primary resources; defaults to `false`