From c2df8c172b89f0859f19a472de6199e2ae5ec344 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Wed, 30 Sep 2020 10:37:21 +0200 Subject: [PATCH 1/3] Improvements to the Jetty documentation. Ported the HTTP/2 documentation. Signed-off-by: Simone Bordet --- .../src/main/config/modules/alpn.mod | 15 +- .../main/asciidoc/old_docs/http2/chapter.adoc | 3 - .../old_docs/http2/configuring-http2.adoc | 72 --------- .../old_docs/http2/enabling-http2.adoc | 75 --------- .../asciidoc/old_docs/http2/introduction.adoc | 54 ------- .../operations-guide/introduction.adoc | 3 + .../operations-guide/keystore/chapter.adoc | 23 +++ .../operations-guide/modules/module-alpn.adoc | 30 ++++ .../modules/module-http2.adoc | 37 +++++ .../modules/module-http2c.adoc | 30 ++++ .../operations-guide/protocols/chapter.adoc | 1 + .../protocols/protocols-http.adoc | 2 +- .../protocols/protocols-http2.adoc | 153 ++++++++++++++++++ .../protocols/protocols-http2c.adoc | 72 +++++++++ .../protocols/protocols-http2s.adoc | 65 ++++++++ .../protocols/protocols-https.adoc | 14 +- .../protocols/protocols-ssl.adoc | 9 +- .../src/main/config/etc/jetty-http2c.xml | 1 + .../src/main/config/modules/http2.mod | 18 +-- .../src/main/config/modules/http2c.mod | 19 ++- .../java/org/eclipse/jetty/start/Module.java | 4 +- 21 files changed, 461 insertions(+), 239 deletions(-) delete mode 100644 jetty-documentation/src/main/asciidoc/old_docs/http2/configuring-http2.adoc delete mode 100644 jetty-documentation/src/main/asciidoc/old_docs/http2/enabling-http2.adoc delete mode 100644 jetty-documentation/src/main/asciidoc/old_docs/http2/introduction.adoc create mode 100644 jetty-documentation/src/main/asciidoc/operations-guide/keystore/chapter.adoc create mode 100644 jetty-documentation/src/main/asciidoc/operations-guide/modules/module-alpn.adoc create mode 100644 jetty-documentation/src/main/asciidoc/operations-guide/modules/module-http2.adoc create mode 100644 jetty-documentation/src/main/asciidoc/operations-guide/modules/module-http2c.adoc create mode 100644 jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2.adoc create mode 100644 jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2c.adoc create mode 100644 jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2s.adoc diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn.mod index 9fe36cb54b7..eaa55ebe73a 100644 --- a/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn.mod +++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/alpn.mod @@ -1,7 +1,5 @@ -# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html - [description] -Enables the ALPN (Application Layer Protocol Negotiation) TLS extension. +Enables the handling of the ALPN (Application Layer Protocol Negotiation) TLS extension. [tag] connector @@ -20,11 +18,12 @@ lib/jetty-alpn-server-${jetty.version}.jar etc/jetty-alpn.xml [ini-template] -## Overrides the order protocols are chosen by the server. -## The default order is that specified by the order of the -## modules declared in start.ini. +# tag::documentation[] +## Specifies the ordered list of application protocols supported by the server. +## The default list is specified by the list of the protocol modules that have +## been enabled, and the order is specified by the module dependencies. # jetty.alpn.protocols=h2,http/1.1 -## Specifies what protocol to use when negotiation fails. +## Specifies the protocol to use when the ALPN negotiation fails. # jetty.alpn.defaultProtocol=http/1.1 - +# end::documentation[] diff --git a/jetty-documentation/src/main/asciidoc/old_docs/http2/chapter.adoc b/jetty-documentation/src/main/asciidoc/old_docs/http2/chapter.adoc index 09ca1ed7e88..eefe585b2de 100644 --- a/jetty-documentation/src/main/asciidoc/old_docs/http2/chapter.adoc +++ b/jetty-documentation/src/main/asciidoc/old_docs/http2/chapter.adoc @@ -19,8 +19,5 @@ [[http2]] == HTTP/2 -include::introduction.adoc[] -include::enabling-http2.adoc[] -include::configuring-http2.adoc[] include::configuring-push.adoc[] include::configuring-haproxy.adoc[] diff --git a/jetty-documentation/src/main/asciidoc/old_docs/http2/configuring-http2.adoc b/jetty-documentation/src/main/asciidoc/old_docs/http2/configuring-http2.adoc deleted file mode 100644 index 49db2c5c90e..00000000000 --- a/jetty-documentation/src/main/asciidoc/old_docs/http2/configuring-http2.adoc +++ /dev/null @@ -1,72 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. -// -// This program and the accompanying materials are made available under -// the terms of the Eclipse Public License 2.0 which is available at -// https://www.eclipse.org/legal/epl-2.0 -// -// This Source Code may also be made available under the following -// Secondary Licenses when the conditions for such availability set -// forth in the Eclipse Public License, v. 2.0 are satisfied: -// the Apache License v2.0 which is available at -// https://www.apache.org/licenses/LICENSE-2.0 -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// ======================================================================== -// - -[[http2-configuring]] -=== Configuring HTTP/2 - -Enabling the HTTP/2 module in the Jetty server does not create a HTTP/2 specific connector, but rather it adds a HTTP/2 Connection factory to an -existing connector. -Thus configuring HTTP/2 is a combination of configuring common properties on the connector and HTTP/2 specific properties on the connection factory. -The modules and XML files involved can be seen with the following commands: - -[source,screen, subs="{sub-order}"] -.... -$ java -jar $JETTY_HOME/start.jar --list-modules - ... - 1) alpn-impl - ... - 2) http ${jetty.base}/start.d/http.ini - 2) ssl ${jetty.base}/start.d/ssl.ini - 3) alpn ${jetty.base}/start.d/alpn.ini - 3) http2c ${jetty.base}/start.d/http2c.ini - ... - 4) http2 ${jetty.base}/start.d/http2.ini - 5) https ${jetty.base}/start.d/https.ini - -$ java -jar $JETTY_HOME/start.jar --list-config - ... - ${jetty.home}/etc/jetty-ssl.xml - ${jetty.home}/etc/jetty-ssl-context.xml - ${jetty.home}/etc/jetty-alpn.xml - ${jetty.home}/etc/jetty-http2c.xml - ${jetty.home}/etc/jetty-http.xml - ... - ${jetty.home}/etc/jetty-http2.xml - ${jetty.home}/etc/jetty-https.xml -.... - -The common properties associated with connectors (host,port, timeouts, etc.) can be set in the module ini files (or `start.ini` if `--add-to-start` was used): `${jetty.base}/start.d/http.ini` and `${jetty.base}/start.d/ssl.ini`. -These properties are instantiated in the associated XML files: `${jetty.home}/etc/jetty-http.xml`; `${jetty.home}/etc/jetty-ssl.xml`, plus the SSL keystore is instantiated in `${jetty.home}/etc/jetty-ssl-context.xml`. - -____ -[NOTE] -If you are planning to edit XML files, make sure to copy them to your `{$jetty.base}/etc/` directory before doing so. -The XML files that come with the Jetty distribution should *not* be modified directly. -____ - -HTTP/2 specific properties can be set in the module ini files: `${jetty.base}/start.d/http2.ini` and `${jetty.base}/start.d/http2c.ini`, which are instantiated in the associated XML files: `${jetty.home}/etc/jetty-http2.xml`; `${jetty.home}/etc/jetty-http2c.xml`, respectively. -Currently there are very few HTTP/2 configuration properties and the default values are reasonable: - -.HTTP/2 Configuration Properties -[cols=",",options="header",] -|======================================================================= -|Property |Description -|jetty.http2.maxConcurrentStreams |The maximum number of concurrently open streams allowed on a single HTTP/2 connection (default 128). Larger values increase parallelism but cost a memory commitment. -|jetty.http2.initialSessionRecvWindow |The initial receive flow control window size for a new session (default 1048576). Larger values may allow greater throughput but also risk head of line blocking if TCP/IP flow control is triggered. -|jetty.http2.initialStreamRecvWindow |The initial receive flow control window size for a new stream (default 524288). Larger values may allow greater throughput but also risk head of line blocking if TCP/IP flow control is triggered. -|======================================================================= diff --git a/jetty-documentation/src/main/asciidoc/old_docs/http2/enabling-http2.adoc b/jetty-documentation/src/main/asciidoc/old_docs/http2/enabling-http2.adoc deleted file mode 100644 index ebde323405d..00000000000 --- a/jetty-documentation/src/main/asciidoc/old_docs/http2/enabling-http2.adoc +++ /dev/null @@ -1,75 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. -// -// This program and the accompanying materials are made available under -// the terms of the Eclipse Public License 2.0 which is available at -// https://www.eclipse.org/legal/epl-2.0 -// -// This Source Code may also be made available under the following -// Secondary Licenses when the conditions for such availability set -// forth in the Eclipse Public License, v. 2.0 are satisfied: -// the Apache License v2.0 which is available at -// https://www.apache.org/licenses/LICENSE-2.0 -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// ======================================================================== -// - -[[http2-enabling]] -=== Enabling HTTP/2 - -This section is written assuming that a link:#startup-base-and-home[Jetty base directory] is being used. -A demo Jetty base that supports HTTP/1, HTTPS/1 and deployment from a webapps directory can be created with the commands: - -[source, screen, subs="{sub-order}"] -.... -$ JETTY_BASE=http2-demo -$ mkdir $JETTY_BASE -$ cd $JETTY_BASE -$ java -jar $JETTY_HOME/start.jar --add-to-start=http,https,deploy,test-keystore -.... - -The commands above create a `$JETTY_BASE` directory called `http2-demo`, and initializes the `http,` `https` and `deploy` modules (and their dependencies) to run a typical Jetty Server on port 8080 (for HTTP/1) and 8443 (for HTTPS/1). -Note that the `test-keystore` module downloads a demo keystore file with a self signed certificate, which needs to be replaced by a Certificate Authority issued certificate for real deployment. -A keystore can also be added by enabling and configuring the `ssl` module. - -To add HTTP/2 to this demo base, it is just a matter of enabling the `http2` module with the following command: - -[source, screen, subs="{sub-order}"] -.... -$ java -jar $JETTY_HOME/start.jar --add-to-start=http2 -.... - -This command does not create a new connector, but instead simply adds the HTTP/2 protocol to the existing HTTPS/1 connector, so that it now supports both protocols on port 8443. -To do this, it also transitively enables the ALPN module for protocol negotiation. -The support for each protocol can be seen in the info logging when the server is started: - -[source,screen, subs="{sub-order}"] ----- -$ java -jar $JETTY_HOME/start.jar -... -2015-06-17 14:16:12.549:INFO:oejs.ServerConnector:main: Started ServerConnector@34c9c77f{HTTP/1.1,[http/1.1]}{0.0.0.0:8080} -2015-06-17 14:16:12.782:INFO:oejs.ServerConnector:main: Started ServerConnector@711f39f9{SSL,[ssl, alpn, h2, h2-17, http/1.1]}{0.0.0.0:8443} -... ----- - -This log shows that port 8080 supports only HTTP/1.1 (which by specification includes HTTP/1.0 support), while port 8443 supports the SSL protocol, with ALPN negotiation to select between several versions of HTTP/2 (h2 & the draft h2-17) and HTTP/1.1. -What is not shown is that HTTP/1.1 is the default ALPN protocol, so that if a client connects that does not speak ALPN, then HTTP/1.1 will be assumed. - -A browser can now be pointed at `https://localhost:8443/` and if it supports HTTP/2 then it will be used (often indicated by a lightening bolt icon in the address bar). -Note that a browser pointed at this server with URL starting with `http://localhost:8080/` will still talk HTTP/1.1, as HTTP/2 has not been enabled on the plain text connector. - -HTTP/2 can be enabled on the plain text connector and the server restarted with the following command: - -[source,screen] -.... -$ java -jar $JETTY_HOME/start.jar --add-to-start=http2c -$ java -jar $JETTY_HOME/start.jar -.. -2015-06-17 14:16:12.549:INFO:oejs.ServerConnector:main: Started ServerConnector@6f32cd1e{HTTP/1.1,[http/1.1, h2c, h2c-17]}{0.0.0.0:8080} -2015-06-17 14:16:12.782:INFO:oejs.ServerConnector:main: Started ServerConnector@711f39f9{SSL,[ssl, alpn, h2, h2-17, http/1.1]}{0.0.0.0:8443} -.. -.... - -No major browser currently supports plain text HTTP/2, so the 8080 port will only be able to use HTTP/2 with specific clients (eg `curl`) that use the upgrade mechanism or assume HTTP/2. diff --git a/jetty-documentation/src/main/asciidoc/old_docs/http2/introduction.adoc b/jetty-documentation/src/main/asciidoc/old_docs/http2/introduction.adoc deleted file mode 100644 index 2c81f182022..00000000000 --- a/jetty-documentation/src/main/asciidoc/old_docs/http2/introduction.adoc +++ /dev/null @@ -1,54 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. -// -// This program and the accompanying materials are made available under -// the terms of the Eclipse Public License 2.0 which is available at -// https://www.eclipse.org/legal/epl-2.0 -// -// This Source Code may also be made available under the following -// Secondary Licenses when the conditions for such availability set -// forth in the Eclipse Public License, v. 2.0 are satisfied: -// the Apache License v2.0 which is available at -// https://www.apache.org/licenses/LICENSE-2.0 -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// ======================================================================== -// - -[[http2-introduction]] -=== Introducing HTTP/2 - -Jetty supports both a client and a server implementation for the HTTP/2 protocol as defined by http://tools.ietf.org/html/rfc7540[RFC 7540]. - -The requirements for running HTTP/2 are JDK 8 or greater, and typically also ALPN support (see xref:alpn-chapter[]). - -A server deployed over TLS (SSL) normally advertises the HTTP/2 protocol via the TLS extension Application Layer Protocol Negotiation link:#alpn[(ALPN)]. - -____ -[NOTE] -To use HTTP/2 in Jetty via a TLS connector you need to add the link:#alpn-starting[ALPN boot jar] in the boot classpath. -This is done automatically when using the Jetty distribution's start.jar link:#startup-modules[module system], but must be configured directly otherwise. -____ - -[[http2-security-update]] -==== Jetty HTTP/2 Security Update - -In mid-2019, there were a link:#security-reports[number of CVEs] were issued warning against vulnerable HTTP/2 implementations. These CVEs (CVE-2019-9511 thru CVE-2019-9518) generally centered around attackers manipulating and flooding HTTP/2 servers and creating a denial of service (DOS). These vulnerabilities were patched with Jetty 9.4.21. - -As a result of these CVEs, Jetty introduced a new, configurable denial of service (DOS) protection feature in Jetty 9.4.22. - -Jetty’s HTTP/2 implementation now features a new Rate Control parameter, `jetty.http2.rateControl.maxEventsPerSecond`, that defaults to 20 events per second, per connection for all pings, bad frames, settings frames, priority changes etc. - - -[[http2-modules]] -==== Jetty HTTP/2 Sub Projects - -The Jetty HTTP/2 implementation consists of the following sub-projects (each producing a jar file): - -1. `http2-common`: Contains the HTTP/2 API and a partial implementation shared across other modules. -2. `http2-hpack`: Contains the HTTP/2 HPACK implementation for HTTP header compression. -3. `http2-server`: Provides the server-side implementation of HTTP/2. -4. `http2-client`: Provides the implementation of HTTP/2 client with a low level HTTP/2 API, dealing with HTTP/2 streams, frames, etc. -5. `http2-http-client-transport`: Provides the implementation of the HTTP/2 transport for `HttpClient` (see xref:client-http[this section]). -Applications can use the higher level API provided by `HttpClient` to send HTTP requests and receive HTTP responses, and the HTTP/2 transport will take care of converting them in HTTP/2 format (see also https://webtide.com/http2-support-for-httpclient/[this blog entry]). diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/introduction.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/introduction.adoc index a9fe1011160..392b8f4e76f 100644 --- a/jetty-documentation/src/main/asciidoc/operations-guide/introduction.adoc +++ b/jetty-documentation/src/main/asciidoc/operations-guide/introduction.adoc @@ -30,6 +30,7 @@ If you are new to Eclipse Jetty, read xref:og-begin[here] to download, install, If you know Eclipse Jetty already, jump to a feature: * xref:og-sessions[HTTP Session Caching and Clustering] +* xref:og-protocols-http2[HTTP/2 Support] TODO @@ -41,6 +42,8 @@ TODO * xref:og-protocols-http[Configure Clear-Text HTTP/1.1] * xref:og-protocols-https[Configure Secure HTTP/1.1 (https)] +* xref:og-protocols-http2c[Configure Clear-Text HTTP/2] +* xref:og-protocols-http2s[Configure Secure HTTP/2] TODO diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/keystore/chapter.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/keystore/chapter.adoc new file mode 100644 index 00000000000..74693b7a560 --- /dev/null +++ b/jetty-documentation/src/main/asciidoc/operations-guide/keystore/chapter.adoc @@ -0,0 +1,23 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[og-keystore]] +=== Configuring KeyStores + +TODO +// TODO: see old_docs/connectors/configuring-ssl.adoc diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-alpn.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-alpn.adoc new file mode 100644 index 00000000000..44665f51c60 --- /dev/null +++ b/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-alpn.adoc @@ -0,0 +1,30 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[og-module-alpn]] +==== Module `alpn` + +The `alpn` module enables support for the ALPN negotiation mechanism of the TLS protocol. + +You can configure the list of application protocols negotiated by the ALPN mechanism, as well as the default protocol to use if the ALPN negotiation fails (for example, the client does not support ALPN). + +The module properties are: + +---- +include::{JETTY_HOME}/modules/alpn.mod[tags=documentation] +---- diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-http2.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-http2.adoc new file mode 100644 index 00000000000..30dc14d7518 --- /dev/null +++ b/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-http2.adoc @@ -0,0 +1,37 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[og-module-http2]] +==== Module `http2` + +The `http2` module enables support for the secure HTTP/2 protocol. + +The module properties are: + +---- +include::{JETTY_HOME}/modules/http2.mod[tags=documentation] +---- + +// tag::rate-control[] +The `jetty.http2.rateControl.maxEventsPerSecond` property controls the number of "bad" or "unnecessary" frames that a client may send before the server closes the connection (with code link:https://tools.ietf.org/html/rfc7540#section-7[`ENHANCE_YOUR_CALM`]) to avoid a denial of service. + +For example, an attacker may send empty `SETTINGS` frames to a server in a tight loop. +While the `SETTINGS` frames don't change the server configuration and each of them is somehow harmless, the server will be very busy processing them because they are sent by the attacker one after the other, causing a CPU spike and eventually a denial of service (as all CPUs will be busy processing empty `SETTINGS` frames). + +The same attack may be performed with `PRIORITY` frames, empty `DATA` frames, `PING` frames, etc. +// end::rate-control[] diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-http2c.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-http2c.adoc new file mode 100644 index 00000000000..5b1a435326d --- /dev/null +++ b/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-http2c.adoc @@ -0,0 +1,30 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[og-module-http2c]] +==== Module `http2c` + +The `http2c` module enables support for the clear-text HTTP/2 protocol. + +The module properties are: + +---- +include::{JETTY_HOME}/modules/http2c.mod[tags=documentation] +---- + +include::module-http2.adoc[tags=rate-control] diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/chapter.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/chapter.adoc index e1c61b3ff73..679f597831d 100644 --- a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/chapter.adoc +++ b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/chapter.adoc @@ -38,6 +38,7 @@ $ java -jar $JETTY_HOME/start.jar --list-modules=connector include::protocols-http.adoc[] include::protocols-https.adoc[] +include::protocols-http2.adoc[] include::protocols-ssl.adoc[] // TODO: old_docs/connectors/*.adoc diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http.adoc index 392141dc059..d2e01a5db6b 100644 --- a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http.adoc +++ b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http.adoc @@ -63,7 +63,7 @@ $ java -jar $JETTY_HOME/start.jar --add-module=server Now the `$JETTY_BASE` directory looks like this: -[source,subs=quotes] +[source] ---- JETTY_BASE ├── resources diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2.adoc new file mode 100644 index 00000000000..4df02b34ca1 --- /dev/null +++ b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2.adoc @@ -0,0 +1,153 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[og-protocols-http2]] +==== Configuring HTTP/2 + +link:https://tools.ietf.org/html/rfc7540[HTTP/2] is the successor of the HTTP/1.1 protocol, but it is quite different from HTTP/1.1: where HTTP/1.1 is a duplex, text-based protocol, HTTP/2 is a multiplex, binary protocol. + +Because of these fundamental differences, a client and a server need to _negotiate_ what version of the HTTP protocol they speak, based on what versions each side supports. + +To ensure maximum compatibility, and reduce the possibility that an intermediary that only understands HTTP/1.1 will close the connection when receiving unrecognized HTTP/2 bytes, HTTP/2 is typically deployed over secure connections, using the TLS protocol to wrap HTTP/2. + +IMPORTANT: Browsers only support secure HTTP/2. + +The protocol negotiation is performed by the link:https://tools.ietf.org/html/rfc7301[ALPN TLS extension]: the client advertises the list of protocols it can speak, and the server communicates to the client the protocol chosen by the server. + +For example, you can have a client that only supports HTTP/1.1 and a server that supports both HTTP/1.1 and HTTP/2: + +[plantuml] +---- +skinparam backgroundColor transparent +skinparam monochrome true +skinparam shadowing false + +participant "client\nsupports\nhttp/1.1" as client +participant "server\nsupports\nhttp/1.1 & http/2" as server + +group TLS handshake +client -> server : ClientHello (alpn=[http/1.1]) +server -> server : picks http/1.1 +server -> client : ServerHello (alpn=http/1.1) +...rest of TLS handshake... +end +group TLS HTTP/1.1 +client -> server : HTTP/1.1 GET +server -> client : HTTP/1.1 200 +end +---- + +Nowadays, it's common that both clients and servers support HTTP/2, so servers prefer HTTP/2 as the protocol to speak: + +[plantuml] +---- +skinparam backgroundColor transparent +skinparam monochrome true +skinparam shadowing false + +participant "client\nsupports\nhttp/1.1 & http/2" as client +participant "server\nsupports\nhttp/1.1 & http/2" as server + +group TLS handshake +client -> server : ClientHello (alpn=[http/1.1,h2]) +server -> server : picks http/2 +server -> client : ServerHello (alpn=h2) +...rest of TLS handshake... +end +group TLS HTTP/2 +client -> server : HTTP/2 GET +server -> client : HTTP/2 200 +end +---- + +When you configure a connector with the HTTP/2 protocol, you typically want to also configure the HTTP/1.1 protocol. +The reason to configure both protocols is that you typically do not control the clients: for example an old browser that does not support HTTP/2, or a monitoring console that performs requests using HTTP/1.1, or a heartbeat service that performs a single HTTP/1.0 request to verify that the server is alive. + +==== Secure vs Clear-Text HTTP/2 + +Deciding whether you want to configure Jetty with xref:og-protocols-http2s[secure HTTP/2] or xref:og-protocols-http2c[clear-text HTTP/2] depends on your use case. + +You want to configure secure HTTP/2 when Jetty is exposed directly to browsers, because browsers only support secure HTTP/2. + +[plantuml] +---- +skinparam backgroundColor transparent +skinparam monochrome true +skinparam shadowing false +skinparam roundCorner 10 + +rectangle browser +cloud internet +rectangle jetty + +jetty <--> internet : TLS+HTTP/2 +internet <--> browser : TLS+HTTP/2 +---- + +You may configure clear-text HTTP/2 (mostly for performance reasons) if you offload TLS at a load balancer (for example, link:https://haproxy.org/[HAProxy]) or at a reverse proxy (for example, link:https://nginx.org/[nginx]). + +[plantuml] +---- +skinparam backgroundColor transparent +skinparam monochrome true +skinparam shadowing false +skinparam roundCorner 10 + +rectangle browser +cloud internet +rectangle haproxy +rectangle jetty + +note right of haproxy: TLS offload + +jetty <--> haproxy : HTTP/2 (clear-text) +haproxy <--> internet : TLS+HTTP/2 +internet <--> browser : TLS+HTTP/2 +---- + +You may configure clear-text HTTP/2 (mostly for performance reasons) to call microservices deployed to different Jetty servers (although you may want to use secure HTTP/2 for confidentiality reasons). + +[plantuml] +---- +skinparam backgroundColor transparent +skinparam monochrome true +skinparam shadowing false +skinparam roundCorner 10 + +rectangle browser +cloud internet +rectangle haproxy +rectangle jetty +rectangle microservice1 +rectangle microservice2 +rectangle microservice3 + +note right of haproxy: TLS offload + +internet <--> browser : TLS+HTTP/2 +haproxy <--> internet : TLS+HTTP/2 +jetty <--> haproxy : HTTP/2 (clear-text) +microservice1 <--> jetty : HTTP/2 +microservice2 <--> jetty : HTTP/2 +microservice3 <--> jetty : HTTP/2 +microservice2 <--> microservice3 : HTTP/2 +microservice1 <--> microservice3 : HTTP/2 +---- + +include::protocols-http2s.adoc[] +include::protocols-http2c.adoc[] diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2c.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2c.adoc new file mode 100644 index 00000000000..8909f119f9e --- /dev/null +++ b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2c.adoc @@ -0,0 +1,72 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[og-protocols-http2c]] +==== Configuring Clear-Text HTTP/2 + +When you enable clear-text HTTP/2 you typically want to enable also clear-text HTTP/1.1, for backwards compatibility reasons and to allow clients to link:https://tools.ietf.org/html/rfc7540#section-3.2[upgrade] from HTTP/1.1 to HTTP/2. + +You need to enable: + +* the `http` Jetty module, which provides the clear-text connector and adds the HTTP/1.1 protocol to the clear-text connector +* the `http2c` Jetty module, which adds the HTTP/2 protocol to the clear-text connector + +---- +$ java -jar $JETTY_HOME/start.jar --add-modules=http,http2c +---- + +Starting Jetty yields: + +---- +$ java -jar $JETTY_HOME/start.jar +---- +[source,subs=quotes] +---- +2020-09-30 09:18:36.322:INFO :oejs.Server:main: jetty-10.0.0-SNAPSHOT; built: 2020-09-29T22:40:09.015Z; git: ba5f91fe00a68804a586b7dd4e2520c8c948dcc8; jvm 15+36-1562 +2020-09-30 09:18:36.349:INFO :oejs.AbstractConnector:main: Started ServerConnector@636be97c##{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:8080}## +2020-09-30 09:18:36.361:INFO :oejs.Server:main: Started Server@3c72f59f{STARTING}[10.0.0-SNAPSHOT,sto=5000] @526ms +---- + +Note how Jetty is listening on port `8080` and the protocols supported are HTTP/1.1 and `h2c` (i.e. clear-text HTTP/2). + +With this configuration, browsers and client applications will be able to connect to port `8080` using: + +* HTTP/1.1 directly (e.g. `curl --http1.1 ++http://localhost:8080++`): +---- +GET / HTTP/1.1 +Host: localhost:8080 +---- +* HTTP/1.1 with upgrade to HTTP/2 (e.g. `curl --http2 ++http://localhost:8080++`): +---- +GET / HTTP/1.1 +Host: localhost:8080 +Connection: Upgrade, HTTP2-Settings +Upgrade: h2c +HTTP2-Settings: +---- +* HTTP/2 directly (e.g. `curl --http2-prior-knowledge ++http://localhost:8080++`): +---- +50 52 49 20 2a 20 48 54 54 50 2f 32 2e 30 0d 0a +0d 0a 53 4d 0d 0a 0d 0a 00 00 12 04 00 00 00 00 +00 00 03 00 00 00 64 00 04 40 00 00 00 00 02 00 +00 00 00 00 00 1e 01 05 00 00 00 01 82 84 86 41 +8a a0 e4 1d 13 9d 09 b8 f0 1e 07 7a 88 25 b6 50 +c3 ab b8 f2 e0 53 03 2a 2f 2a +---- + +The HTTP/2 protocol parameters can be configured by editing the xref:og-module-http2c[`http2c` module] properties. diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2s.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2s.adoc new file mode 100644 index 00000000000..d171bd5420e --- /dev/null +++ b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-http2s.adoc @@ -0,0 +1,65 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[og-protocols-http2s]] +==== Configuring Secure HTTP/2 + +When you enable secure HTTP/2 you typically want to enable also secure HTTP/1.1, for backwards compatibility reasons: in this way, old browsers or other clients that do not support HTTP/2 will be able to connect to your server. + +You need to enable: + +* the `ssl` Jetty module, which provides the secure connector and the keystore and TLS configuration +* the `http2` Jetty module, which adds ALPN handling and adds the HTTP/2 protocol to the secured connector +* optionally, the `https` Jetty module, which adds the HTTP/1.1 protocol to the secured connector + +Use the following command (issued from within the `$JETTY_BASE` directory): + +---- +$ java -jar $JETTY_HOME/start.jar --add-modules=ssl,http2,https +---- + +As when enabling the `https` Jetty module, you need a valid keystore (read xref:og-keystore[this section] to create your own keystore). + +As a quick example, you can enable the xref:og-module-test-keystore[`test-keystore` module], that provides a keystore containing a self-signed certificate: + +---- +$ java -jar $JETTY_HOME/start.jar --add-modules=test-keystore +---- + +Starting Jetty yields: + +---- +$ java -jar $JETTY_HOME/start.jar +---- +[source,subs=quotes] +---- +2020-09-29 19:00:47.316:INFO :oejs.Server:main: jetty-10.0.0-SNAPSHOT; built: 2020-09-29T13:28:40.441Z; git: 9c0082610528a846b366ae26f4c74894579a8e48; jvm 15+36-1562 +2020-09-29 19:00:47.528:INFO :oejus.SslContextFactory:main: x509=X509@7770f470(mykey,h=[localhost],w=[]) for Server@24313fcc[provider=null,keyStore=file:///tmp/jetty.base/etc/test-keystore.p12,trustStore=file:///tmp/jetty.base/etc/test-keystore.p12] +2020-09-29 19:00:47.621:INFO :oejs.AbstractConnector:main: Started ServerConnector@73700b80##{SSL, (ssl, alpn, h2, http/1.1)}{0.0.0.0:8443}## +2020-09-29 19:00:47.630:INFO :oejs.Server:main: Started Server@30ee2816{STARTING}[10.0.0-SNAPSHOT,sto=5000] @746ms +---- + +Note how Jetty is listening on port `8443` and the protocols supported are the sequence `(ssl, alpn, h2, http/1.1)`. + +The (ordered) list of protocols after `alpn` are the _application protocols_, in the example above `(h2, http/1.1)`. + +When a new connection is accepted by the connector, Jetty first interprets the TLS bytes, then it handles the ALPN negotiation knowing that the application protocols are (in order) `h2` and then `http/1.1`. + +You can customize the list of application protocols and the default protocol to use in case the ALPN negotiation fails by editing the xref:og-module-alpn[`alpn` module] properties. + +The HTTP/2 protocol parameters can be configured by editing the xref:og-module-http2[`http2` module] properties. diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-https.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-https.adoc index 56b28aac4b7..fe43c38973f 100644 --- a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-https.adoc +++ b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-https.adoc @@ -45,7 +45,7 @@ Then, the xref:og-module-https[`https` module] adds HTTP/1.1 as the protocol sec The `$JETTY_BASE` directory looks like this: -[source,subs=verbatim] +[source] ---- $JETTY_BASE ├── resources @@ -55,7 +55,7 @@ $JETTY_BASE └── ssl.ini ---- -Note that the keystore file is missing, because you have to provide one with the cryptographic material you want (read xref:og-ssl[this section] to create your own keystore). +Note that the keystore file is missing, because you have to provide one with the cryptographic material you want (read xref:og-keystore[this section] to create your own keystore). You need to configure these two properties by editing `ssl.ini`: * `jetty.sslContext.keyStorePath` @@ -64,7 +64,7 @@ You need to configure these two properties by editing `ssl.ini`: As a quick example, you can enable the xref:og-module-test-keystore[`test-keystore` module], that provides a keystore containing a self-signed certificate: ---- -$ java -jar $JETTY_HOME/start.jar --add-modules=ssl,https +$ java -jar $JETTY_HOME/start.jar --add-modules=test-keystore ---- ---- INFO : test-keystore initialized in ${jetty.base}/start.d/test-keystore.ini @@ -75,6 +75,7 @@ INFO : Base directory was modified The `$JETTY_BASE` directory is now: +[source,subs=quotes] ---- ├── etc │ └── #test-keystore.p12# @@ -100,3 +101,10 @@ $ java -jar $JETTY_HOME/start.jar ---- Note how Jetty is listening on port `8443` for the secure HTTP/1.1 protocol. + +[WARNING] +==== +If you point your browser at `+https://localhost:8443/+` you will get a warning from the browser about a "potential security risk ahead", or that "your connection is not private", or similar message depending on the browser. + +This is normal because the certificate contained in `test-keystore.p12` is self-signed -- and as such not signed by a recognized certificate authority -- and therefore browsers do not trust it. +==== diff --git a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-ssl.adoc b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-ssl.adoc index 8c9ac79a430..0d2032b8d4b 100644 --- a/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-ssl.adoc +++ b/jetty-documentation/src/main/asciidoc/operations-guide/protocols/protocols-ssl.adoc @@ -34,15 +34,14 @@ Keystores may encode the cryptographic material with different encodings, the mo After configuring the keystore path and keystore password, you may want to further customize the parameters of the TLS protocol, such as the minimum TLS protocol version, or the TLS algorithms, etc. -The Jetty `ssl` module allows you to configure the keystore and the TLS parameters; if other modules require encryption, they declare a dependency on the `ssl` module. +The `ssl` Jetty module allows you to configure a secure network connector -- i.e. a connector configured with the TLS protocol, the keystore and the TLS parameters; if other modules require encryption, they declare a dependency on the `ssl` module. -Since the `ssl` module is only about encryption, it does not configure a connector listening on a network port because it does not know what is the wrapped protocol. It is the job of other Jetty modules to configure the wrapped protocol. -For example, it is the xref:og-protocols-https[`https` module] that configures the listening network port for secure HTTP/1.1. -The `https` module depends on the `ssl` module to allow the configuration of keystore and TLS, and adds HTTP/1.1 as the protocol wrapped by TLS. +For example, it is the xref:og-protocols-https[`https` module] that configures the wrapped protocol to be HTTP/1.1. +Similarly, it is the xref:og-protocols-http2[`http2` module] that configures the wrapped protocol to be HTTP/2. -Recall from the xref:og-modules[section about modules], that only modules that are explicitly enabled get their module configuration file (`+*.ini+`) saved in `$JETTY_BASE/start.d/`, and you want `$JETTY_BASE/start.d/ssl.ini` to be present so that you can configure the keystore and TLS properties. +Recall from the xref:og-modules[section about modules], that only modules that are explicitly enabled get their module configuration file (`+*.ini+`) saved in `$JETTY_BASE/start.d/`, and you want `$JETTY_BASE/start.d/ssl.ini` to be present so that you can configure the connector properties, the keystore properties and the TLS properties. // TODO: section about client authentication with certificates? // See readme_keystores.txt about the fact that the server keystore needs the CA=true extension. diff --git a/jetty-http2/http2-server/src/main/config/etc/jetty-http2c.xml b/jetty-http2/http2-server/src/main/config/etc/jetty-http2c.xml index e820dd186ff..3f77565aeec 100644 --- a/jetty-http2/http2-server/src/main/config/etc/jetty-http2c.xml +++ b/jetty-http2/http2-server/src/main/config/etc/jetty-http2c.xml @@ -8,6 +8,7 @@ + diff --git a/jetty-http2/http2-server/src/main/config/modules/http2.mod b/jetty-http2/http2-server/src/main/config/modules/http2.mod index 9a871e39139..f1742041b51 100644 --- a/jetty-http2/http2-server/src/main/config/modules/http2.mod +++ b/jetty-http2/http2-server/src/main/config/modules/http2.mod @@ -1,8 +1,5 @@ -# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html - [description] -Enables HTTP2 protocol support on the TLS(SSL) Connector with ALPN. -Uses the ALPN extension to select which protocol to use. +Enables the support for the secure HTTP/2 protocol. [tags] connector @@ -21,17 +18,20 @@ lib/http2/*.jar etc/jetty-http2.xml [ini-template] -## Max number of concurrent streams per connection +# tag::documentation[] +## Specifies the maximum number of concurrent requests per session. # jetty.http2.maxConcurrentStreams=128 -## Initial stream receive window (client to server) +## Specifies the initial stream receive window (client to server) in bytes. # jetty.http2.initialStreamRecvWindow=524288 -## Initial session receive window (client to server) +## Specifies the initial session receive window (client to server) in bytes. # jetty.http2.initialSessionRecvWindow=1048576 -## The max number of keys in all SETTINGS frames +## Specifies the maximum number of keys in all SETTINGS frames received by a session. # jetty.http2.maxSettingsKeys=64 -## Max number of bad frames and pings per second +## Specifies the maximum number of bad frames and pings per second, +## after which a session is closed to avoid denial of service attacks. # jetty.http2.rateControl.maxEventsPerSecond=20 +# end::documentation[] diff --git a/jetty-http2/http2-server/src/main/config/modules/http2c.mod b/jetty-http2/http2-server/src/main/config/modules/http2c.mod index be9674850da..46b5364ce0b 100644 --- a/jetty-http2/http2-server/src/main/config/modules/http2c.mod +++ b/jetty-http2/http2-server/src/main/config/modules/http2c.mod @@ -1,8 +1,5 @@ -# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html - [description] -Enables the HTTP2C protocol on the HTTP Connector. -The connector will accept both HTTP/1 and HTTP/2 connections. +Enables the support for the clear-text HTTP/2 protocol. [tags] connector @@ -19,14 +16,20 @@ lib/http2/*.jar etc/jetty-http2c.xml [ini-template] -## Max number of concurrent streams per connection +# tag::documentation[] +## Specifies the maximum number of concurrent requests per session. # jetty.http2c.maxConcurrentStreams=1024 -## Initial stream receive window (client to server) + ## Specifies the initial stream receive window (client to server) in bytes. # jetty.http2c.initialStreamRecvWindow=65535 -## The max number of keys in all SETTINGS frames +## Specifies the initial session receive window (client to server) in bytes. +# jetty.http2.initialSessionRecvWindow=1048576 + +## Specifies the maximum number of keys in all SETTINGS frames received by a session. # jetty.http2.maxSettingsKeys=64 -## Max number of bad frames and pings per second +## Specifies the maximum number of bad frames and pings per second, +## after which a session is closed to avoid denial of service attacks. # jetty.http2.rateControl.maxEventsPerSecond=20 +# end::documentation[] diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java index 6e4d9ceb68d..8047da2c816 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java @@ -375,7 +375,9 @@ public class Module implements Comparable // for the [ini-template] section if ("INI-TEMPLATE".equals(sectionType)) { - _iniTemplate.add(line); + // Exclude asciidoc tag lines used in documentation. + if (!line.contains("tag::") && !line.contains("end::")) + _iniTemplate.add(line); } } else From 8c45ba6b2bbb0afbe770bf09a5932ed2bb2f92e4 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 30 Sep 2020 08:45:29 -0500 Subject: [PATCH 2/3] Fixing typo Signed-off-by: Joakim Erdfelt --- jetty-home/testing-with-local-deploy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-home/testing-with-local-deploy.md b/jetty-home/testing-with-local-deploy.md index 3569b1adc11..83457cd8376 100644 --- a/jetty-home/testing-with-local-deploy.md +++ b/jetty-home/testing-with-local-deploy.md @@ -43,5 +43,5 @@ rm -rf $HOME/tmp/mybase/* cd $HOME/tmp/mybase mkdir $JLOCAL_REPO rm -rf $JLOCAL_REPO/* -java -jar $JETTY_HOME/start.jar maven.local.repo=$JLOCAL_REPO/ maven.repo.uri=file://$JDEPLOY_REPO --add-module=demo +java -jar $JETTY_HOME/start.jar maven.local.repo=$JLOCAL_REPO/ maven.repo.uri=file://$JDEPLOY_REPO/ --add-module=demo ``` From 26dbe0798704003e19749d49c436d61225cc3acf Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 30 Sep 2020 08:46:14 -0500 Subject: [PATCH 3/3] General cleanup of html & links Signed-off-by: Joakim Erdfelt --- .../src/main/webapp/auth.html | 32 ++++----- .../src/main/webapp/index.html | 71 ++++++++++--------- .../src/main/webapp/login.html | 34 ++++----- .../main/java/com/acme/DispatchServlet.java | 26 +++---- .../src/main/java/com/acme/Dump.java | 2 +- .../src/main/java/com/acme/SessionDump.java | 6 +- .../src/main/webapp/auth.html | 42 +++++------ .../src/main/webapp/cgi-bin/hello.sh | 2 +- .../src/main/webapp/error404.html | 6 +- .../src/main/webapp/index.html | 57 +++++++-------- .../src/main/webapp/logon.html | 36 +++++----- .../src/main/webapp/logonError.html | 9 +-- .../src/main/webapp/remote.html | 34 ++++----- .../src/main/webapp/index.html | 69 +++++++++--------- .../java/com/acme/test/AnnotationTest.java | 2 +- .../com/acme/test/AsyncListenerServlet.java | 2 +- .../com/acme/test/ClassLoaderServlet.java | 2 +- .../java/com/acme/test/MultiPartTest.java | 2 +- .../com/acme/test/RoleAnnotationTest.java | 4 +- .../java/com/acme/test/SecuredServlet.java | 4 +- .../src/main/webapp/index.html | 59 +++++++-------- .../src/main/webapp/login.html | 36 +++++----- 22 files changed, 276 insertions(+), 261 deletions(-) diff --git a/demos/demo-jaas-webapp/src/main/webapp/auth.html b/demos/demo-jaas-webapp/src/main/webapp/auth.html index ab122415090..5fcce8000e9 100644 --- a/demos/demo-jaas-webapp/src/main/webapp/auth.html +++ b/demos/demo-jaas-webapp/src/main/webapp/auth.html @@ -1,18 +1,18 @@ - - - - + + + + - + - -

