Skip to content

Commit bb52d95

Browse files
authoredAug 23, 2024··
Fixes #12063 - Introduce Jetty module for HTTP/2 client dependencies. (#12170)
Introduced http2-client.mod and http2-client-transport.mod. These modules download dependencies via a [files] section. They can be used to have the server provide the dependencies in case of a web application proxies request using HTTP/2. Fixed ContentProvider to set the context ClassLoader before reading the Jetty XML context file, which may reference classes from the web application. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
1 parent 6527aa5 commit bb52d95

File tree

9 files changed

+188
-4
lines changed

9 files changed

+188
-4
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
# DO NOT EDIT THIS FILE - See: https://jetty.org/docs/
22

33
[description]
4-
Adds the Jetty HTTP client to the server classpath.
4+
Adds the Jetty HTTP client dependencies to the server classpath.
5+
6+
[tags]
7+
client
58

69
[lib]
7-
lib/jetty-client-${jetty.version}.jar
810
lib/jetty-alpn-client-${jetty.version}.jar
11+
lib/jetty-alpn-java-client-${jetty.version}.jar
12+
lib/jetty-client-${jetty.version}.jar

‎jetty-core/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,10 @@ public ContextHandler createContextHandler(final App app) throws Exception
385385
// Handle a context XML file
386386
if (FileID.isXml(path))
387387
{
388+
ClassLoader coreContextClassLoader = Environment.CORE.equals(environment) ? findCoreContextClassLoader(path) : null;
389+
if (coreContextClassLoader != null)
390+
Thread.currentThread().setContextClassLoader(coreContextClassLoader);
391+
388392
context = applyXml(context, path, env, properties);
389393

390394
// Look for the contextHandler itself
@@ -401,13 +405,11 @@ else if (context instanceof Supplier<?> supplier)
401405
throw new IllegalStateException("Unknown context type of " + context);
402406

403407
// Set the classloader if we have a coreContextClassLoader
404-
ClassLoader coreContextClassLoader = Environment.CORE.equals(environment) ? findCoreContextClassLoader(path) : null;
405408
if (coreContextClassLoader != null)
406409
contextHandler.setClassLoader(coreContextClassLoader);
407410

408411
return contextHandler;
409412
}
410-
411413
// Otherwise it must be a directory or an archive
412414
else if (!Files.isDirectory(path) && !FileID.isWebArchive(path))
413415
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[description]
2+
Adds the Jetty HTTP/2 client transport dependencies to the server classpath.
3+
4+
[tags]
5+
client
6+
http2
7+
8+
[depends]
9+
client
10+
http2-client
11+
12+
[files]
13+
maven://org.eclipse.jetty.http2/jetty-http2-client-transport/${jetty.version}/jar|lib/http2/jetty-http2-client-transport-${jetty.version}.jar
14+
15+
[lib]
16+
lib/http2/jetty-http2-client-transport-${jetty.version}.jar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[description]
2+
Adds the Jetty HTTP/2 client dependencies to the server classpath.
3+
4+
[tags]
5+
client
6+
http2
7+
8+
[files]
9+
maven://org.eclipse.jetty/jetty-alpn-client/${jetty.version}/jar|lib/jetty-alpn-client-${jetty.version}.jar
10+
maven://org.eclipse.jetty/jetty-alpn-java-client/${jetty.version}/jar|lib/jetty-alpn-java-client-${jetty.version}.jar
11+
maven://org.eclipse.jetty.http2/jetty-http2-client/${jetty.version}/jar|lib/http2/jetty-http2-client-${jetty.version}.jar
12+
13+
[lib]
14+
lib/jetty-alpn-client-${jetty.version}.jar
15+
lib/jetty-alpn-java-client-${jetty.version}.jar
16+
lib/http2/jetty-http2-client-${jetty.version}.jar
17+
lib/http2/jetty-http2-common-${jetty.version}.jar
18+
lib/http2/jetty-http2-hpack-${jetty.version}.jar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>org.eclipse.jetty</groupId>
6+
<artifactId>jetty-tests</artifactId>
7+
<version>12.0.13-SNAPSHOT</version>
8+
</parent>
9+
10+
<artifactId>jetty-test-http2-client-transport-provided-webapp</artifactId>
11+
<name>Core :: Tests :: HTTP/2 Client Transport Provided WebApp</name>
12+
13+
<properties>
14+
<maven.deploy.skip>true</maven.deploy.skip>
15+
</properties>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>org.eclipse.jetty</groupId>
20+
<artifactId>jetty-server</artifactId>
21+
<scope>provided</scope>
22+
</dependency>
23+
<dependency>
24+
<groupId>org.eclipse.jetty.http2</groupId>
25+
<artifactId>jetty-http2-client-transport</artifactId>
26+
<scope>provided</scope>
27+
</dependency>
28+
</dependencies>
29+
30+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//
2+
// ========================================================================
3+
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
4+
//
5+
// This program and the accompanying materials are made available under the
6+
// terms of the Eclipse Public License v. 2.0 which is available at
7+
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
8+
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
//
10+
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
11+
// ========================================================================
12+
//
13+
14+
package org.eclipse.jetty.test.http2.client.transport.provided;
15+
16+
import java.util.concurrent.TimeUnit;
17+
18+
import org.eclipse.jetty.client.HttpClient;
19+
import org.eclipse.jetty.http2.client.HTTP2Client;
20+
import org.eclipse.jetty.http2.client.transport.HttpClientTransportOverHTTP2;
21+
import org.eclipse.jetty.server.Handler;
22+
import org.eclipse.jetty.server.Request;
23+
import org.eclipse.jetty.server.Response;
24+
import org.eclipse.jetty.util.Callback;
25+
26+
public class HTTP2ClientTransportProvidedHandler extends Handler.Abstract
27+
{
28+
private final HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(new HTTP2Client()));
29+
30+
@Override
31+
protected void doStart() throws Exception
32+
{
33+
addBean(httpClient);
34+
super.doStart();
35+
}
36+
37+
@Override
38+
public boolean handle(Request request, Response response, Callback callback) throws Exception
39+
{
40+
// Verify that the HTTP2Client dependencies are provided by the server
41+
// by making a request to an external server, as if this Handler was a proxy.
42+
43+
httpClient.newRequest("https://webtide.com/")
44+
.timeout(15, TimeUnit.SECONDS)
45+
.send(result ->
46+
{
47+
if (result.isSucceeded())
48+
{
49+
response.setStatus(result.getResponse().getStatus());
50+
callback.succeeded();
51+
}
52+
else
53+
{
54+
callback.failed(result.getFailure());
55+
}
56+
});
57+
return true;
58+
}
59+
}

