Skip to content

Commit 89adf5b

Browse files
committed
Merge remote-tracking branch 'origin/jetty-12.0.x' into fix/12.0.x/npe-httpuri-decodedpath
2 parents 19aec3a + 3aedd8d commit 89adf5b

File tree

36 files changed

+880
-260
lines changed

36 files changed

+880
-260
lines changed

.github/dependabot.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,7 @@ updates:
246246
- dependency-name: "org.apache.avro:*"
247247
versions: [ ">=1.12" ]
248248

249+
- package-ecosystem: "github-actions"
250+
directory: "/"
251+
schedule:
252+
interval: "weekly"

.github/workflows/codeql-analysis.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ jobs:
3131

3232
steps:
3333
- name: Checkout repository
34-
uses: actions/checkout@v3
34+
uses: actions/checkout@v4
3535

3636
# Install and setup JDK 11
3737
- name: Setup JDK 11
38-
uses: actions/setup-java@v3
38+
uses: actions/setup-java@v4
3939
if: ${{
4040
startsWith(github.ref, 'refs/heads/jetty-10.') ||
4141
startsWith(github.ref, 'refs/heads/jetty-11.') ||
@@ -49,7 +49,7 @@ jobs:
4949

5050
# Install and setup JDK 17
5151
- name: Setup JDK 17
52-
uses: actions/setup-java@v3
52+
uses: actions/setup-java@v4
5353
if: ${{
5454
startsWith(github.ref, 'refs/heads/jetty-12.') ||
5555
startsWith(github.base_ref, 'jetty-12.')
@@ -61,7 +61,7 @@ jobs:
6161

6262
# Initializes the CodeQL tools for scanning.
6363
- name: Initialize CodeQL
64-
uses: github/codeql-action/init@v2
64+
uses: github/codeql-action/init@v3
6565
with:
6666
languages: ${{ matrix.languages }}
6767
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -74,7 +74,7 @@ jobs:
7474

7575
- name: Set up Maven
7676
run:
77-
mvn -e -B -V org.apache.maven.plugins:maven-wrapper-plugin:3.1.0:wrapper "-Dmaven=3.9.6"
77+
mvn -e -B -V org.apache.maven.plugins:maven-wrapper-plugin:3.1.0:wrapper "-Dmaven=3.9.9"
7878

7979
- name: Clean install dependencies and build
8080
env:
@@ -94,4 +94,4 @@ jobs:
9494
# ./location_of_script_within_repo/buildscript.sh
9595

9696
- name: Perform CodeQL Analysis
97-
uses: github/codeql-action/analyze@v2
97+
uses: github/codeql-action/analyze@v3

Jenkinsfile

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,6 @@ def mavenBuild(jdk, cmdline, mvnName) {
125125
extraArgs = " -Dmaven.test.failure.ignore=true "
126126
}
127127
}
128-
runLaunchable ("verify")
129-
runLaunchable ("record build --name jetty-12.0.x")
130128
dashProfile = ""
131129
if(useEclipseDash()) {
132130
dashProfile = " -Peclipse-dash "
@@ -140,9 +138,7 @@ def mavenBuild(jdk, cmdline, mvnName) {
140138
}
141139
finally
142140
{
143-
junit testDataPublishers: [[$class: 'JUnitFlakyTestDataPublisher']], testResults: '**/target/surefire-reports/**/*.xml,**/target/invoker-reports/TEST*.xml', allowEmptyResults: true
144-
echo "Launchable record tests"
145-
runLaunchable ("record tests --build jetty-12.0.x maven '**/target/surefire-reports/**/*.xml' '**/target/invoker-reports/TEST*.xml'")
141+
junit testResults: '**/target/surefire-reports/**/*.xml,**/target/invoker-reports/TEST*.xml', allowEmptyResults: true
146142
}
147143
}
148144
}
@@ -187,17 +183,5 @@ def websiteBuild() {
187183
}
188184
}
189185
}
190-
/**
191-
* run launchable with args and ignore any errors
192-
* @param args
193-
*/
194-
def runLaunchable(args) {
195-
try {
196-
sh "launchable $args"
197-
} catch (Exception e) {
198-
e.printStackTrace()
199-
echo "skip failure running Launchable: " + e.getMessage()
200-
}
201-
}
202186