SUCCESS! You are AUTHENTICATED and AUTHORIZED

- In order to see this page, you must have been JAAS authentictated using the - configured Login Module. You have also been AUTHORIZED according to this webapp's role-based web security constraints. -

- To logout click: -

- Logout -

- - + +

SUCCESS! You are AUTHENTICATED and AUTHORIZED

+In order to see this page, you must have been JAAS authentictated using the +configured Login Module. You have also been AUTHORIZED according to this webapp's role-based web security constraints. +

+ To logout click: +

+ Logout +

+ + diff --git a/demos/demo-jaas-webapp/src/main/webapp/index.html b/demos/demo-jaas-webapp/src/main/webapp/index.html index 2f831617dd0..55e8dd9b521 100644 --- a/demos/demo-jaas-webapp/src/main/webapp/index.html +++ b/demos/demo-jaas-webapp/src/main/webapp/index.html @@ -1,44 +1,47 @@ - - - JAAS Authentication and Authorization Test - - + + + JAAS Authentication and Authorization Test + + - - - -
- Demo Home -


-
Test Web Application Only - Do NOT Deploy in Production
+ + + +
+Demo Home +
+
Demo Web Application Only - Do NOT Deploy in Production +
-

JAAS Authentication and Authorization Demo

-

Preparation