‎jetty-core/jetty-tests/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<modules>
1515
<module>jetty-test-client-transports</module>
1616
<module>jetty-test-jmx</module>
17+
<module>jetty-test-http2-client-transport-provided-webapp</module>
1718
</modules>
1819

1920
<properties>

‎jetty-home/pom.xml

+4
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@
158158
<artifactId>jetty-gcloud-session-manager</artifactId>
159159
<optional>true</optional>
160160
</dependency>
161+
<dependency>
162+
<groupId>org.eclipse.jetty.http2</groupId>
163+
<artifactId>jetty-http2-client-transport</artifactId>
164+
</dependency>
161165
<dependency>
162166
<groupId>org.eclipse.jetty.http2</groupId>
163167
<artifactId>jetty-http2-server</artifactId>

‎tests/test-distribution/test-distribution-common/src/test/java/org/eclipse/jetty/tests/distribution/DistributionTests.java

+50
Original file line numberDiff line numberDiff line change
@@ -1892,4 +1892,54 @@ public void testStateTrackingModule() throws Exception
18921892
}
18931893
}
18941894
}
1895+
1896+
@Test
1897+
public void testHTTP2ClientInCoreWebAppProvidedByServer() throws Exception
1898+
{
1899+
String jettyVersion = System.getProperty("jettyVersion");
1900+
JettyHomeTester distribution = JettyHomeTester.Builder.newInstance()
1901+
.jettyVersion(jettyVersion)
1902+
.build();
1903+
1904+
try (JettyHomeTester.Run run1 = distribution.start("--add-modules=http,http2-client-transport,core-deploy"))
1905+
{
1906+
assertTrue(run1.awaitFor(START_TIMEOUT, TimeUnit.SECONDS));
1907+
assertEquals(0, run1.getExitValue());
1908+
1909+
Path jettyLogging = distribution.getJettyBase().resolve("resources/jetty-logging.properties");
1910+
String loggingConfig = """
1911+
org.eclipse.jetty.LEVEL=DEBUG
1912+
""";
1913+
Files.writeString(jettyLogging, loggingConfig, StandardOpenOption.TRUNCATE_EXISTING);
1914+
1915+
String name = "test-webapp";
1916+
Path webapps = distribution.getJettyBase().resolve("webapps");
1917+
Path webAppDirLib = webapps.resolve(name + ".d").resolve("lib");
1918+
Path webAppJar = distribution.resolveArtifact("org.eclipse.jetty:jetty-test-http2-client-transport-provided-webapp:jar:" + jettyVersion);
1919+
Files.copy(webAppJar, Files.createDirectories(webAppDirLib).resolve("webapp.jar"));
1920+
Files.writeString(webapps.resolve(name + ".xml"), """
1921+
<?xml version="1.0"?>
1922+
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
1923+
<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
1924+
<Set name="contextPath">/test</Set>
1925+
<Set name="handler">
1926+
<New class="org.eclipse.jetty.test.http2.client.transport.provided.HTTP2ClientTransportProvidedHandler" />
1927+
</Set>
1928+
</Configure>
1929+
""");
1930+
1931+
int port = Tester.freePort();
1932+
try (JettyHomeTester.Run run2 = distribution.start("jetty.http.port=" + port))
1933+
{
1934+
assertTrue(run2.awaitConsoleLogsFor("Started oejs.Server@", START_TIMEOUT, TimeUnit.SECONDS));
1935+
1936+
startHttpClient();
1937+
URI serverUri = URI.create("http://localhost:" + port + "/test/");
1938+
ContentResponse response = client.newRequest(serverUri)
1939+
.timeout(15, TimeUnit.SECONDS)
1940+
.send();
1941+
assertEquals(HttpStatus.OK_200, response.getStatus());
1942+
}
1943+
}
1944+
}
18951945
}

0 commit comments

Comments
 (0)
Please sign in to comment.