203187
// vim: et:ts=2:sw=2:ft=groovy

documentation/jetty/modules/code/examples/src/main/java/org/eclipse/jetty/docs/programming/client/http/HTTPClientDocs.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@
2020
import java.net.SocketAddress;
2121
import java.net.URI;
2222
import java.nio.ByteBuffer;
23+
import java.nio.channels.SocketChannel;
2324
import java.nio.file.Path;
2425
import java.nio.file.Paths;
2526
import java.util.List;
2627
import java.util.concurrent.CompletableFuture;
28+
import java.util.concurrent.ConcurrentHashMap;
29+
import java.util.concurrent.ConcurrentMap;
2730
import java.util.concurrent.TimeUnit;
2831
import javax.net.ssl.SSLEngine;
2932
import javax.net.ssl.SSLException;
@@ -1233,4 +1236,38 @@ public void connectionInformation() throws Exception
12331236
.send();
12341237
// end::connectionInformation[]
12351238
}
1239+
1240+
public void connectListener() throws Exception
1241+
{
1242+
// tag::connectListener[]
1243+
ClientConnector clientConnector = new ClientConnector();
1244+
clientConnector.addEventListener(new ClientConnector.ConnectListener()
1245+
{
1246+
private final ConcurrentMap<SocketChannel, Long> times = new ConcurrentHashMap<>();
1247+
1248+
@Override
1249+
public void onConnectBegin(SocketChannel socketChannel, SocketAddress socketAddress)
1250+
{
1251+
times.put(socketChannel, System.nanoTime());
1252+
}
1253+
1254+
@Override
1255+
public void onConnectSuccess(SocketChannel socketChannel)
1256+
{
1257+
Long begin = times.remove(socketChannel);
1258+
System.getLogger("connection").log(INFO, "established in %d ns", System.nanoTime() - begin);
1259+
}
1260+
1261+
@Override
1262+
public void onConnectFailure(SocketChannel socketChannel, SocketAddress socketAddress, Throwable failure)
1263+
{
1264+
Long begin = times.remove(socketChannel);
1265+
System.getLogger("connection").log(INFO, "failed in %d ns", System.nanoTime() - begin);
1266+
}
1267+
});
1268+
1269+
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
1270+
httpClient.start();
1271+
// end::connectListener[]
1272+
}
12361273
}

documentation/jetty/modules/code/examples/src/main/java/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
import org.eclipse.jetty.server.handler.CrossOriginHandler;
8585
import org.eclipse.jetty.server.handler.DefaultHandler;
8686
import org.eclipse.jetty.server.handler.EventsHandler;
87+
import org.eclipse.jetty.server.handler.GracefulHandler;
8788
import org.eclipse.jetty.server.handler.QoSHandler;
8889
import org.eclipse.jetty.server.handler.ResourceHandler;
8990
import org.eclipse.jetty.server.handler.SecuredRedirectHandler;
@@ -1637,6 +1638,38 @@ public void defaultHandler() throws Exception
16371638
// end::defaultHandler[]
16381639
}
16391640