-

To enable JAAS in a base jetty instance do: -

+

JAAS Authentication and Authorization Demo

+

Preparation

+

To enable JAAS in a base jetty instance do: +

     $ cd $JETTY_BASE
     $ java -jar $JETTY_HOME/start.jar --add-module=jaas
     
-

-

This will create a $JETTY_BASE/start.d/jaas.ini file to enable and parameterize JAAS. - The Jetty demo-base already has JAAS enabled by the demo-jaas module.

+

+

This will create a $JETTY_BASE/start.d/jaas.ini file to enable and parameterize JAAS. + This Jetty demo-jaas already has JAAS enabled by the demo-jaas module.

The full source of this demonstration is available here.

+ href="https://github.com/eclipse/jetty.project/tree/jetty-10.0.x/demos/demo-jaas-webapp">here.

-

Using the Demo

-

- Click on the link below to test JAAS authentication and role-based web security constraint authorization. Use username="me" with password="me". All other usernames, passwords should result in authentication failure. -

- LOGIN -

- This demo uses a simple login module that stores its configuration in a properties file. There are other types of login - module provided with the jetty distro. For full information, please refer to the - Jetty 9 documentation. -

+

Using the Demo

+

+ Click on the link below to test JAAS authentication and role-based web security constraint authorization. Use + username="me" with password="me". All other usernames, passwords should result in authentication + failure. +