1641+
public void gracefulHandler() throws Exception
1642+
{
1643+
// tag::gracefulHandler[]
1644+
Server server = new Server();
1645+
1646+
// Install the GracefulHandler.
1647+
GracefulHandler gracefulHandler = new GracefulHandler();
1648+
server.setHandler(gracefulHandler);
1649+
1650+
// Set the Server stopTimeout to wait at most
1651+
// 10 seconds for existing requests to complete.
1652+
server.setStopTimeout(10_000);
1653+
1654+
// Add one web application.
1655+
class MyWebApp extends Handler.Abstract
1656+
{
1657+
@Override
1658+
public boolean handle(Request request, Response response, Callback callback) throws Exception
1659+
{
1660+
// Implement your web application.
1661+
callback.succeeded();
1662+
return true;
1663+
}
1664+
}
1665+
1666+
ContextHandler contextHandler = new ContextHandler(new MyWebApp(), "/app");
1667+
gracefulHandler.setHandler(contextHandler);
1668+
1669+
server.start();
1670+
// end::gracefulHandler[]
1671+
}
1672+
16401673
public void continue100()
16411674
{
16421675
// tag::continue100[]

documentation/jetty/modules/operations-guide/pages/modules/standard.adoc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,19 @@ Jetty's configuration properties are identical across all versions of this modul
168168
include::{jetty-home}/modules/ee10-webapp.mod[tags=ini-template]
169169
----
170170

171+
[[graceful]]
172+
== Module `graceful`
173+
174+
The `graceful` module allows to shut down gracefully the Jetty server when it is stopped (see xref:start/index.adoc#stop[this section] for more information about stopping Jetty).
175+
176+
The `graceful` module installs the `GracefulHandler` at the root of the `Handler` tree; the `GracefulHandler` rejects new requests, but allows current requests to terminate within a configurable timeout, as explained in xref:programming-guide:server/http.adoc#handler-use-graceful[this section].
177+
178+
The module properties are:
179+
180+
----
181+
include::{jetty-home}/modules/graceful.mod[tags=documentation]
182+
----
183+
171184
[[http]]
172185
== Module `http`
173186

documentation/jetty/modules/operations-guide/pages/start/index.adoc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,18 @@ The `jetty.server.stopAtShutdown` property configures a JVM shutdown hook that i
540540

541541
Obviously, the JVM can also be stopped with `kill -KILL <pid>` that exits the process abruptly without running the JVM shutdown hooks.
542542

543+
[[stop-graceful]]
544+
=== Stopping Gracefully
545+
546+
Stopping Jetty abruptly when there are active HTTP requests being handled may result in a variety or errors, because Jetty components that are used to handle requests are being stopped concurrently.
547+
548+
For example, when the Jetty thread pool is stopped, an attempt to submit a task would throw `RejectedExecutionException`; when a component is stopped, its fields may be nulled-out, resulting in a `NullPointerException` being thrown if the component is used; etc.
549+
550+
You can stop Jetty _gracefully_ by adding the `graceful` Jetty module (see xref:modules/standard.adoc#graceful[this section] for more information).
551+
552+
When Jetty is stopped, the `graceful` module organizes to reject new requests, but allows existing requests to finish within a configurable timeout; then closes all the connections, stops all the Jetty components, and then exits the JVM.
553+
In this way, existing requests are not responded with an error caused by the server stopping, provided they complete within the timeout.
554+
543555
[[stop-remote]]
544556
=== Stopping Jetty from Remote
545557

documentation/jetty/modules/programming-guide/pages/client/http.adoc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ include::code:example$src/main/java/org/eclipse/jetty/docs/programming/client/ht
541541
----
542542

543543
[[connection-information]]
544-
=== Request Connection Information
544+
=== Connection Information
545545

546546
In order to send a request, it is necessary to obtain a connection, as explained in the xref:request-processing[request processing section].
547547

@@ -562,6 +562,25 @@ This means that the connection is not available in the _request queued_ event, b
562562
For more information about request events, see xref:non-blocking[this section].
563563
====
564564

565+
[[connection-events]]
566+
=== Connection Events
567+
568+
In order to send HTTP requests, a connection is necessary, as explained in the xref:request-processing[request processing section].
569+
570+
HTTP/1.1 and HTTP/2 use `SocketChannel.connect(SocketAddress)` to establish a connection with the server, either via the TCP transport or via the Unix-Domain transport.
571+
572+
You can listen to these `connect` events using a `ClientConnector.ConnectListener`, for example to record connection establishment times:
573+
574+
[,java,indent=0]
575+
----
576+
include::code:example$src/main/java/org/eclipse/jetty/docs/programming/client/http/HTTPClientDocs.java[tags=connectListener]
577+
----
578+
579+
This could be particularly useful when you notice that your client application seem "slow" to send requests.
580+
The `connect begin` and `connect success` events, along with the `request queued` and `request begin` event (detailed xref:non-blocking[here]), allow you to understand whether it is the server being slow at accepting connections, or it is the client being slow at processing queued requests.
581+
582+
Once the low-level connection has been established, you can be notified of connection events using a `Connection.Listener`, or more concretely `ConnectionStatistics`, as described in xref:arch/io.adoc#connection-listener[this section].
583+
565584
[[configuration]]
566585
== HttpClient Configuration
567586

documentation/jetty/modules/programming-guide/pages/server/http.adoc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,41 @@ The `Forwarded` header is typically present in requests that have been forwarded
12541254

12551255
Note that `ThreadLimitHandler` is different from xref:handler-use-qos[`QoSHandler`] in that it limits the number of concurrent requests per remote IP address, while `QoSHandler` limits the total number of concurrent requests.
12561256

1257+
[[handler-use-graceful]]
1258+
==== GracefulHandler
1259+
1260+
`GracefulHandler` allows to stop the Jetty server in a graceful way, by rejecting new requests but allowing existing requests to complete within a configurable timeout.
1261+
1262+
In this way, existing requests can be completed normally rather than with failures caused by the fact that the server is stopping; for example, stopping the server causes all TCP connections to be closed, so trying to write a response will result in a failure.
1263+
1264+
In order to stop Jetty gracefully, you need the following:
1265+
1266+
* Install the `GracefulHandler`, typically just after the `Server` at the root of the `Handler` tree.
1267+
* Configure `Server.stopTimeout` to a positive value.
1268+
1269+
When the `Server` component is stopped, it will check the `Server.stopTimeout`, and if positive, it will initiate a graceful shutdown by notifying all components that implement the `Graceful` interface that the shutdown has been initiated.
1270+
1271+
`GracefulHandler` implements `Graceful`, so it will start rejecting new requests with status code `503 Service Available`, but will allow existing requests to complete for a period of time up to `Server.stopTimeout`.
1272+
1273+
When all existing requests have completed, the `Server` stops all ``Connector``s, closes all connections, and finally stops all the components.
1274+
1275+
This is how you configure and use `GracefulHandler`:
1276+
1277+
[,java,indent=0]
1278+
----
1279+
include::code:example$src/main/java/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[tags=gracefulHandler]
1280+
----
1281+
1282+
The `Handler` tree structure looks like the following:
1283+
1284+
[,screen]
1285+
----
1286+
Server
1287+
└── GracefulHandler
1288+
└── ContextHandler
1289+
└── MyWebApp
1290+
----
1291+
12571292
[[handler-use-servlet]]
12581293
=== Servlet API Handlers
12591294

jetty-core/jetty-alpn/jetty-alpn-conscrypt-server/src/test/java/org/eclipse/jetty/alpn/conscrypt/server/ConscryptHTTP2ServerTest.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public class ConscryptHTTP2ServerTest
5656
Security.addProvider(new OpenSSLProvider());
5757
}
5858

59+
private final HttpConfiguration httpsConfig = new HttpConfiguration();
5960
private final Server server = new Server();
6061

6162
private SslContextFactory.Server newServerSslContextFactory()
@@ -90,9 +91,7 @@ private void configureSslContextFactory(SslContextFactory sslContextFactory)
9091
@BeforeEach
9192
public void startServer() throws Exception
9293
{
93-
HttpConfiguration httpsConfig = new HttpConfiguration();
9494
httpsConfig.setSecureScheme("https");
95-
9695
httpsConfig.setSendXPoweredBy(true);
9796
httpsConfig.setSendServerVersion(true);
9897
httpsConfig.addCustomizer(new SecureRequestCustomizer());
@@ -140,4 +139,12 @@ public void testSimpleRequest() throws Exception
140139
assertEquals(200, contentResponse.getStatus());
141140
}
142141
}
142+
143+
@Test
144+
public void testSNIRequired() throws Exception
145+
{
146+
// The KeyStore contains 1 certificate with two DNS names.
147+
httpsConfig.getCustomizer(SecureRequestCustomizer.class).setSniRequired(true);
148+
testSimpleRequest();
149+
}
143150
}

0 commit comments

Comments
 (0)