+LOGIN +

+ This demo uses a simple login module that stores its configuration in a properties file. There are other types of login + module provided with the jetty distro. For full information, please refer to the + Jetty 9 documentation. +

-
-
+
+
- - + + diff --git a/demos/demo-jaas-webapp/src/main/webapp/login.html b/demos/demo-jaas-webapp/src/main/webapp/login.html index 608ea5ec522..757e81fe8d3 100644 --- a/demos/demo-jaas-webapp/src/main/webapp/login.html +++ b/demos/demo-jaas-webapp/src/main/webapp/login.html @@ -1,18 +1,18 @@ - - JAAS Authentication and Authorization Test - - - -

Enter your username and password to login

- Enter login=me and password=me in order to authenticate successfully -
- Login: -

- Password: -

- -

-

- - + +JAAS Authentication and Authorization Test + + + +

Enter your username and password to login

+ Enter login=me and password=me in order to authenticate successfully +
+ Login: +

+ Password: +

+ +

+

+ + diff --git a/demos/demo-jetty-webapp/src/main/java/com/acme/DispatchServlet.java b/demos/demo-jetty-webapp/src/main/java/com/acme/DispatchServlet.java index cce49261271..8f252044de3 100644 --- a/demos/demo-jetty-webapp/src/main/java/com/acme/DispatchServlet.java +++ b/demos/demo-jetty-webapp/src/main/java/com/acme/DispatchServlet.java @@ -94,18 +94,18 @@ public class DispatchServlet extends HttpServlet PrintWriter pout = null; pout = sres.getWriter(); - pout.write("

Include (writer): " + info + "


"); + pout.write("

Include (writer): " + info + "


"); RequestDispatcher dispatch = getServletContext().getRequestDispatcher(info); if (dispatch == null) { pout = sres.getWriter(); - pout.write("

Null dispatcher

"); + pout.write("

Null dispatcher

"); } else dispatch.include(sreq, sres); - pout.write("

-- Included (writer)

"); + pout.write("

-- Included (writer)

"); } else if (info.startsWith("/includeS/")) { @@ -118,18 +118,18 @@ public class DispatchServlet extends HttpServlet OutputStream out = null; out = sres.getOutputStream(); - out.write(("

Include (outputstream): " + info + "


").getBytes()); + out.write(("

Include (outputstream): " + info + "


").getBytes()); RequestDispatcher dispatch = getServletContext().getRequestDispatcher(info); if (dispatch == null) { out = sres.getOutputStream(); - out.write("

Null dispatcher

".getBytes()); + out.write("

Null dispatcher

".getBytes()); } else dispatch.include(sreq, sres); - out.write("

-- Included (outputstream)

".getBytes()); + out.write("

-- Included (outputstream)

".getBytes()); } else if (info.startsWith("/forward/")) { @@ -161,7 +161,7 @@ public class DispatchServlet extends HttpServlet { sres.setContentType("text/html"); PrintWriter pout = sres.getWriter(); - pout.write("

No dispatcher for: " + info + "


"); + pout.write("

No dispatcher for: " + info + "


"); pout.flush(); } } @@ -187,7 +187,7 @@ public class DispatchServlet extends HttpServlet { sres.setContentType("text/html"); PrintWriter pout = sres.getWriter(); - pout.write("

No dispatcher for: " + cpath + "/" + info + "


"); + pout.write("

No dispatcher for: " + cpath + "/" + info + "


"); pout.flush(); } } @@ -204,7 +204,7 @@ public class DispatchServlet extends HttpServlet else { pout = sres.getWriter(); - pout.write("

Include named: " + info + "


"); + pout.write("

Include named: " + info + "


"); } RequestDispatcher dispatch = getServletContext().getNamedDispatcher(info); @@ -213,11 +213,11 @@ public class DispatchServlet extends HttpServlet else { pout = sres.getWriter(); - pout.write("

No servlet named: " + info + "

"); + pout.write("

No servlet named: " + info + "

"); } pout = sres.getWriter(); - pout.write("

Included "); + pout.write("

Included "); } else if (info.startsWith("/forwardN/")) { @@ -231,7 +231,7 @@ public class DispatchServlet extends HttpServlet { sres.setContentType("text/html"); PrintWriter pout = sres.getWriter(); - pout.write("

No servlet named: " + info + "

"); + pout.write("

No servlet named: " + info + "

"); pout.flush(); } } @@ -240,7 +240,7 @@ public class DispatchServlet extends HttpServlet sres.setContentType("text/html"); PrintWriter pout = sres.getWriter(); pout.write( - "

Dispatch URL must be of the form:

" + + "

Dispatch URL must be of the form:

" + "
" +
                     prefix + "/includeW/path\n" +
                     prefix + "/includeS/path\n" +
diff --git a/demos/demo-jetty-webapp/src/main/java/com/acme/Dump.java b/demos/demo-jetty-webapp/src/main/java/com/acme/Dump.java
index 8859cb69cb0..a67aac17ec5 100644
--- a/demos/demo-jetty-webapp/src/main/java/com/acme/Dump.java
+++ b/demos/demo-jetty-webapp/src/main/java/com/acme/Dump.java
@@ -407,7 +407,7 @@ public class Dump extends HttpServlet
         if (pi != null && pi.startsWith("/ex"))
         {
             OutputStream out = response.getOutputStream();
-            out.write("This text should be reset".getBytes());
+            out.write("This text should be reset".getBytes());
             if ("/ex0".equals(pi))
                 throw new ServletException("test ex0", new Throwable());
             else if ("/ex1".equals(pi))
diff --git a/demos/demo-jetty-webapp/src/main/java/com/acme/SessionDump.java b/demos/demo-jetty-webapp/src/main/java/com/acme/SessionDump.java
index 67bd337b7c6..a0269b0dd67 100644
--- a/demos/demo-jetty-webapp/src/main/java/com/acme/SessionDump.java
+++ b/demos/demo-jetty-webapp/src/main/java/com/acme/SessionDump.java
@@ -131,7 +131,7 @@ public class SessionDump extends HttpServlet
 
         if (session == null)
         {
-            out.println("

No Session

"); + out.println("

No Session

"); out.println(""); } else @@ -167,10 +167,10 @@ public class SessionDump extends HttpServlet out.println("
"); if (request.isRequestedSessionIdFromCookie()) - out.println("

Turn off cookies in your browser to try url encoding
"); + out.println("

Turn off cookies in your browser to try url encoding
"); if (request.isRequestedSessionIdFromURL()) - out.println("

Turn on cookies in your browser to try cookie encoding
"); + out.println("

Turn on cookies in your browser to try cookie encoding
"); out.println("Encoded Link
"); } catch (IllegalStateException e) diff --git a/demos/demo-jetty-webapp/src/main/webapp/auth.html b/demos/demo-jetty-webapp/src/main/webapp/auth.html index 3b55b767f39..79d66d7ab3a 100644 --- a/demos/demo-jetty-webapp/src/main/webapp/auth.html +++ b/demos/demo-jetty-webapp/src/main/webapp/auth.html @@ -1,36 +1,36 @@ - - - Powered By Jetty - Auth Links - - - - - + + + Powered By Jetty - Auth Links + + + + +

Jetty Authentication Links

-This page contains several links to test the authentication constraints: + This page contains several links to test the authentication constraints:

-Usernames/Passwords are jetty/jetty admin/admin & user/password + Usernames/Passwords are jetty/jetty admin/admin & user/password

-Return to main menu. + Return to main menu.

- - + + diff --git a/demos/demo-jetty-webapp/src/main/webapp/cgi-bin/hello.sh b/demos/demo-jetty-webapp/src/main/webapp/cgi-bin/hello.sh index 86660496a72..1ded600bc48 100644 --- a/demos/demo-jetty-webapp/src/main/webapp/cgi-bin/hello.sh +++ b/demos/demo-jetty-webapp/src/main/webapp/cgi-bin/hello.sh @@ -1,4 +1,4 @@ #!/bin/sh echo "Content-Type: text/html" echo -echo "

Hello World

" +echo "

Hello World

" diff --git a/demos/demo-jetty-webapp/src/main/webapp/error404.html b/demos/demo-jetty-webapp/src/main/webapp/error404.html index 0dd635b22bc..4aea1975753 100644 --- a/demos/demo-jetty-webapp/src/main/webapp/error404.html +++ b/demos/demo-jetty-webapp/src/main/webapp/error404.html @@ -1,4 +1,4 @@ - -

Not Found ERROR

+ +

Not Found ERROR

custom 404 page - \ No newline at end of file + \ No newline at end of file diff --git a/demos/demo-jetty-webapp/src/main/webapp/index.html b/demos/demo-jetty-webapp/src/main/webapp/index.html index 2b4a56fc1de..82061ecc65d 100644 --- a/demos/demo-jetty-webapp/src/main/webapp/index.html +++ b/demos/demo-jetty-webapp/src/main/webapp/index.html @@ -1,25 +1,27 @@ - - - Powered By Jetty - - - - - - -
- Demo Home -
-
Test Web Application Only - Do NOT Deploy in Production
-

Welcome to Jetty

+ + + + +
+Demo Home +
+
Demo Web Application Only - Do NOT Deploy in Production +
+ +

Welcome to Eclipse Jetty

-This is the Test webapp for the Jetty HTTP Server and Servlet Container. -It is configured as a jetty base directory in $JETTY_HOME/demo_base. + This is the Demo webapp for the Eclipse Jetty HTTP Server and Servlet Container. + It was added into your $JETTY_BASE/webapps directory.

Jetty Tests:

@@ -56,17 +58,16 @@ It is configured as a jetty base directory in $JETTY_HOME/demo_base.

Useful links:

- +


-
- - +
+ + diff --git a/demos/demo-jetty-webapp/src/main/webapp/logon.html b/demos/demo-jetty-webapp/src/main/webapp/logon.html index 2cfa699c807..6bededa576d 100644 --- a/demos/demo-jetty-webapp/src/main/webapp/logon.html +++ b/demos/demo-jetty-webapp/src/main/webapp/logon.html @@ -1,20 +1,20 @@ - -

FORM Authentication demo

+ +

FORM Authentication demo

- - - - - - - - - - - - -
Username:
Password:
- -
+ + + + + + + + + + + + +
Username:
Password:
+ +
- \ No newline at end of file + \ No newline at end of file diff --git a/demos/demo-jetty-webapp/src/main/webapp/logonError.html b/demos/demo-jetty-webapp/src/main/webapp/logonError.html index 1b1228bd69d..bef8cdf20de 100644 --- a/demos/demo-jetty-webapp/src/main/webapp/logonError.html +++ b/demos/demo-jetty-webapp/src/main/webapp/logonError.html @@ -1,5 +1,6 @@ - -

Authentication ERROR

+ +

Authentication ERROR

Username, password or role incorrect. -                                                         - \ No newline at end of file +                                    +                    + \ No newline at end of file diff --git a/demos/demo-jetty-webapp/src/main/webapp/remote.html b/demos/demo-jetty-webapp/src/main/webapp/remote.html index 558861c15d4..d2e45bcd013 100644 --- a/demos/demo-jetty-webapp/src/main/webapp/remote.html +++ b/demos/demo-jetty-webapp/src/main/webapp/remote.html @@ -1,32 +1,34 @@ - - - Powered By Jetty - - - - - + + + Powered By Jetty + + + + +

Welcome to Jetty 10 - REMOTE ACCESS!!

-This is the Test webapp for the Jetty HTTP Server and Servlet Container. + This is the Test webapp for the Jetty HTTP Server and Servlet Container. For more information about Jetty, please visit our website or documentation. Commercial support for Jetty is available via webtide.

-This test context serves several demo filters and servlets + This test context serves several demo filters and servlets that are not safe for deployment on the internet, since (by design) they contain cross domain scripting vulnerabilities and reveal private information. This page -is displayed because you have accessed this context from a non local IP address. + is displayed because you have accessed this context from a non local IP address.

-You can disable the remote address checking by editing demo-base/webapps/test.d/override-web.xml, uncommenting the declaration of the TestFilter, and changing the -"remote" init parameter to "true". + You can disable the remote address checking by editing demo-base/webapps/test.d/override-web.xml, uncommenting the + declaration of the TestFilter, and changing the + "remote" init parameter to "true".

-This webapp is deployed in $JETTY_HOME/demo-base/webapps/test.war and configured by $JETTY_HOME/demo-base/webapps/test.xml and $JETTY_HOME/demo-base/webapps/test.d/override-web.xml + This webapp is deployed in $JETTY_HOME/demo-base/webapps/test.war and configured by $JETTY_HOME/demo-base/webapps/test.xml + and $JETTY_HOME/demo-base/webapps/test.d/override-web.xml

- - + + diff --git a/demos/demo-jndi-webapp/src/main/webapp/index.html b/demos/demo-jndi-webapp/src/main/webapp/index.html index 131cef6eb2e..a6731102192 100644 --- a/demos/demo-jndi-webapp/src/main/webapp/index.html +++ b/demos/demo-jndi-webapp/src/main/webapp/index.html @@ -1,47 +1,52 @@ - - - JNDI Test WebApp - - + + + JNDI Test WebApp + + - - - -
- Demo Home -
-
Test Web Application Only - Do NOT Deploy in Production
+ + + +
+Demo Home +
+
Demo Web Application Only - Do NOT Deploy in Production +

JNDI Test WebApp

-This example shows how to configure and lookup resources such as DataSources, a JTA transaction manager and a java.mail.Session in JNDI. + This example shows how to configure and lookup resources such as DataSources, a JTA transaction manager and a + java.mail.Session in JNDI.

-

Preparation

-

To enable JNDI in a base jetty instance do: -

-    $ cd $JETTY_BASE
-    $ java -jar $JETTY_HOME/start.jar --add-module=jndi
-    
-

-

This will create a $JETTY_BASE/start.d/jndi.ini file to enable and parameterise JNDI. - The jetty demo-base already has JNDI enabled and some mock resources included by the - demo-jndi module.

-

The full source of this demonstration is available here.

- +

Preparation

+

To enable JNDI in a base jetty instance do: +

+$ cd $JETTY_BASE
+$ java -jar $JETTY_HOME/start.jar --add-module=jndi
+
+

+

+ This will create a $JETTY_BASE/start.d/jndi.ini file to enable and parameterise JNDI. + The jetty demo-base already has JNDI enabled and some mock resources included by the + demo-jndi module. +

+

+ The full source of this demonstration is available + here. +

Execution

-Click Test to check the runtime lookup of the JNDI resources. + Click Test to check the runtime lookup of the JNDI resources.

- +
+
+
-
-
- - - + + diff --git a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/AnnotationTest.java b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/AnnotationTest.java index e9c576edf60..499161380f6 100644 --- a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/AnnotationTest.java +++ b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/AnnotationTest.java @@ -182,7 +182,7 @@ public class AnnotationTest extends HttpServlet response.setContentType("text/html"); ServletOutputStream out = response.getOutputStream(); out.println(""); - out.println(""); + out.println(""); out.println(""); out.println("

Results

"); diff --git a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/AsyncListenerServlet.java b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/AsyncListenerServlet.java index 7efe30fd09a..4eb057e778a 100644 --- a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/AsyncListenerServlet.java +++ b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/AsyncListenerServlet.java @@ -89,7 +89,7 @@ public class AsyncListenerServlet extends HttpServlet PrintWriter writer = resp.getWriter(); writer.println(""); - writer.println(""); + writer.println(""); writer.println(""); writer.println("

AsyncListener

"); writer.println("
");
diff --git a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/ClassLoaderServlet.java b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/ClassLoaderServlet.java
index b22a5db26d1..bfb4aec70f1 100644
--- a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/ClassLoaderServlet.java
+++ b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/ClassLoaderServlet.java
@@ -40,7 +40,7 @@ public class ClassLoaderServlet extends HttpServlet
         {
             PrintWriter writer = resp.getWriter();
             writer.println("");
-            writer.println("");
+            writer.println("");
             writer.println("");
             writer.println("

ClassLoader Isolation Test

"); diff --git a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/MultiPartTest.java b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/MultiPartTest.java index 387803900cb..ee7074a25b4 100644 --- a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/MultiPartTest.java +++ b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/MultiPartTest.java @@ -55,7 +55,7 @@ public class MultiPartTest extends HttpServlet response.setContentType("text/html"); ServletOutputStream out = response.getOutputStream(); out.println(""); - out.println(""); + out.println(""); out.println(""); out.println("

Results

"); out.println("

"); diff --git a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/RoleAnnotationTest.java b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/RoleAnnotationTest.java index e886402e8fc..fc97169bd79 100644 --- a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/RoleAnnotationTest.java +++ b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/RoleAnnotationTest.java @@ -58,7 +58,7 @@ public class RoleAnnotationTest extends HttpServlet response.setContentType("text/html"); ServletOutputStream out = response.getOutputStream(); out.println(""); - out.println(""); + out.println(""); out.println("

Jetty DeclareRoles Annotation Results

"); out.println(""); @@ -74,7 +74,7 @@ public class RoleAnnotationTest extends HttpServlet if (!context.endsWith("/")) context += "/"; - out.println("

Logout

"); + out.println("

Logout

"); out.println(""); out.println(""); diff --git a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/SecuredServlet.java b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/SecuredServlet.java index a66f858f066..3c220363ecb 100644 --- a/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/SecuredServlet.java +++ b/demos/demo-spec/demo-spec-webapp/src/main/java/com/acme/test/SecuredServlet.java @@ -37,7 +37,7 @@ public class SecuredServlet extends HttpServlet { PrintWriter writer = resp.getWriter(); writer.println(""); - writer.println(""); + writer.println(""); writer.println(""); writer.println("

@ServletSecurity

"); writer.println("
");
@@ -48,7 +48,7 @@ public class SecuredServlet extends HttpServlet
         String context = getServletConfig().getServletContext().getContextPath();
         if (!context.endsWith("/"))
             context += "/";
-        writer.println("

Logout

"); + writer.println("

Logout

"); writer.println(""); writer.println(""); writer.flush(); diff --git a/demos/demo-spec/demo-spec-webapp/src/main/webapp/index.html b/demos/demo-spec/demo-spec-webapp/src/main/webapp/index.html index 3bde2de85ab..d4ec12570d1 100644 --- a/demos/demo-spec/demo-spec-webapp/src/main/webapp/index.html +++ b/demos/demo-spec/demo-spec-webapp/src/main/webapp/index.html @@ -1,33 +1,36 @@ - - - Test Specification WebApp - - + + + Test Specification WebApp + + - - - -
- Demo Home -
-
Test Web Application Only - Do NOT Deploy in Production
+ + + +
+Demo Home +
+
Demo Web Application Only - Do NOT Deploy in Production +
-

Servlet 3.0/3.1/4.0 Test WebApp

+

Servlet 4.0 Demo WebApp

-This example tests some aspects of the servlet specification: