From 3174cfec89773d56327d745503d9bb71d894cfad Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 20 Oct 2022 11:58:44 -0500 Subject: [PATCH 01/42] Adding ContextHandlerDeepTest --- .../handler/ContextHandlerDeepTest.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java new file mode 100644 index 00000000000..6c47d83a6e6 --- /dev/null +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java @@ -0,0 +1,75 @@ +package org.eclipse.jetty.server.handler; + +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.HttpTester; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.LocalConnector; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.Callback; +import org.eclipse.jetty.util.component.LifeCycle; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ContextHandlerDeepTest +{ + private Server server; + private LocalConnector connector; + + private void startServer(Handler handler) throws Exception + { + server = new Server(); + connector = new LocalConnector(server); + server.addConnector(connector); + + server.setHandler(handler); + server.start(); + } + + @AfterEach + public void stopServer() + { + LifeCycle.stop(server); + } + + @Test + public void testNestedThreeDeepContextHandler() throws Exception + { + ContextHandler contextHandlerA = new ContextHandler(); + contextHandlerA.setContextPath("/a"); + ContextHandler contextHandlerB = new ContextHandler(); + contextHandlerB.setContextPath("/b"); + ContextHandler contextHandlerC = new ContextHandler(); + contextHandlerC.setContextPath("/c"); + + contextHandlerA.setHandler(contextHandlerB); + contextHandlerB.setHandler(contextHandlerC); + contextHandlerC.setHandler(new Handler.Processor() + { + @Override + public void process(Request request, Response response, Callback callback) + { + response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/plain; charset=utf-8"); + String msg = "contextPath=" + request.getContext().getContextPath(); + response.write(true, BufferUtil.toBuffer(msg), callback); + } + }); + + startServer(contextHandlerA); + + String rawRequest = """ + GET /a/b/c/d HTTP/1.1\r + Host: local\r + Connection: close\r + + """; + HttpTester.Response response = HttpTester.parseResponse(connector.getResponse(rawRequest)); + assertEquals(HttpStatus.OK_200, response.getStatus()); + assertEquals("contextPath=/a/b/c", response.getContent()); + } +} From f359023f065a76eb6bb42a8df3e899319cb6a9c4 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 20 Oct 2022 12:31:28 -0500 Subject: [PATCH 02/42] Adding more to ContextHandlerDeepTest --- .../server/handler/ContextHandlerDeepTest.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java index 6c47d83a6e6..f98659a44a2 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java @@ -14,6 +14,8 @@ import org.eclipse.jetty.util.component.LifeCycle; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.assertEquals; public class ContextHandlerDeepTest @@ -55,7 +57,17 @@ public class ContextHandlerDeepTest public void process(Request request, Response response, Callback callback) { response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/plain; charset=utf-8"); - String msg = "contextPath=" + request.getContext().getContextPath(); + String msg = """ + contextPath=%s + pathInContext=%s + httpURI.getPath=%s + """ + .formatted( + request.getContext().getContextPath(), + request.getPathInContext(), + request.getHttpURI().getPath() + ); + response.write(true, BufferUtil.toBuffer(msg), callback); } }); @@ -70,6 +82,8 @@ public class ContextHandlerDeepTest """; HttpTester.Response response = HttpTester.parseResponse(connector.getResponse(rawRequest)); assertEquals(HttpStatus.OK_200, response.getStatus()); - assertEquals("contextPath=/a/b/c", response.getContent()); + assertThat(response.getContent(), containsString("contextPath=/a/b/c\n")); + assertThat(response.getContent(), containsString("pathInContext=/d\n")); + assertThat(response.getContent(), containsString("httpURI.getPath=/a/b/c/d\n")); } } From 0b542dc29b8f61c984dabfd14d12d01a79bdb396 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 20 Oct 2022 16:30:58 -0500 Subject: [PATCH 03/42] Applying suggestions from @gregw in issue #8749 --- .../org/eclipse/jetty/server/Request.java | 35 +++++++++++++++++++ .../java/org/eclipse/jetty/server/Server.java | 2 +- .../jetty/server/handler/ContextHandler.java | 6 +++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 0f127e17e96..fa262382b13 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -150,6 +150,12 @@ public interface Request extends Attributes, Content.Source */ Context getContext(); + default String getContextPath() + { + Context context = getContext(); + return context == null ? null : context.getContextPath(); + } + /** * TODO see discussion in #7713, as this path should probably be canonically encoded - ie everything but %25 and %2F decoded * @return The part of the decoded path of the URI after any context path prefix has been removed. @@ -509,6 +515,35 @@ public interface Request extends Attributes, Content.Source return getWrapped().getContext(); } + @Override + public String getContextPath() + { + Context context = getContext(); + if (context == null) + return null; + + Request.Wrapper wrapper = this; + + String contextPath = context.getContextPath(); + + while (wrapper != null) + { + Request wrapped = wrapper.getWrapped(); + + Context outer = wrapped.getContext(); + if (context != outer) + { + if (outer == null || outer instanceof Server.ServerContext) + return contextPath; + contextPath = URIUtil.addPaths(outer.getContextPath(), contextPath); + context = outer; + } + + wrapper = wrapped instanceof Request.Wrapper w ? w : null; + } + return contextPath; + } + @Override public String getPathInContext() { diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 04d33e42263..98411fe133f 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -712,7 +712,7 @@ public class Server extends Handler.Wrapper implements Attributes private static class DynamicErrorProcessor extends ErrorProcessor {} - private class ServerContext extends Attributes.Wrapper implements Context + public class ServerContext extends Attributes.Wrapper implements Context { private ServerContext() { diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 6fbc19cc5a1..10636bc07a1 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -981,7 +981,11 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace @Override public String getContextPath() { - return _contextPath; + Context context = getContext(); + Request.Wrapper wrapper = this; + String contextPath = context.getContextPath(); + Context outer = wrapper.getWrapped().getContext(); + return (outer instanceof Server.ServerContext) ? contextPath : null; } @Override From 4c0c2a69888d810d6123d33c543424481515b0fd Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 20 Oct 2022 16:33:44 -0500 Subject: [PATCH 04/42] Reverting ContextHandler.Context change --- .../org/eclipse/jetty/server/handler/ContextHandler.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 10636bc07a1..6fbc19cc5a1 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -981,11 +981,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace @Override public String getContextPath() { - Context context = getContext(); - Request.Wrapper wrapper = this; - String contextPath = context.getContextPath(); - Context outer = wrapper.getWrapped().getContext(); - return (outer instanceof Server.ServerContext) ? contextPath : null; + return _contextPath; } @Override From 10305412c603f8166abf3284d34b5eb29d1304ee Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 20 Oct 2022 16:35:26 -0500 Subject: [PATCH 05/42] Use request.getContextPath() instead. --- .../eclipse/jetty/server/handler/ContextHandlerDeepTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java index f98659a44a2..6eb04153f3a 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java @@ -63,7 +63,7 @@ public class ContextHandlerDeepTest httpURI.getPath=%s """ .formatted( - request.getContext().getContextPath(), + request.getContextPath(), request.getPathInContext(), request.getHttpURI().getPath() ); From 578d921b2449886dfd351d80b30f61f127b6b609 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 20 Oct 2022 16:38:55 -0500 Subject: [PATCH 06/42] Adding missing license header --- .../server/handler/ContextHandlerDeepTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java index 6eb04153f3a..78dc2cccc18 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java @@ -1,3 +1,16 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + package org.eclipse.jetty.server.handler; import org.eclipse.jetty.http.HttpHeader; From 02aab52daabee95c473f52172661f3c5a570f087 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 21 Oct 2022 08:48:36 +1100 Subject: [PATCH 07/42] Added javadoc --- .../java/org/eclipse/jetty/server/Context.java | 3 +++ .../java/org/eclipse/jetty/server/Request.java | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java index 52e1fd8140a..ea02b843a2c 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java @@ -35,7 +35,10 @@ import org.eclipse.jetty.util.resource.Resource; public interface Context extends Attributes, Decorator, Executor { /** + *

Get the context path of this Context.

+ *

This may differ from the {@link Request#getContextPath()} in the uncommon case of nested contexts.

* @return The URI path prefix of the context, which may be null for the server context, or "/" for the root context. + * @see Request#getContextPath() */ String getContextPath(); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index fa262382b13..266e66d89a9 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -150,6 +150,14 @@ public interface Request extends Attributes, Content.Source */ Context getContext(); + /** + * Get the full context path. + * @return The full contextPath of the request. In the common case, this is equivalent to + * calling {@link Context#getContextPath()} on the context returned from {@link #getContext()}. + * However, in the case of nested contexts, this method will return the concatenation of nested + * context paths rather than just the current context path. + * @see Context#getContextPath() + */ default String getContextPath() { Context context = getContext(); @@ -157,8 +165,13 @@ public interface Request extends Attributes, Content.Source } /** - * TODO see discussion in #7713, as this path should probably be canonically encoded - ie everything but %25 and %2F decoded - * @return The part of the decoded path of the URI after any context path prefix has been removed. + *

Get the canonically encoded path of the URI, scoped to the current context.

+ *

The pathInContext represents the targeted resource within the current content for the request. + * In most circumstances it will be a semantic suffix of the URI returned from {@link #getHttpURI()}. + * However a wrapped request may alter one but not the other, and in such cases a handler should consider using + * {@link #getHttpURI()} when generating URIs visible outside of the current context.

+ * @return The part of the canonically encoded path of the URI after any context path prefix has been removed. + * @see HttpURI#getCanonicalPath() */ String getPathInContext(); From 3980958949f1af33b3c65da64f12439f6ddd1ddc Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 20 Oct 2022 16:58:24 -0500 Subject: [PATCH 08/42] Change Server.ServerContext to package-private --- .../src/main/java/org/eclipse/jetty/server/Server.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 98411fe133f..623e57a3bc1 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -712,7 +712,7 @@ public class Server extends Handler.Wrapper implements Attributes private static class DynamicErrorProcessor extends ErrorProcessor {} - public class ServerContext extends Attributes.Wrapper implements Context + class ServerContext extends Attributes.Wrapper implements Context { private ServerContext() { From 2fc83a1e61f557fe148e10117aa4e64b236885d9 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 20 Oct 2022 16:58:51 -0500 Subject: [PATCH 09/42] Drop the word "uncommon" --- .../src/main/java/org/eclipse/jetty/server/Context.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java index ea02b843a2c..f91eb14714f 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java @@ -36,7 +36,7 @@ public interface Context extends Attributes, Decorator, Executor { /** *

Get the context path of this Context.

- *

This may differ from the {@link Request#getContextPath()} in the uncommon case of nested contexts.

+ *

This may differ from the {@link Request#getContextPath()} in the case of nested contexts.

* @return The URI path prefix of the context, which may be null for the server context, or "/" for the root context. * @see Request#getContextPath() */ From 1885df7e03af1af0b8e178aca6021d0b1d7c92dd Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Sun, 23 Oct 2022 22:36:15 +1100 Subject: [PATCH 10/42] WIP replacing getPathInContext with static method --- .../docs/programming/server/HandlerDocs.java | 4 +- .../client/HttpClientProxyProtocolTest.java | 2 +- .../jetty/client/HttpClientProxyTest.java | 2 +- .../jetty/client/HttpClientRedirectTest.java | 8 +- .../eclipse/jetty/client/HttpClientTest.java | 4 +- .../jetty/client/HttpClientURITest.java | 16 ++-- .../eclipse/jetty/client/HttpCookieTest.java | 16 ++-- .../jetty/client/HttpRequestAbortTest.java | 2 +- .../client/ValidatingConnectionPoolTest.java | 2 +- .../fcgi/proxy/FastCGIProxyHandlerTest.java | 8 +- .../jetty/http2/tests/HTTP2CServer.java | 2 +- .../http2/tests/MaxConcurrentStreamsTest.java | 2 +- .../tests/MultiplexedConnectionPoolTest.java | 6 +- .../http2/tests/PushedResourcesTest.java | 4 +- .../jetty/http2/tests/StreamResetTest.java | 2 +- .../rewrite/handler/CompactPathRule.java | 9 +- .../handler/CookiePatternRuleTest.java | 2 +- .../jetty/server/CustomRequestLog.java | 2 +- .../org/eclipse/jetty/server/Request.java | 88 +++++++++++-------- .../eclipse/jetty/server/ResourceService.java | 2 +- .../handler/BufferedResponseHandler.java | 2 +- .../jetty/server/handler/ContextHandler.java | 35 +++----- .../handler/ContextHandlerCollection.java | 2 +- .../jetty/server/handler/ContextRequest.java | 11 +-- .../jetty/server/handler/DefaultHandler.java | 4 +- .../server/handler/InetAccessHandler.java | 2 +- .../server/handler/MovedContextHandler.java | 4 +- .../jetty/server/handler/ResourceHandler.java | 6 +- .../jetty/server/handler/TryPathsHandler.java | 12 +-- .../server/handler/gzip/GzipHandler.java | 2 +- .../server/internal/HttpChannelState.java | 8 +- .../jetty/server/CustomRequestLogTest.java | 2 +- .../jetty/server/ErrorProcessorTest.java | 12 +-- ...ttpConfigurationAuthorityOverrideTest.java | 6 +- .../SlowClientWithPipelinedRequestTest.java | 2 +- .../handler/ContextHandlerDeepTest.java | 4 +- .../server/handler/ContextHandlerTest.java | 2 +- .../jetty/server/handler/DumpHandler.java | 2 +- .../handler/ThreadLimitHandlerTest.java | 2 +- .../server/handler/TryPathsHandlerTest.java | 4 +- .../server/handler/gzip/GzipHandlerTest.java | 2 +- .../ssl/SniSslConnectionFactoryTest.java | 2 +- .../session/SimpleSessionHandlerTest.java | 2 +- .../jetty/session/TestableRequest.java | 6 -- .../transport/HttpClientIdleTimeoutTest.java | 4 +- .../transport/HttpClientStreamTest.java | 2 +- .../test/client/transport/HttpClientTest.java | 8 +- .../transport/HttpClientTimeoutTest.java | 4 +- .../unixdomain/server/UnixDomainTest.java | 2 +- .../core/server/WebSocketMappings.java | 2 +- .../core/server/WebSocketUpgradeHandler.java | 2 +- .../core/proxy/WebSocketProxyTest.java | 2 +- .../security/openid/OpenIdAuthenticator.java | 2 +- .../ee10/proxy/ConnectHandlerSSLTest.java | 2 +- .../jetty/ee10/proxy/ConnectHandlerTest.java | 2 +- .../ee10/proxy/ForwardProxyTLSServerTest.java | 2 +- .../jetty/ee10/servlet/DefaultServlet.java | 12 +-- .../ee10/servlet/ServletContextHandler.java | 2 +- .../servlet/security/SecurityHandler.java | 2 +- .../authentication/FormAuthenticator.java | 4 +- .../jetty/ee10/servlet/ErrorPageTest.java | 2 +- .../internal/JakartaServerUpgradeRequest.java | 3 +- .../internal/JakartaWebSocketCreator.java | 2 +- .../jetty/ee9/nested/ContextHandler.java | 2 +- .../org/eclipse/jetty/ee9/nested/Request.java | 4 +- .../jetty/ee9/nested/ContextHandlerTest.java | 3 +- .../eclipse/jetty/ee9/nested/RequestTest.java | 6 -- .../jetty/ee9/nested/ResponseTest.java | 6 -- .../ee9/proxy/ConnectHandlerSSLTest.java | 2 +- .../jetty/ee9/proxy/ConnectHandlerTest.java | 2 +- .../ee9/proxy/ForwardProxyTLSServerTest.java | 2 +- .../internal/JakartaServerUpgradeRequest.java | 3 +- .../internal/JakartaWebSocketCreator.java | 2 +- 73 files changed, 191 insertions(+), 221 deletions(-) diff --git a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/HandlerDocs.java b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/HandlerDocs.java index e00c0f2c9fc..4388c111295 100644 --- a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/HandlerDocs.java +++ b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/HandlerDocs.java @@ -165,7 +165,7 @@ public class HandlerDocs public Request.Processor handle(Request request) throws Exception { if (HttpMethod.GET.is(request.getMethod()) && - "greeting".equals(request.getPathInContext())) + "greeting".equals(Request.getPathInContext(request))) return this; return null; } @@ -207,7 +207,7 @@ public class HandlerDocs { String name = handler.getClass().getSimpleName().replace("Handler", ""); String path = "/" + name; - if (request.getPathInContext().equals(name)) + if (Request.getPathInContext(request).equals(name)) { Request.Processor processor = handler.handle(request); if (processor != null) diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java index 40831e51a0c..d31f45cbd63 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java @@ -172,7 +172,7 @@ public class HttpClientProxyProtocolTest EndPoint endPoint = request.getConnectionMetaData().getConnection().getEndPoint(); assertTrue(endPoint instanceof ProxyConnectionFactory.ProxyEndPoint); ProxyConnectionFactory.ProxyEndPoint proxyEndPoint = (ProxyConnectionFactory.ProxyEndPoint)endPoint; - if (request.getPathInContext().equals("/tls_version")) + if (Request.getPathInContext(request).equals("/tls_version")) { assertNotNull(proxyEndPoint.getTLV(typeTLS)); assertEquals(tlsVersion, proxyEndPoint.getAttribute(ProxyConnectionFactory.TLS_VERSION)); diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java index fefe462df57..33952a77910 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java @@ -163,7 +163,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest @Override public void process(org.eclipse.jetty.server.Request request, Response response, Callback callback) { - String target = request.getPathInContext(); + String target = org.eclipse.jetty.server.Request.getPathInContext(request); if (target.startsWith("/proxy")) { String authorization = request.getHeaders().get(HttpHeader.PROXY_AUTHORIZATION.asString()); diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java index 3b089c3beaf..4e5bb4a529d 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java @@ -445,7 +445,7 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest @Override public void process(Request request, org.eclipse.jetty.server.Response response, Callback callback) throws Exception { - if (request.getPathInContext().startsWith("/redirect")) + if (Request.getPathInContext(request).startsWith("/redirect")) { response.setStatus(HttpStatus.SEE_OTHER_303); response.getHeaders().put(HttpHeader.LOCATION, scenario.getScheme() + "://localhost:" + connector.getLocalPort() + "/ok"); @@ -537,7 +537,7 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest @Override protected void service(Request request, org.eclipse.jetty.server.Response response) throws Exception { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); if ("/one".equals(target)) { response.setStatus(HttpStatus.SEE_OTHER_303); @@ -588,7 +588,7 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest protected void service(Request request, org.eclipse.jetty.server.Response response) throws Exception { String serverURI = scenario.getScheme() + "://localhost:" + connector.getLocalPort(); - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); if ("/one".equals(target)) { Thread.sleep(timeout); @@ -676,7 +676,7 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest { Fields fields = Request.extractQueryParameters(request); - String[] paths = request.getPathInContext().split("/", 4); + String[] paths = Request.getPathInContext(request).split("/", 4); int status = Integer.parseInt(paths[1]); response.setStatus(status); diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java index 45099adc083..06cce0eb974 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java @@ -484,7 +484,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest @Override protected void service(org.eclipse.jetty.server.Request request, org.eclipse.jetty.server.Response response) { - if (request.getPathInContext().endsWith("/one")) + if (org.eclipse.jetty.server.Request.getPathInContext(request).endsWith("/one")) request.getConnectionMetaData().getConnection().getEndPoint().close(); } }); @@ -904,7 +904,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest protected void service(org.eclipse.jetty.server.Request request, org.eclipse.jetty.server.Response response) { List userAgents = request.getHeaders().getValuesList(HttpHeader.USER_AGENT); - if ("/ua".equals(request.getPathInContext())) + if ("/ua".equals(org.eclipse.jetty.server.Request.getPathInContext(request))) assertEquals(1, userAgents.size()); else assertEquals(0, userAgents.size()); diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java index e0330c0cb38..ee55a0ffd74 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java @@ -203,7 +203,7 @@ public class HttpClientURITest extends AbstractHttpClientServerTest @Override protected void service(org.eclipse.jetty.server.Request request, Response response) { - assertEquals(path, request.getPathInContext()); + assertEquals(path, org.eclipse.jetty.server.Request.getPathInContext(request)); } }); @@ -236,7 +236,7 @@ public class HttpClientURITest extends AbstractHttpClientServerTest @Override protected void service(org.eclipse.jetty.server.Request request, Response response) { - assertEquals(path, request.getPathInContext()); + assertEquals(path, org.eclipse.jetty.server.Request.getPathInContext(request)); assertEquals(query, request.getHttpURI().getQuery()); } }); @@ -273,7 +273,7 @@ public class HttpClientURITest extends AbstractHttpClientServerTest @Override protected void service(org.eclipse.jetty.server.Request request, Response response) { - assertEquals(path, request.getPathInContext()); + assertEquals(path, org.eclipse.jetty.server.Request.getPathInContext(request)); assertEquals(query, request.getHttpURI().getQuery()); } }); @@ -312,7 +312,7 @@ public class HttpClientURITest extends AbstractHttpClientServerTest @Override protected void service(org.eclipse.jetty.server.Request request, Response response) { - assertEquals(path, request.getPathInContext()); + assertEquals(path, org.eclipse.jetty.server.Request.getPathInContext(request)); assertEquals(query, request.getHttpURI().getQuery()); } }); @@ -354,7 +354,7 @@ public class HttpClientURITest extends AbstractHttpClientServerTest @Override protected void service(org.eclipse.jetty.server.Request request, Response response) { - assertEquals(path, request.getPathInContext()); + assertEquals(path, org.eclipse.jetty.server.Request.getPathInContext(request)); assertEquals(query, request.getHttpURI().getQuery()); Fields fields = org.eclipse.jetty.server.Request.extractQueryParameters(request); assertEquals(value1, fields.getValue(name1)); @@ -393,7 +393,7 @@ public class HttpClientURITest extends AbstractHttpClientServerTest @Override protected void service(org.eclipse.jetty.server.Request request, Response response) { - assertEquals(path, request.getPathInContext()); + assertEquals(path, org.eclipse.jetty.server.Request.getPathInContext(request)); assertEquals(query, request.getHttpURI().getQuery()); } }); @@ -426,7 +426,7 @@ public class HttpClientURITest extends AbstractHttpClientServerTest @Override protected void service(org.eclipse.jetty.server.Request request, Response response) { - assertEquals(path, request.getPathInContext()); + assertEquals(path, org.eclipse.jetty.server.Request.getPathInContext(request)); assertEquals(query, request.getHttpURI().getQuery()); } }); @@ -607,7 +607,7 @@ public class HttpClientURITest extends AbstractHttpClientServerTest protected void service(org.eclipse.jetty.server.Request request, Response response) { assertEquals("*", request.getHttpURI().getPath()); - assertEquals("*", request.getPathInContext()); + assertEquals("*", org.eclipse.jetty.server.Request.getPathInContext(request)); } }); diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpCookieTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpCookieTest.java index e4bdc8d829f..467936fdfe6 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpCookieTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpCookieTest.java @@ -179,7 +179,7 @@ public class HttpCookieTest extends AbstractHttpClientServerTest @Override protected void service(Request request, org.eclipse.jetty.server.Response response) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); int r = (int)request.getHeaders().getLongField(headerName); if ("/foo".equals(target) && r == 0) { @@ -234,7 +234,7 @@ public class HttpCookieTest extends AbstractHttpClientServerTest @Override protected void service(Request request, org.eclipse.jetty.server.Response response) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); int r = (int)request.getHeaders().getLongField(headerName); if ("/foo/bar".equals(target) && r == 0) { @@ -290,7 +290,7 @@ public class HttpCookieTest extends AbstractHttpClientServerTest @Override protected void service(Request request, org.eclipse.jetty.server.Response response) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); int r = (int)request.getHeaders().getLongField(headerName); if ("/foo".equals(target) && r == 0) { @@ -346,7 +346,7 @@ public class HttpCookieTest extends AbstractHttpClientServerTest @Override protected void service(Request request, org.eclipse.jetty.server.Response response) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); int r = (int)request.getHeaders().getLongField(headerName); if ("/foo/bar".equals(target) && r == 0) { @@ -403,7 +403,7 @@ public class HttpCookieTest extends AbstractHttpClientServerTest @Override protected void service(Request request, org.eclipse.jetty.server.Response response) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); int r = (int)request.getHeaders().getLongField(headerName); if ("/foo".equals(target) && r == 0) { @@ -462,7 +462,7 @@ public class HttpCookieTest extends AbstractHttpClientServerTest @Override protected void service(Request request, org.eclipse.jetty.server.Response response) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); int r = (int)request.getHeaders().getLongField(headerName); if ("/foo".equals(target) && r == 0) { @@ -528,7 +528,7 @@ public class HttpCookieTest extends AbstractHttpClientServerTest @Override protected void service(Request request, org.eclipse.jetty.server.Response response) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); int r = (int)request.getHeaders().getLongField(headerName); if ("/foo".equals(target) && r == 0) { @@ -598,7 +598,7 @@ public class HttpCookieTest extends AbstractHttpClientServerTest @Override protected void service(Request request, org.eclipse.jetty.server.Response response) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); int r = (int)request.getHeaders().getLongField(headerName); if ("/foo/bar".equals(target) && r == 0) { diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpRequestAbortTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpRequestAbortTest.java index 5576173918b..d870f25650f 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpRequestAbortTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpRequestAbortTest.java @@ -485,7 +485,7 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest @Override public void process(org.eclipse.jetty.server.Request request, Response response, Callback callback) { - if ("/done".equals(request.getPathInContext())) + if ("/done".equals(org.eclipse.jetty.server.Request.getPathInContext(request))) callback.succeeded(); else Response.sendRedirect(request, response, callback, "/done"); diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java index 8cbd3e35194..25f6cb1e959 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java @@ -73,7 +73,7 @@ public class ValidatingConnectionPoolTest extends AbstractHttpClientServerTest @Override protected void service(org.eclipse.jetty.server.Request request, Response response) throws Throwable { - if (request.getPathInContext().endsWith("/redirect")) + if (org.eclipse.jetty.server.Request.getPathInContext(request).endsWith("/redirect")) { response.setStatus(HttpStatus.TEMPORARY_REDIRECT_307); response.getHeaders().putLongField(HttpHeader.CONTENT_LENGTH, 0); diff --git a/jetty-core/jetty-fcgi/jetty-fcgi-proxy/src/test/java/org/eclipse/jetty/fcgi/proxy/FastCGIProxyHandlerTest.java b/jetty-core/jetty-fcgi/jetty-fcgi-proxy/src/test/java/org/eclipse/jetty/fcgi/proxy/FastCGIProxyHandlerTest.java index 33e8115ec4b..c95f8ec9f19 100644 --- a/jetty-core/jetty-fcgi/jetty-fcgi-proxy/src/test/java/org/eclipse/jetty/fcgi/proxy/FastCGIProxyHandlerTest.java +++ b/jetty-core/jetty-fcgi/jetty-fcgi-proxy/src/test/java/org/eclipse/jetty/fcgi/proxy/FastCGIProxyHandlerTest.java @@ -91,7 +91,7 @@ public class FastCGIProxyHandlerTest { HttpURI httpURI = request.getHttpURI(); HttpURI.Mutable newHttpURI = HttpURI.build(httpURI) - .path(appContextPath + request.getPathInContext()); + .path(appContextPath + Request.getPathInContext(request)); newHttpURI.port(unixDomainPath == null ? ((ServerConnector)serverConnector).getLocalPort() : 0); return newHttpURI; }, "/scriptRoot"); @@ -152,7 +152,7 @@ public class FastCGIProxyHandlerTest public void process(Request request, Response response, Callback callback) { assertNotEquals(proxyContext.getContextPath(), request.getContext().getContextPath()); - assertEquals(path, request.getPathInContext()); + assertEquals(path, Request.getPathInContext(request)); response.getHeaders().putLongField(HttpHeader.CONTENT_LENGTH, data.length); response.write(true, ByteBuffer.wrap(data), callback); } @@ -198,7 +198,7 @@ public class FastCGIProxyHandlerTest { assertThat((String)request.getAttribute(FCGI.Headers.REQUEST_URI), startsWith(originalPath)); assertEquals(originalQuery, request.getAttribute(FCGI.Headers.QUERY_STRING)); - assertThat(request.getPathInContext(), endsWith(remotePath)); + assertThat(Request.getPathInContext(request), endsWith(remotePath)); callback.succeeded(); } }); @@ -211,7 +211,7 @@ public class FastCGIProxyHandlerTest @Override public Request.Processor handle(Request request) throws Exception { - if (request.getPathInContext().startsWith("/remote/")) + if (Request.getPathInContext(request).startsWith("/remote/")) { request.setAttribute(pathAttribute, originalPath); request.setAttribute(queryAttribute, originalQuery); diff --git a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServer.java b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServer.java index 21f09e89196..735d2b19619 100644 --- a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServer.java +++ b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServer.java @@ -67,7 +67,7 @@ public class HTTP2CServer extends Server response.getHeaders().put("Custom", "Value"); response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/plain"); String content = "Hello from Jetty using " + request.getConnectionMetaData().getProtocol() + "\n"; - content += "uri=" + request.getPathInContext() + "\n"; + content += "uri=" + Request.getPathInContext(request) + "\n"; content += "date=" + new Date() + "\n"; response.getHeaders().putLongField(HttpHeader.CONTENT_LENGTH, content.length()); Content.Sink.write(response, true, content, callback); diff --git a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/MaxConcurrentStreamsTest.java b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/MaxConcurrentStreamsTest.java index 2832d8db17b..f6f802ac0ed 100644 --- a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/MaxConcurrentStreamsTest.java +++ b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/MaxConcurrentStreamsTest.java @@ -421,7 +421,7 @@ public class MaxConcurrentStreamsTest extends AbstractTest @Override public void process(Request request, org.eclipse.jetty.server.Response response, Callback callback) { - if (request.getPathInContext().endsWith("/1")) + if (Request.getPathInContext(request).endsWith("/1")) sleep(2 * timeout); callback.succeeded(); } diff --git a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/MultiplexedConnectionPoolTest.java b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/MultiplexedConnectionPoolTest.java index 96d8e252dcf..6f0841cce83 100644 --- a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/MultiplexedConnectionPoolTest.java +++ b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/MultiplexedConnectionPoolTest.java @@ -135,7 +135,7 @@ public class MultiplexedConnectionPoolTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - int req = Integer.parseInt(request.getPathInContext().substring(1)); + int req = Integer.parseInt(Request.getPathInContext(request).substring(1)); reqExecutingLatches[req].countDown(); Thread.sleep(250); reqExecutedLatches[req].countDown(); @@ -231,7 +231,7 @@ public class MultiplexedConnectionPoolTest @Override public void process(Request request, Response response, Callback callback) { - int req = Integer.parseInt(request.getPathInContext().substring(1)); + int req = Integer.parseInt(Request.getPathInContext(request).substring(1)); Content.Sink.write(response, true, "req " + req + " executed", callback); } }, 64, 1L); @@ -380,7 +380,7 @@ public class MultiplexedConnectionPoolTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - if (request.getPathInContext().equals("/block")) + if (Request.getPathInContext(request).equals("/block")) { handlerSignalingSemaphore.release(); handlerWaitingSemaphore.acquire(); diff --git a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/PushedResourcesTest.java b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/PushedResourcesTest.java index 569b178e537..aeecfb4b42b 100644 --- a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/PushedResourcesTest.java +++ b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/PushedResourcesTest.java @@ -108,7 +108,7 @@ public class PushedResourcesTest extends AbstractTest @Override public void process(Request request, Response response, Callback callback) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); if (target.equals(path1)) { response.write(true, ByteBuffer.wrap(pushBytes1), callback); @@ -173,7 +173,7 @@ public class PushedResourcesTest extends AbstractTest @Override public void process(Request request, Response response, Callback callback) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); if (target.equals(oldPath)) { Response.sendRedirect(request, response, callback, newPath); diff --git a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/StreamResetTest.java b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/StreamResetTest.java index 2fd97c025ae..acc8be6b9b1 100644 --- a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/StreamResetTest.java +++ b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/StreamResetTest.java @@ -928,7 +928,7 @@ public class StreamResetTest extends AbstractTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); if (target.equals("/1")) service1(request, response, callback); else if (target.equals("/2")) diff --git a/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java b/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java index f0223cc5967..fadab27eae8 100644 --- a/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java +++ b/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java @@ -15,6 +15,7 @@ package org.eclipse.jetty.rewrite.handler; import java.io.IOException; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.util.URIUtil; @@ -27,18 +28,20 @@ public class CompactPathRule extends Rule @Override public Request.WrapperProcessor matchAndApply(Request.WrapperProcessor input) throws IOException { - String path = input.getPathInContext(); + String path = Request.getPathInContext(input); String compacted = URIUtil.compactPath(path); if (path.equals(compacted)) return null; + HttpURI uri = Request.updateHttpURI(input, compacted); + return new Request.WrapperProcessor(input) { @Override - public String getPathInContext() + public HttpURI getHttpURI() { - return compacted; + return uri; } }; } diff --git a/jetty-core/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java b/jetty-core/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java index 1f8bacf6988..1b520d00250 100644 --- a/jetty-core/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java +++ b/jetty-core/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java @@ -43,7 +43,7 @@ public class CookiePatternRuleTest extends AbstractRuleTest public void process(Request request, Response response, Callback callback) { response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/plain;charset=utf-8"); - Content.Sink.write(response, false, "pathInContext=%s%n".formatted(request.getPathInContext()), Callback.NOOP); + Content.Sink.write(response, false, "pathInContext=%s%n".formatted(Request.getPathInContext(request)), Callback.NOOP); Content.Sink.write(response, false, "path=%s%n".formatted(request.getHttpURI().getPath()), Callback.NOOP); Content.Sink.write(response, false, "query=%s%n".formatted(request.getHttpURI().getQuery()), Callback.NOOP); Request original = Request.unWrap(request); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java index 3f8fd2da1d3..c7c9d2cf2de 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java @@ -1139,7 +1139,7 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog Resource baseResource = context.getBaseResource(); if (baseResource != null) { - String fileName = baseResource.resolve(request.getPathInContext()).getName(); + String fileName = baseResource.resolve(Request.getPathInContext(request)).getName(); append(b, fileName); } else diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 266e66d89a9..e4144dc0be7 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -152,16 +152,40 @@ public interface Request extends Attributes, Content.Source /** * Get the full context path. + * @param request The request to get the context path from. * @return The full contextPath of the request. In the common case, this is equivalent to * calling {@link Context#getContextPath()} on the context returned from {@link #getContext()}. * However, in the case of nested contexts, this method will return the concatenation of nested * context paths rather than just the current context path. * @see Context#getContextPath() */ - default String getContextPath() + static String getContextPath(Request request) { - Context context = getContext(); - return context == null ? null : context.getContextPath(); + Context context = request.getContext(); + if (context == null) + return null; + + if (!(request instanceof Request.Wrapper wrapper)) + return context.getContextPath(); + + String contextPath = context.getContextPath(); + + while (wrapper != null) + { + Request wrapped = wrapper.getWrapped(); + + Context outer = wrapped.getContext(); + if (context != outer) + { + if (outer == null || outer instanceof Server.ServerContext) + return contextPath; + contextPath = URIUtil.addPaths(outer.getContextPath(), contextPath); + context = outer; + } + + wrapper = wrapped instanceof Request.Wrapper w ? w : null; + } + return contextPath; } /** @@ -169,11 +193,27 @@ public interface Request extends Attributes, Content.Source *

The pathInContext represents the targeted resource within the current content for the request. * In most circumstances it will be a semantic suffix of the URI returned from {@link #getHttpURI()}. * However a wrapped request may alter one but not the other, and in such cases a handler should consider using + * @param request The request to get the path in the context from. * {@link #getHttpURI()} when generating URIs visible outside of the current context.

* @return The part of the canonically encoded path of the URI after any context path prefix has been removed. * @see HttpURI#getCanonicalPath() */ - String getPathInContext(); + static String getPathInContext(Request request) + { + String path = request.getHttpURI().getCanonicalPath(); + String contextPath = Request.getContextPath(request); + + if (StringUtil.isBlank(contextPath) || "/".equals(contextPath)) + return path; + + if (!path.startsWith(contextPath)) + return null; // TODO ISE??? + if (path.length() == contextPath.length()) + return ""; + if (path.charAt(contextPath.length()) != '/') + return null; // TODO ISE??? + return path.substring(contextPath.length()); + } /** * @return the HTTP headers of this request @@ -528,41 +568,6 @@ public interface Request extends Attributes, Content.Source return getWrapped().getContext(); } - @Override - public String getContextPath() - { - Context context = getContext(); - if (context == null) - return null; - - Request.Wrapper wrapper = this; - - String contextPath = context.getContextPath(); - - while (wrapper != null) - { - Request wrapped = wrapper.getWrapped(); - - Context outer = wrapped.getContext(); - if (context != outer) - { - if (outer == null || outer instanceof Server.ServerContext) - return contextPath; - contextPath = URIUtil.addPaths(outer.getContextPath(), contextPath); - context = outer; - } - - wrapper = wrapped instanceof Request.Wrapper w ? w : null; - } - return contextPath; - } - - @Override - public String getPathInContext() - { - return getWrapped().getPathInContext(); - } - @Override public HttpFields getHeaders() { @@ -737,4 +742,9 @@ public interface Request extends Attributes, Content.Source processor.process(this, response, callback); } } + + static HttpURI updateHttpURI(Request request, String newPathInContext) + { + return HttpURI.build(request.getHttpURI()).path(URIUtil.addPaths(getContextPath(request), newPathInContext)).asImmutable(); + } } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index f4d49646ffb..7558c1dc5e6 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -151,7 +151,7 @@ public class ResourceService public void doGet(Request request, Response response, Callback callback, HttpContent content) throws Exception { - String pathInContext = request.getPathInContext(); + String pathInContext = Request.getPathInContext(request); // Is this a Range request? List reqRanges = request.getHeaders().getValuesList(HttpHeader.RANGE.asString()); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/BufferedResponseHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/BufferedResponseHandler.java index 447303fc8f4..9b4bf9988a5 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/BufferedResponseHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/BufferedResponseHandler.java @@ -129,7 +129,7 @@ public class BufferedResponseHandler extends Handler.Wrapper if (processor == null) return null; - final String path = request.getPathInContext(); + final String path = Request.getPathInContext(request); if (LOG.isDebugEnabled()) LOG.debug("{} handle {} in {}", this, request, request.getContext()); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 29574168805..e9db7ff262d 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -593,20 +593,6 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace return false; } - protected String getPathInContext(Request request) - { - String path = request.getPathInContext(); - if (!path.startsWith(_context.getContextPath())) - return null; - if ("/".equals(_context.getContextPath())) - return path; - if (path.length() == _context.getContextPath().length()) - return ""; - if (path.charAt(_context.getContextPath().length()) != '/') - return null; - return path.substring(_context.getContextPath().length()); - } - @Override public void destroy() { @@ -622,18 +608,23 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace if (!checkVirtualHost(request)) return null; - String pathInContext = getPathInContext(request); - if (pathInContext == null) + String path = Request.getPathInContext(request); + if (!path.startsWith(_contextPath)) return null; - if (pathInContext.isEmpty() && !getAllowNullPathInContext()) - return this::processMovedPermanently; + if (_contextPath.length() == path.length()) + { + if (!getAllowNullPathInContext()) + return this::processMovedPermanently; + } + else if (path.charAt(_contextPath.length()) != '/') + return null; // TODO check availability and maybe return a 503 if (!isAvailable() && isStarted()) return this::processUnavailable; - ContextRequest contextRequest = wrap(request, pathInContext); + ContextRequest contextRequest = wrap(request); // wrap might fail (eg ServletContextHandler could not match a servlet) if (contextRequest == null) return null; @@ -665,7 +656,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace protected Request.Processor processByContextHandler(ContextRequest contextRequest) { - if (!_allowNullPathInContext && StringUtil.isEmpty(contextRequest.getPathInContext())) + if (!_allowNullPathInContext && StringUtil.isEmpty(Request.getPathInContext(contextRequest))) { return (request, response, callback) -> { @@ -777,9 +768,9 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace _errorProcessor = errorProcessor; } - protected ContextRequest wrap(Request request, String pathInContext) + protected ContextRequest wrap(Request request) { - return new ContextRequest(this, _context, request, pathInContext); + return new ContextRequest(this, _context, request); } @Override diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java index e7ac1496cf0..af72d05d0ee 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java @@ -140,7 +140,7 @@ public class ContextHandlerCollection extends Handler.Collection if (pathBranches == null) return null; - String path = request.getPathInContext(); + String path = Request.getPathInContext(request); if (!path.startsWith("/")) { super.handle(request); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextRequest.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextRequest.java index 6a4cd691ad0..7a4193c593f 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextRequest.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextRequest.java @@ -28,16 +28,14 @@ import org.slf4j.LoggerFactory; public class ContextRequest extends Request.WrapperProcessor implements Invocable, Supplier, Runnable { private static final Logger LOG = LoggerFactory.getLogger(ContextRequest.class); - private final String _pathInContext; private final ContextHandler _contextHandler; private final ContextHandler.Context _context; private Response _response; private Callback _callback; - protected ContextRequest(ContextHandler contextHandler, ContextHandler.Context context, Request wrapped, String pathInContext) + protected ContextRequest(ContextHandler contextHandler, ContextHandler.Context context, Request wrapped) { super(wrapped); - _pathInContext = pathInContext; _contextHandler = contextHandler; _context = context; } @@ -115,11 +113,6 @@ public class ContextRequest extends Request.WrapperProcessor implements Invocabl return _context; } - public String getPathInContext() - { - return _pathInContext; - } - @Override public Object getAttribute(String name) { @@ -127,7 +120,7 @@ public class ContextRequest extends Request.WrapperProcessor implements Invocabl return switch (name) { case "o.e.j.s.h.ScopedRequest.contextPath" -> _context.getContextPath(); - case "o.e.j.s.h.ScopedRequest.pathInContext" -> _pathInContext; + case "o.e.j.s.h.ScopedRequest.pathInContext" -> Request.getPathInContext(this); default -> super.getAttribute(name); }; } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java index b7a13523715..805649d9871 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java @@ -109,7 +109,7 @@ public class DefaultHandler extends Handler.Processor String method = request.getMethod(); // little cheat for common request - if (isServeIcon() && _favicon != null && HttpMethod.GET.is(method) && request.getPathInContext().equals("/favicon.ico")) + if (isServeIcon() && _favicon != null && HttpMethod.GET.is(method) && Request.getPathInContext(request).equals("/favicon.ico")) { ByteBuffer content = BufferUtil.EMPTY_BUFFER; if (_faviconModifiedMs > 0 && request.getHeaders().getDateField(HttpHeader.IF_MODIFIED_SINCE) == _faviconModifiedMs) @@ -127,7 +127,7 @@ public class DefaultHandler extends Handler.Processor return; } - if (!isShowContexts() || !HttpMethod.GET.is(method) || !request.getPathInContext().equals("/")) + if (!isShowContexts() || !HttpMethod.GET.is(method) || !Request.getPathInContext(request).equals("/")) { Response.writeError(request, response, callback, HttpStatus.NOT_FOUND_404, null); return; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/InetAccessHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/InetAccessHandler.java index d4baf81b4e4..10d1730614d 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/InetAccessHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/InetAccessHandler.java @@ -222,7 +222,7 @@ public class InetAccessHandler extends Handler.Wrapper protected boolean isAllowed(InetAddress addr, Request request) { String connectorName = request.getConnectionMetaData().getConnector().getName(); - String path = request.getPathInContext(); + String path = Request.getPathInContext(request); return _set.test(new AccessTuple(connectorName, addr, path)); } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java index 9c28b730564..ec2d58f69ca 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java @@ -102,8 +102,8 @@ public class MovedContextHandler extends ContextHandler return; String path = _newContextURL; - if (!_discardPathInfo && request.getPathInContext() != null) - path = URIUtil.addPaths(path, request.getPathInContext()); + if (!_discardPathInfo && Request.getPathInContext(request) != null) + path = URIUtil.addPaths(path, Request.getPathInContext(request)); HttpURI uri = request.getHttpURI(); StringBuilder location = new StringBuilder(); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java index 86c845ccacb..fe78924e1e3 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java @@ -92,8 +92,8 @@ public class ResourceHandler extends Handler.Wrapper for (String welcome : _welcomes) { - String welcomeInContext = URIUtil.addPaths(request.getPathInContext(), welcome); - Resource welcomePath = _resourceBase.resolve(request.getPathInContext()).resolve(welcome); + String welcomeInContext = URIUtil.addPaths(Request.getPathInContext(request), welcome); + Resource welcomePath = _resourceBase.resolve(Request.getPathInContext(request)).resolve(welcome); if (Resources.isReadableFile(welcomePath)) return welcomeInContext; } @@ -111,7 +111,7 @@ public class ResourceHandler extends Handler.Wrapper return super.handle(request); } - HttpContent content = _resourceService.getContent(request.getPathInContext(), request); + HttpContent content = _resourceService.getContent(Request.getPathInContext(request), request); if (content == null) return super.handle(request); // no content - try other handlers diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java index 4a4fa86fd63..0c28d858182 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java @@ -15,9 +15,11 @@ package org.eclipse.jetty.server.handler; import java.util.List; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Context; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.resource.Resource; /** @@ -77,24 +79,24 @@ public class TryPathsHandler extends Handler.Wrapper private String interpolate(Request request, String value) { - String path = request.getPathInContext(); + String path = Request.getPathInContext(request); return value.replace("$path", path); } private static class TryPathsRequest extends Request.Wrapper { - private final String pathInContext; + private final HttpURI uri; public TryPathsRequest(Request wrapped, String pathInContext) { super(wrapped); - this.pathInContext = pathInContext; + uri = HttpURI.build(wrapped.getHttpURI()).path(URIUtil.addPaths(Request.getContextPath(wrapped), pathInContext)); } @Override - public String getPathInContext() + public HttpURI getHttpURI() { - return pathInContext; + return uri; } } } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java index 1ad8e64f155..478b975eb1b 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java @@ -523,7 +523,7 @@ public class GzipHandler extends Handler.Wrapper implements GzipFactory @Override public Request.Processor handle(Request request) throws Exception { - final String path = request.getPathInContext(); + final String path = Request.getPathInContext(request); if (LOG.isDebugEnabled()) LOG.debug("{} handle {}", this, request); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpChannelState.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpChannelState.java index 568dcb64658..cc97e13e5aa 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpChannelState.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpChannelState.java @@ -605,7 +605,7 @@ public class HttpChannelState implements HttpChannel, Components { if (!HttpMethod.PRI.is(request.getMethod()) && !HttpMethod.CONNECT.is(request.getMethod()) && - !_request.getPathInContext().startsWith("/") && + !Request.getPathInContext(_request).startsWith("/") && !HttpMethod.OPTIONS.is(request.getMethod())) { _processState = ProcessState.PROCESSING; @@ -903,12 +903,6 @@ public class HttpChannelState implements HttpChannel, Components return getConnectionMetaData().getConnector().getServer().getContext(); } - @Override - public String getPathInContext() - { - return _metaData.getURI().getCanonicalPath(); - } - @Override public HttpFields getHeaders() { diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/CustomRequestLogTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/CustomRequestLogTest.java index bd5b805b57a..e2116d864ab 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/CustomRequestLogTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/CustomRequestLogTest.java @@ -614,7 +614,7 @@ public class CustomRequestLogTest @Override public void process(Request request, Response response, Callback callback) { - if (request.getPathInContext().equals("/abort")) + if (Request.getPathInContext(request).equals("/abort")) { Callback cbk = Callback.from(() -> callback.failed(new QuietException.Exception("test fail")), callback::failed); Content.Sink.write(response, false, "data", cbk); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java index ae530278deb..d253c93c237 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java @@ -71,21 +71,21 @@ public class ErrorProcessorTest @Override public void process(Request request, Response response, Callback callback) { - if (request.getPathInContext().startsWith("/badmessage/")) + if (Request.getPathInContext(request).startsWith("/badmessage/")) { - int code = Integer.parseInt(request.getPathInContext().substring(request.getPathInContext().lastIndexOf('/') + 1)); + int code = Integer.parseInt(Request.getPathInContext(request).substring(Request.getPathInContext(request).lastIndexOf('/') + 1)); throw new BadMessageException(code); } // produce an exception with an JSON formatted cause message - if (request.getPathInContext().startsWith("/jsonmessage/")) + if (Request.getPathInContext(request).startsWith("/jsonmessage/")) { String message = "\"}, \"glossary\": {\n \"title\": \"example\"\n }\n {\""; throw new TestException(message); } // produce an exception with an XML cause message - if (request.getPathInContext().startsWith("/xmlmessage/")) + if (Request.getPathInContext(request).startsWith("/xmlmessage/")) { String message = "\n" + @@ -96,14 +96,14 @@ public class ErrorProcessorTest } // produce an exception with an HTML cause message - if (request.getPathInContext().startsWith("/htmlmessage/")) + if (Request.getPathInContext(request).startsWith("/htmlmessage/")) { String message = "
%3Cscript%3E"; throw new TestException(message); } // produce an exception with a UTF-8 cause message - if (request.getPathInContext().startsWith("/utf8message/")) + if (Request.getPathInContext(request).startsWith("/utf8message/")) { // @checkstyle-disable-check : AvoidEscapedUnicodeCharacters String message = "Euro is € and \u20AC and %E2%82%AC"; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConfigurationAuthorityOverrideTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConfigurationAuthorityOverrideTest.java index 8f733868597..17e73ee4c75 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConfigurationAuthorityOverrideTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConfigurationAuthorityOverrideTest.java @@ -654,7 +654,7 @@ public class HttpConfigurationAuthorityOverrideTest @Override public Request.Processor handle(Request request) throws Exception { - if (!request.getPathInContext().startsWith("/dump")) + if (!Request.getPathInContext(request).startsWith("/dump")) return null; return (rq, rs, cb) -> { @@ -679,7 +679,7 @@ public class HttpConfigurationAuthorityOverrideTest @Override public Request.Processor handle(Request request) throws Exception { - if (!request.getPathInContext().startsWith("/redirect")) + if (!Request.getPathInContext(request).startsWith("/redirect")) return null; return (rq, rs, cb) -> @@ -696,7 +696,7 @@ public class HttpConfigurationAuthorityOverrideTest @Override public Request.Processor handle(Request request) throws Exception { - if (!request.getPathInContext().startsWith("/error")) + if (!Request.getPathInContext(request).startsWith("/error")) return null; return super.handle(request); } diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java index 2283b6f401b..b6f8ddf0d2b 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java @@ -84,7 +84,7 @@ public class SlowClientWithPipelinedRequestTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - if ("/content".equals(request.getPathInContext())) + if ("/content".equals(Request.getPathInContext(request))) { // TODO is this still a valid test? // We simulate what the DefaultServlet does, bypassing the blocking diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java index 78dc2cccc18..cc526beee4b 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java @@ -76,8 +76,8 @@ public class ContextHandlerDeepTest httpURI.getPath=%s """ .formatted( - request.getContextPath(), - request.getPathInContext(), + Request.getContextPath(request), + Request.getPathInContext(request), request.getHttpURI().getPath() ); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java index 733a6bb0433..2b4e8f3ea4e 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java @@ -188,7 +188,7 @@ public class ContextHandlerTest { if (request != null) { - assertThat(request.getPathInContext(), equalTo("/path")); + assertThat(Request.getPathInContext(request), equalTo("/path")); assertThat(request.getContext(), sameInstance(_context)); } assertThat(ContextHandler.getCurrentContext(), sameInstance(_context)); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DumpHandler.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DumpHandler.java index 3565e7b82d7..ed3c2f0aa49 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DumpHandler.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DumpHandler.java @@ -150,7 +150,7 @@ public class DumpHandler extends Handler.Processor.Blocking writer.write("
httpURI.path=" + httpURI.getPath() + "

\n"); writer.write("
httpURI.query=" + httpURI.getQuery() + "

\n"); writer.write("
httpURI.pathQuery=" + httpURI.getPathQuery() + "

\n"); - writer.write("
pathInContext=" + request.getPathInContext() + "

\n"); + writer.write("
pathInContext=" + Request.getPathInContext(request) + "

\n"); writer.write("
contentType=" + request.getHeaders().get(HttpHeader.CONTENT_TYPE) + "

\n"); writer.write("
servername=" + Request.getServerName(request) + "

\n"); writer.write("
local=" + Request.getLocalAddr(request) + ":" + Request.getLocalPort(request) + "

\n"); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ThreadLimitHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ThreadLimitHandlerTest.java index 18546d38b0a..3236af83d05 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ThreadLimitHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ThreadLimitHandlerTest.java @@ -199,7 +199,7 @@ public class ThreadLimitHandlerTest public void process(Request request, Response response, Callback callback) throws Exception { response.setStatus(HttpStatus.OK_200); - if (!"/other".equals(request.getPathInContext())) + if (!"/other".equals(Request.getPathInContext(request))) { try { diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java index 677f70bb512..4af25272461 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java @@ -99,7 +99,7 @@ public class TryPathsHandlerTest @Override public void process(Request request, Response response, Callback callback) { - assertThat(request.getPathInContext(), equalTo("/forward?p=/last")); + assertThat(Request.getPathInContext(request), equalTo("/forward?p=/last")); response.setStatus(HttpStatus.NO_CONTENT_204); callback.succeeded(); } @@ -155,7 +155,7 @@ public class TryPathsHandlerTest HttpURI httpURI = request.getHttpURI(); assertEquals("https", httpURI.getScheme()); assertTrue(request.isSecure()); - assertEquals(path, request.getPathInContext()); + assertEquals(path, Request.getPathInContext(request)); callback.succeeded(); } }); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java index 9275c207f28..ac9e8179088 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java @@ -148,7 +148,7 @@ public class GzipHandlerTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - String pathInfo = request.getPathInContext(); + String pathInfo = Request.getPathInContext(request); response.getHeaders().put(HttpHeader.CONTENT_TYPE, getContentTypeFromRequest(pathInfo, request)); Content.Sink.write(response, true, "This is content for " + pathInfo + "\n", callback); } diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java index 5f109352919..8fd71a8cd03 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java @@ -139,7 +139,7 @@ public class SniSslConnectionFactoryTest public void process(Request request, Response response, Callback callback) throws Exception { response.setStatus(200); - response.getHeaders().put("X-URL", request.getPathInContext()); + response.getHeaders().put("X-URL", Request.getPathInContext(request)); response.getHeaders().put("X-HOST", Request.getServerName(request)); callback.succeeded(); } diff --git a/jetty-core/jetty-session/src/test/java/org/eclipse/jetty/session/SimpleSessionHandlerTest.java b/jetty-core/jetty-session/src/test/java/org/eclipse/jetty/session/SimpleSessionHandlerTest.java index e9703c7900d..0436fca57ae 100644 --- a/jetty-core/jetty-session/src/test/java/org/eclipse/jetty/session/SimpleSessionHandlerTest.java +++ b/jetty-core/jetty-session/src/test/java/org/eclipse/jetty/session/SimpleSessionHandlerTest.java @@ -62,7 +62,7 @@ public class SimpleSessionHandlerTest @Override public void process(Request request, Response response, Callback callback) { - String pathInContext = request.getPathInContext(); + String pathInContext = Request.getPathInContext(request); String[] split = pathInContext.substring(1).split("/"); SessionRequest sessionRequest = Request.as(request, SessionRequest.class); diff --git a/jetty-core/jetty-session/src/test/java/org/eclipse/jetty/session/TestableRequest.java b/jetty-core/jetty-session/src/test/java/org/eclipse/jetty/session/TestableRequest.java index 03573681cda..d8d77e215a8 100644 --- a/jetty-core/jetty-session/src/test/java/org/eclipse/jetty/session/TestableRequest.java +++ b/jetty-core/jetty-session/src/test/java/org/eclipse/jetty/session/TestableRequest.java @@ -96,12 +96,6 @@ public class TestableRequest implements Request return null; } - @Override - public String getPathInContext() - { - return null; - } - @Override public HttpFields getHeaders() { diff --git a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientIdleTimeoutTest.java b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientIdleTimeoutTest.java index 5513eddb338..0d9d95680ea 100644 --- a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientIdleTimeoutTest.java +++ b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientIdleTimeoutTest.java @@ -42,7 +42,7 @@ public class HttpClientIdleTimeoutTest extends AbstractTest public void process(Request request, Response response, Callback callback) throws Exception { // Do not succeed the callback if it's a timeout request. - if (!request.getPathInContext().equals("/timeout")) + if (!Request.getPathInContext(request).equals("/timeout")) callback.succeeded(); } }); @@ -76,7 +76,7 @@ public class HttpClientIdleTimeoutTest extends AbstractTest public void process(Request request, Response response, Callback callback) throws Exception { // Do not succeed the callback if it's a timeout request. - if (!request.getPathInContext().equals("/timeout")) + if (!Request.getPathInContext(request).equals("/timeout")) callback.succeeded(); } }); diff --git a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientStreamTest.java b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientStreamTest.java index bb2b8c183c9..9003d116c13 100644 --- a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientStreamTest.java +++ b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientStreamTest.java @@ -1069,7 +1069,7 @@ public class HttpClientStreamTest extends AbstractTest @Override public void process(Request request, org.eclipse.jetty.server.Response response, Callback callback) { - if (request.getPathInContext().startsWith("/303")) + if (Request.getPathInContext(request).startsWith("/303")) org.eclipse.jetty.server.Response.sendRedirect(request, response, callback, "/200"); callback.succeeded(); } diff --git a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTest.java b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTest.java index 8460a42fee9..ec53294c320 100644 --- a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTest.java +++ b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTest.java @@ -369,7 +369,7 @@ public class HttpClientTest extends AbstractTest public void process(Request request, org.eclipse.jetty.server.Response response, Callback callback) { assertTrue(HttpMethod.OPTIONS.is(request.getMethod())); - assertEquals("*", request.getPathInContext()); + assertEquals("*", Request.getPathInContext(request)); callback.succeeded(); } }); @@ -392,7 +392,7 @@ public class HttpClientTest extends AbstractTest @Override public void process(Request request, org.eclipse.jetty.server.Response response, Callback callback) { - if ("*".equals(request.getPathInContext())) + if ("*".equals(Request.getPathInContext(request))) { // Be nasty and send a relative redirect. // Code 303 will change the method to GET. @@ -566,7 +566,7 @@ public class HttpClientTest extends AbstractTest @Override public void process(Request request, org.eclipse.jetty.server.Response response, Callback callback) { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); if ("/notMapped".equals(target)) org.eclipse.jetty.server.Response.writeError(request, response, callback, HttpStatus.NOT_FOUND_404); else @@ -762,7 +762,7 @@ public class HttpClientTest extends AbstractTest @Override public void process(Request request, org.eclipse.jetty.server.Response response, Callback callback) throws Exception { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); if (target.equals("/1")) assertTrue(latch.await(5, TimeUnit.SECONDS)); else if (target.equals("/2")) diff --git a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTimeoutTest.java b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTimeoutTest.java index a3c06c46630..7e821391ea0 100644 --- a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTimeoutTest.java +++ b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTimeoutTest.java @@ -424,7 +424,7 @@ public class HttpClientTimeoutTest extends AbstractTest @Override public void process(org.eclipse.jetty.server.Request request, org.eclipse.jetty.server.Response response, Callback callback) throws Exception { - if (request.getPathInContext().startsWith("/one")) + if (org.eclipse.jetty.server.Request.getPathInContext(request).startsWith("/one")) Thread.sleep(3 * timeout); callback.succeeded(); } @@ -460,7 +460,7 @@ public class HttpClientTimeoutTest extends AbstractTest @Override public void process(org.eclipse.jetty.server.Request request, org.eclipse.jetty.server.Response response, Callback callback) throws Exception { - if (request.getPathInContext().startsWith("/one")) + if (org.eclipse.jetty.server.Request.getPathInContext(request).startsWith("/one")) serverLatch.await(); callback.succeeded(); } diff --git a/jetty-core/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java b/jetty-core/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java index 96bf751ddaf..d7a1a982b2e 100644 --- a/jetty-core/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java +++ b/jetty-core/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java @@ -205,7 +205,7 @@ public class UnixDomainTest assertThat(endPoint, Matchers.instanceOf(ProxyConnectionFactory.ProxyEndPoint.class)); assertThat(endPoint.getLocalSocketAddress(), Matchers.instanceOf(unixDomainSocketAddressClass)); assertThat(endPoint.getRemoteSocketAddress(), Matchers.instanceOf(unixDomainSocketAddressClass)); - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); if ("/v1".equals(target)) { // As PROXYv1 does not support UNIX, the wrapped EndPoint data is used. diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketMappings.java b/jetty-core/jetty-websocket/jetty-websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketMappings.java index 7f86efd370e..6bd20c35498 100644 --- a/jetty-core/jetty-websocket/jetty-websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketMappings.java +++ b/jetty-core/jetty-websocket/jetty-websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketMappings.java @@ -246,7 +246,7 @@ public class WebSocketMappings implements Dumpable, LifeCycle.Listener */ public boolean upgrade(Request request, Response response, Callback callback, Configuration.Customizer defaultCustomizer) throws IOException { - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); WebSocketNegotiator negotiator = getMatchedNegotiator(target, pathSpec -> { // Store PathSpec resource mapping as request attribute, diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketUpgradeHandler.java b/jetty-core/jetty-websocket/jetty-websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketUpgradeHandler.java index c02c7897486..1e800954b5c 100644 --- a/jetty-core/jetty-websocket/jetty-websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketUpgradeHandler.java +++ b/jetty-core/jetty-websocket/jetty-websocket-core-server/src/main/java/org/eclipse/jetty/websocket/core/server/WebSocketUpgradeHandler.java @@ -68,7 +68,7 @@ public class WebSocketUpgradeHandler extends Handler.Wrapper if (processor == null) return null; - String target = request.getPathInContext(); + String target = Request.getPathInContext(request); WebSocketNegotiator negotiator = mappings.getMatchedNegotiator(target, pathSpec -> { // Store PathSpec resource mapping as request attribute, diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/proxy/WebSocketProxyTest.java b/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/proxy/WebSocketProxyTest.java index e243375cd58..ed14e513b09 100644 --- a/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/proxy/WebSocketProxyTest.java +++ b/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/proxy/WebSocketProxyTest.java @@ -83,7 +83,7 @@ public class WebSocketProxyTest { if (request.getHeaders().get("Upgrade") != null) { - if (blockServerUpgradeRequests && request.getPathInContext().startsWith("/server")) + if (blockServerUpgradeRequests && Request.getPathInContext(request).startsWith("/server")) { return (req, resp, cb) -> Response.writeError(req, resp, cb, HttpStatus.INTERNAL_SERVER_ERROR_500); } diff --git a/jetty-ee10/jetty-ee10-openid/src/main/java/org/eclipse/jetty/ee10/security/openid/OpenIdAuthenticator.java b/jetty-ee10/jetty-ee10-openid/src/main/java/org/eclipse/jetty/ee10/security/openid/OpenIdAuthenticator.java index 18a79d2ab4f..22dd8d1cd32 100644 --- a/jetty-ee10/jetty-ee10-openid/src/main/java/org/eclipse/jetty/ee10/security/openid/OpenIdAuthenticator.java +++ b/jetty-ee10/jetty-ee10-openid/src/main/java/org/eclipse/jetty/ee10/security/openid/OpenIdAuthenticator.java @@ -395,7 +395,7 @@ public class OpenIdAuthenticator extends LoginAuthenticator if (!mandatory) return new DeferredAuthentication(this); - if (isErrorPage(baseRequest.getPathInContext()) && !DeferredAuthentication.isDeferred(res)) + if (isErrorPage(Request.getPathInContext(baseRequest)) && !DeferredAuthentication.isDeferred(res)) return new DeferredAuthentication(this); try diff --git a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ConnectHandlerSSLTest.java b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ConnectHandlerSSLTest.java index 7922d88d25d..c4c4a7214dc 100644 --- a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ConnectHandlerSSLTest.java +++ b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ConnectHandlerSSLTest.java @@ -155,7 +155,7 @@ public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - String uri = request.getPathInContext(); + String uri = Request.getPathInContext(request); if ("/echo".equals(uri)) { StringBuilder builder = new StringBuilder(); diff --git a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ConnectHandlerTest.java b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ConnectHandlerTest.java index 3486aef1cda..0b777b22680 100644 --- a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ConnectHandlerTest.java +++ b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ConnectHandlerTest.java @@ -843,7 +843,7 @@ public class ConnectHandlerTest extends AbstractConnectHandlerTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - String cp = request.getPathInContext(); + String cp = Request.getPathInContext(request); switch (cp) { case "/echo" -> diff --git a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyTLSServerTest.java b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyTLSServerTest.java index 768613919a2..f13cf29215c 100644 --- a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyTLSServerTest.java +++ b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyTLSServerTest.java @@ -1009,7 +1009,7 @@ public class ForwardProxyTLSServerTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - String uri = request.getPathInContext(); + String uri = Request.getPathInContext(request); if ("/echo".equals(uri)) { if (request.getHttpURI().getQuery() != null) diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java index 25f069278be..3142ee8a04e 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java @@ -464,13 +464,7 @@ public class DefaultServlet extends HttpServlet @Override public HttpURI getHttpURI() { - return _request.getHttpURI(); - } - - @Override - public String getPathInContext() - { - return URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo()); + return Request.updateHttpURI(_request, URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo())); } @Override @@ -962,7 +956,7 @@ public class DefaultServlet extends HttpServlet return null; } - String requestTarget = isPathInfoOnly() ? request.getPathInfo() : coreRequest.getPathInContext(); + String requestTarget = isPathInfoOnly() ? request.getPathInfo() : Request.getPathInContext(coreRequest); String welcomeServlet = null; Resource base = _baseResource.resolve(requestTarget); @@ -971,7 +965,7 @@ public class DefaultServlet extends HttpServlet for (String welcome : welcomes) { Resource welcomePath = base.resolve(welcome); - String welcomeInContext = URIUtil.addPaths(coreRequest.getPathInContext(), welcome); + String welcomeInContext = URIUtil.addPaths(Request.getPathInContext(coreRequest), welcome); if (Resources.isReadableFile(welcomePath)) return welcomeInContext; diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java index cded2cbfb7c..d4efdb15ee8 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java @@ -1185,7 +1185,7 @@ public class ServletContextHandler extends ContextHandler implements Graceful } @Override - protected ServletContextRequest wrap(Request request, String pathInContext) + protected ServletContextRequest wrap(Request request) { MatchedResource matchedResource = _servletHandler.getMatchedServlet(pathInContext); if (matchedResource == null) diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/SecurityHandler.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/SecurityHandler.java index 42d18bb632f..525a5f325f3 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/SecurityHandler.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/SecurityHandler.java @@ -514,7 +514,7 @@ public abstract class SecurityHandler extends Handler.Wrapper implements Authent if (isAuthMandatory) { - boolean authorized = checkWebResourcePermissions(request.getPathInContext(), request, response, roleInfo, userAuth.getUserIdentity()); + boolean authorized = checkWebResourcePermissions(Request.getPathInContext(request), request, response, roleInfo, userAuth.getUserIdentity()); if (!authorized) { Response.writeError(request, response, callback, HttpServletResponse.SC_FORBIDDEN, "!role"); diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java index 168a5ba4caf..bddb2328dc8 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java @@ -223,12 +223,12 @@ public class FormAuthenticator extends LoginAuthenticator ServletContextRequest servletContextRequest = Request.as(req, ServletContextRequest.class); ServletContextRequest.ServletApiRequest servletApiRequest = servletContextRequest.getServletApiRequest(); - boolean jSecurityCheck = isJSecurityCheck(req.getPathInContext()); + boolean jSecurityCheck = isJSecurityCheck(Request.getPathInContext(req)); mandatory |= jSecurityCheck; if (!mandatory) return new DeferredAuthentication(this); - if (isLoginOrErrorPage(req.getPathInContext()) && !DeferredAuthentication.isDeferred(res)) + if (isLoginOrErrorPage(Request.getPathInContext(req)) && !DeferredAuthentication.isDeferred(res)) return new DeferredAuthentication(this); // Handle a request for authentication. diff --git a/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/ErrorPageTest.java b/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/ErrorPageTest.java index cd04214ea9d..5916c167a83 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/ErrorPageTest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/ErrorPageTest.java @@ -106,7 +106,7 @@ public class ErrorPageTest @Override public Request.Processor handle(Request request) throws Exception { - if (request.getPathInContext().startsWith("/noop")) + if (Request.getPathInContext(request).startsWith("/noop")) return null; else return super.handle(request); diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/server/internal/JakartaServerUpgradeRequest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/server/internal/JakartaServerUpgradeRequest.java index 89318b798df..91e24665bde 100644 --- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/server/internal/JakartaServerUpgradeRequest.java +++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/server/internal/JakartaServerUpgradeRequest.java @@ -17,6 +17,7 @@ import java.net.URI; import java.security.Principal; import org.eclipse.jetty.ee10.websocket.jakarta.common.UpgradeRequest; +import org.eclipse.jetty.server.Request; import org.eclipse.jetty.websocket.core.server.ServerUpgradeRequest; public class JakartaServerUpgradeRequest implements UpgradeRequest @@ -44,6 +45,6 @@ public class JakartaServerUpgradeRequest implements UpgradeRequest @Override public String getPathInContext() { - return servletRequest.getPathInContext(); + return Request.getPathInContext(servletRequest); } } diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/server/internal/JakartaWebSocketCreator.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/server/internal/JakartaWebSocketCreator.java index 3d1359e05a8..8c205c968ae 100644 --- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/server/internal/JakartaWebSocketCreator.java +++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/server/internal/JakartaWebSocketCreator.java @@ -139,7 +139,7 @@ public class JakartaWebSocketCreator implements WebSocketCreator { // We can get path params from PathSpec and Request Path. UriTemplatePathSpec pathSpec = (UriTemplatePathSpec)pathSpecObject; - Map pathParams = pathSpec.getPathParams(request.getPathInContext()); + Map pathParams = pathSpec.getPathParams(Request.getPathInContext(request)); // Wrap the config with the path spec information. config = new PathParamServerEndpointConfig(config, pathParams); diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java index 5dbd3d7de9e..b078971ce9d 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java @@ -2456,7 +2456,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu } @Override - protected ContextRequest wrap(org.eclipse.jetty.server.Request request, String pathInContext) + protected ContextRequest wrap(org.eclipse.jetty.server.Request request) { HttpChannel httpChannel = (HttpChannel)request.getComponents().getCache().get(HttpChannel.class.getName()); if (httpChannel == null) diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java index f13b547fddd..ac6b3642c8b 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java @@ -1546,8 +1546,8 @@ public class Request implements HttpServletRequest _uri = coreRequest.getHttpURI(); _pathInContext = _context.getContextHandler().isCanonicalEncodingURIs() - ? coreRequest.getPathInContext() - : URIUtil.decodePath(coreRequest.getPathInContext()); + ? org.eclipse.jetty.server.Request.getPathInContext(coreRequest) + : URIUtil.decodePath(org.eclipse.jetty.server.Request.getPathInContext(coreRequest)); _httpFields = coreRequest.getHeaders(); setSecure(coreRequest.isSecure()); diff --git a/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ContextHandlerTest.java b/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ContextHandlerTest.java index 8c3ecf58be7..b96ca04a8e4 100644 --- a/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ContextHandlerTest.java +++ b/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ContextHandlerTest.java @@ -34,7 +34,6 @@ import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.LocalConnector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; -import org.eclipse.jetty.server.handler.DefaultHandler; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -176,7 +175,7 @@ public class ContextHandlerTest coreRequest.connectionMetaData.persistent=%b """.formatted( - coreRequest.getPathInContext(), + org.eclipse.jetty.server.Request.getPathInContext(coreRequest), baseRequest.hashCode(), coreRequest.getId(), coreRequest.getConnectionMetaData().getId(), diff --git a/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/RequestTest.java b/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/RequestTest.java index 65edb724e16..2d9622b281d 100644 --- a/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/RequestTest.java +++ b/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/RequestTest.java @@ -2293,12 +2293,6 @@ public class RequestTest return null; } - @Override - public String getPathInContext() - { - return _uri; - } - @Override public HttpFields getHeaders() { diff --git a/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ResponseTest.java b/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ResponseTest.java index 2c84055fa85..cfc5169cb34 100644 --- a/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ResponseTest.java +++ b/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/ResponseTest.java @@ -2305,12 +2305,6 @@ public class ResponseTest return _context; } - @Override - public String getPathInContext() - { - return _reqMeta.getURI().getCanonicalPath(); - } - @Override public HttpFields getHeaders() { diff --git a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ConnectHandlerSSLTest.java b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ConnectHandlerSSLTest.java index f6446961bd1..67290c8b78f 100644 --- a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ConnectHandlerSSLTest.java +++ b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ConnectHandlerSSLTest.java @@ -155,7 +155,7 @@ public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - String uri = request.getPathInContext(); + String uri = Request.getPathInContext(request); if ("/echo".equals(uri)) { StringBuilder builder = new StringBuilder(); diff --git a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ConnectHandlerTest.java b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ConnectHandlerTest.java index b1f59a59ff7..b4b8a3d260e 100644 --- a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ConnectHandlerTest.java +++ b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ConnectHandlerTest.java @@ -843,7 +843,7 @@ public class ConnectHandlerTest extends AbstractConnectHandlerTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - String cp = request.getPathInContext(); + String cp = Request.getPathInContext(request); switch (cp) { case "/echo" -> diff --git a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyTLSServerTest.java b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyTLSServerTest.java index 5e4b0edc453..89b312a9f1e 100644 --- a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyTLSServerTest.java +++ b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyTLSServerTest.java @@ -885,7 +885,7 @@ public class ForwardProxyTLSServerTest @Override public void process(Request request, Response response, Callback callback) throws Exception { - String uri = request.getPathInContext(); + String uri = Request.getPathInContext(request); if ("/echo".equals(uri)) { if (request.getHttpURI().getQuery() != null) diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/server/internal/JakartaServerUpgradeRequest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/server/internal/JakartaServerUpgradeRequest.java index 34c96546d78..b079f3417f5 100644 --- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/server/internal/JakartaServerUpgradeRequest.java +++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/server/internal/JakartaServerUpgradeRequest.java @@ -17,6 +17,7 @@ import java.net.URI; import java.security.Principal; import org.eclipse.jetty.ee9.websocket.jakarta.common.UpgradeRequest; +import org.eclipse.jetty.server.Request; import org.eclipse.jetty.websocket.core.server.ServerUpgradeRequest; public class JakartaServerUpgradeRequest implements UpgradeRequest @@ -45,6 +46,6 @@ public class JakartaServerUpgradeRequest implements UpgradeRequest @Override public String getPathInContext() { - return servletRequest.getPathInContext(); + return Request.getPathInContext(servletRequest); } } diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/server/internal/JakartaWebSocketCreator.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/server/internal/JakartaWebSocketCreator.java index 58d140f0b8d..979cb8439de 100644 --- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/server/internal/JakartaWebSocketCreator.java +++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-server/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/server/internal/JakartaWebSocketCreator.java @@ -139,7 +139,7 @@ public class JakartaWebSocketCreator implements WebSocketCreator { // We can get path params from PathSpec and Request Path. UriTemplatePathSpec pathSpec = (UriTemplatePathSpec)pathSpecObject; - Map pathParams = pathSpec.getPathParams(request.getPathInContext()); + Map pathParams = pathSpec.getPathParams(Request.getPathInContext(request)); // Wrap the config with the path spec information. config = new PathParamServerEndpointConfig(config, pathParams); From 30401d8cf84bb6be07e5253d2cf2b2c00bbce816 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 24 Oct 2022 11:26:50 +1100 Subject: [PATCH 11/42] WIP replacing getPathInContext with static method --- .../java/org/eclipse/jetty/http/HttpURI.java | 2 + .../org/eclipse/jetty/server/Context.java | 6 +-- .../org/eclipse/jetty/server/Request.java | 54 +++---------------- .../java/org/eclipse/jetty/server/Server.java | 6 +++ .../jetty/server/handler/ContextHandler.java | 46 ++++++++++++---- .../jetty/server/handler/TryPathsHandler.java | 6 +-- .../handler/ContextHandlerDeepTest.java | 4 +- .../server/handler/TryPathsHandlerTest.java | 2 +- .../org/eclipse/jetty/util/Attributes.java | 22 ++++---- .../java/org/eclipse/jetty/util/URIUtil.java | 23 ++++++++ .../jetty/ee10/servlet/ServletChannel.java | 6 +-- .../ee10/servlet/ServletContextHandler.java | 3 +- .../ee10/servlet/ServletContextRequest.java | 11 ++-- .../jetty/ee9/nested/ContextHandler.java | 5 +- .../eclipse/jetty/ee9/nested/Dispatcher.java | 16 +++--- 15 files changed, 116 insertions(+), 96 deletions(-) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index fe2d1cece9b..364870ad9fa 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -889,6 +889,8 @@ public interface HttpURI { if (hasAuthority() && !isPathValidForAuthority(path)) throw new IllegalArgumentException("Relative path with authority"); + if (!URIUtil.isLegalPath(path)) + throw new IllegalArgumentException("Path not correctly encoded: " + path); _uri = null; _path = path; _canonicalPath = null; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java index f91eb14714f..31c29c9a34d 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java @@ -36,9 +36,6 @@ public interface Context extends Attributes, Decorator, Executor { /** *

Get the context path of this Context.

- *

This may differ from the {@link Request#getContextPath()} in the case of nested contexts.

- * @return The URI path prefix of the context, which may be null for the server context, or "/" for the root context. - * @see Request#getContextPath() */ String getContextPath(); @@ -59,4 +56,7 @@ public interface Context extends Attributes, Decorator, Executor /** scope the calling thread to the context and request and run the runnable. */ void run(Runnable runnable, Request request); + + /** Return a URI path scoped to this context **/ + String pathInContext(String path); } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index e4144dc0be7..6d42ac2667f 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -151,68 +151,26 @@ public interface Request extends Attributes, Content.Source Context getContext(); /** - * Get the full context path. + *

Get the context pat. this is equivalent to request.getContext().getContextPath() + * * @param request The request to get the context path from. - * @return The full contextPath of the request. In the common case, this is equivalent to - * calling {@link Context#getContextPath()} on the context returned from {@link #getContext()}. - * However, in the case of nested contexts, this method will return the concatenation of nested - * context paths rather than just the current context path. + * @return The contextPath of the request. . * @see Context#getContextPath() */ static String getContextPath(Request request) { - Context context = request.getContext(); - if (context == null) - return null; - - if (!(request instanceof Request.Wrapper wrapper)) - return context.getContextPath(); - - String contextPath = context.getContextPath(); - - while (wrapper != null) - { - Request wrapped = wrapper.getWrapped(); - - Context outer = wrapped.getContext(); - if (context != outer) - { - if (outer == null || outer instanceof Server.ServerContext) - return contextPath; - contextPath = URIUtil.addPaths(outer.getContextPath(), contextPath); - context = outer; - } - - wrapper = wrapped instanceof Request.Wrapper w ? w : null; - } - return contextPath; + return request.getContext().getContextPath(); } /** *

Get the canonically encoded path of the URI, scoped to the current context.

- *

The pathInContext represents the targeted resource within the current content for the request. - * In most circumstances it will be a semantic suffix of the URI returned from {@link #getHttpURI()}. - * However a wrapped request may alter one but not the other, and in such cases a handler should consider using - * @param request The request to get the path in the context from. - * {@link #getHttpURI()} when generating URIs visible outside of the current context.

+ *

The pathInContext represents the targeted resource within the current content for the request.

* @return The part of the canonically encoded path of the URI after any context path prefix has been removed. * @see HttpURI#getCanonicalPath() */ static String getPathInContext(Request request) { - String path = request.getHttpURI().getCanonicalPath(); - String contextPath = Request.getContextPath(request); - - if (StringUtil.isBlank(contextPath) || "/".equals(contextPath)) - return path; - - if (!path.startsWith(contextPath)) - return null; // TODO ISE??? - if (path.length() == contextPath.length()) - return ""; - if (path.charAt(contextPath.length()) != '/') - return null; // TODO ISE??? - return path.substring(contextPath.length()); + return request.getContext().pathInContext(request.getHttpURI().getCanonicalPath()); } /** diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 623e57a3bc1..e7c387a456c 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -785,6 +785,12 @@ public class Server extends Handler.Wrapper implements Attributes if (factory != null) factory.destroy(o); } + + @Override + public String pathInContext(String path) + { + return path; + } } private class ServerEnvironment extends Attributes.Wrapper implements Environment diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index e9db7ff262d..eeaadf707d7 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.EventListener; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; @@ -94,6 +95,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace private String _displayName; private String _contextPath = "/"; + private boolean _rootContext; private Resource _baseResource; private ClassLoader _classLoader; private Request.Processor _errorProcessor; @@ -608,17 +610,26 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace if (!checkVirtualHost(request)) return null; - String path = Request.getPathInContext(request); - if (!path.startsWith(_contextPath)) - return null; - - if (_contextPath.length() == path.length()) + // Root context accepts all requests + if (!_rootContext) { - if (!getAllowNullPathInContext()) - return this::processMovedPermanently; + // Otherwise check the path + + String path = request.getHttpURI().getCanonicalPath(); + if (path == null || !path.startsWith(_contextPath)) + return null; + + if (path.length() == _contextPath.length()) + { + if (!getAllowNullPathInContext()) + return this::processMovedPermanently; + } + else + { + if (path.charAt(_contextPath.length()) != '/') + return null; + } } - else if (path.charAt(_contextPath.length()) != '/') - return null; // TODO check availability and maybe return a 503 if (!isAvailable() && isStarted()) @@ -678,7 +689,8 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace { if (isStarted()) throw new IllegalStateException(getState()); - _contextPath = URIUtil.canonicalPath(contextPath); + _contextPath = URIUtil.canonicalPath(Objects.requireNonNull(contextPath)); + _rootContext = "/".equals(contextPath); } /** @@ -1154,6 +1166,20 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace if (factory != null) factory.destroy(o); } + + @Override + public String pathInContext(String path) + { + if (_rootContext) + return path; + if (!path.startsWith(_contextPath)) + return null; + if (path.length() == _contextPath.length()) + return ""; + if (path.charAt(_contextPath.length()) != '/') + return null; + return path.substring(_contextPath.length()); + } } /** diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java index 0c28d858182..6935719544d 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java @@ -85,18 +85,18 @@ public class TryPathsHandler extends Handler.Wrapper private static class TryPathsRequest extends Request.Wrapper { - private final HttpURI uri; + private final HttpURI _uri; public TryPathsRequest(Request wrapped, String pathInContext) { super(wrapped); - uri = HttpURI.build(wrapped.getHttpURI()).path(URIUtil.addPaths(Request.getContextPath(wrapped), pathInContext)); + _uri = Request.updateHttpURI(wrapped, URIUtil.canonicalPath(pathInContext)); } @Override public HttpURI getHttpURI() { - return uri; + return _uri; } } } diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java index cc526beee4b..229a04f5640 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerDeepTest.java @@ -58,9 +58,9 @@ public class ContextHandlerDeepTest ContextHandler contextHandlerA = new ContextHandler(); contextHandlerA.setContextPath("/a"); ContextHandler contextHandlerB = new ContextHandler(); - contextHandlerB.setContextPath("/b"); + contextHandlerB.setContextPath("/a/b"); ContextHandler contextHandlerC = new ContextHandler(); - contextHandlerC.setContextPath("/c"); + contextHandlerC.setContextPath("/a/b/c"); contextHandlerA.setHandler(contextHandlerB); contextHandlerB.setHandler(contextHandlerC); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java index 4af25272461..ea1d98f160c 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java @@ -99,7 +99,7 @@ public class TryPathsHandlerTest @Override public void process(Request request, Response response, Callback callback) { - assertThat(Request.getPathInContext(request), equalTo("/forward?p=/last")); + assertThat(Request.getPathInContext(request), equalTo("/forward%3Fp=/last")); response.setStatus(HttpStatus.NO_CONTENT_204); callback.succeeded(); } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java index 56684918598..ff2611e39e4 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java @@ -170,60 +170,60 @@ public interface Attributes */ class Wrapper implements Attributes { - protected final Attributes _attributes; + private final Attributes _wrapped; - public Wrapper(Attributes attributes) + public Wrapper(Attributes wrapped) { - _attributes = attributes; + _wrapped = wrapped; } public Attributes getWrapped() { - return _attributes; + return _wrapped; } @Override public Object removeAttribute(String name) { - return _attributes.removeAttribute(name); + return _wrapped.removeAttribute(name); } @Override public Object setAttribute(String name, Object attribute) { - return _attributes.setAttribute(name, attribute); + return _wrapped.setAttribute(name, attribute); } @Override public Object getAttribute(String name) { - return _attributes.getAttribute(name); + return _wrapped.getAttribute(name); } @Override public Set getAttributeNameSet() { - return _attributes.getAttributeNameSet(); + return _wrapped.getAttributeNameSet(); } @Override public void clearAttributes() { - _attributes.clearAttributes(); + _wrapped.clearAttributes(); } // TODO: remove? or fix (don't want the wrapped and wrapper to match) @Override public int hashCode() { - return _attributes.hashCode(); + return _wrapped.hashCode(); } // TODO: remove? or fix (don't want the wrapped and wrapper to match) @Override public boolean equals(Object obj) { - return _attributes.equals(obj); + return _wrapped.equals(obj); } } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java index 96a6f45163a..31dc97ed0e8 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java @@ -697,6 +697,29 @@ public final class URIUtil } } + /** + * @param path The path to check for legality + * @return True if the path does not contain any illegal path characters + */ + public static boolean isLegalPath(String path) + { + if (path == null) + return true; + + int end = path.length(); + for (int i = 0; i < end; i++) + { + char c = path.charAt(i); + switch (c) + { + case '?' : + case '#' : + return false; + } + } + return true; + } + /** * Test if codepoint is safe and unambiguous to pass as input to {@link URI} * diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletChannel.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletChannel.java index c34fed3b173..412fcfd8458 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletChannel.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletChannel.java @@ -397,7 +397,7 @@ public class ServletChannel implements Runnable ServletHandler servletHandler = servletContextApi.getContext().getServletContextHandler().getServletHandler(); ServletHandler.MappedServlet mappedServlet = _request._mappedServlet; - mappedServlet.handle(servletHandler, _request.getPathInContext(), _request.getHttpServletRequest(), _request.getHttpServletResponse()); + mappedServlet.handle(servletHandler, Request.getPathInContext(_request), _request.getHttpServletRequest(), _request.getHttpServletResponse()); }); break; @@ -408,7 +408,7 @@ public class ServletChannel implements Runnable dispatch(DispatcherType.ASYNC, () -> { HttpURI uri; - String pathInContext = _request.getPathInContext(); + String pathInContext = Request.getPathInContext(_request); AsyncContextEvent asyncContextEvent = _state.getAsyncContextEvent(); String dispatchString = asyncContextEvent.getDispatchPath(); if (dispatchString != null) @@ -796,7 +796,7 @@ public class ServletChannel implements Runnable if (authentication instanceof Authentication.User userAuthentication) _request.setAttribute(CustomRequestLog.USER_NAME, userAuthentication.getUserIdentity().getUserPrincipal().getName()); - String realPath = apiRequest.getServletContext().getRealPath(_request.getPathInContext()); + String realPath = apiRequest.getServletContext().getRealPath(Request.getPathInContext(_request)); _request.setAttribute(CustomRequestLog.REAL_PATH, realPath); String servletName = _request.getServletName(); diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java index d4efdb15ee8..09fb8e18f57 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java @@ -1187,6 +1187,7 @@ public class ServletContextHandler extends ContextHandler implements Graceful @Override protected ServletContextRequest wrap(Request request) { + String pathInContext = getContext().pathInContext(request.getHttpURI().getCanonicalPath()); MatchedResource matchedResource = _servletHandler.getMatchedServlet(pathInContext); if (matchedResource == null) return null; @@ -1216,7 +1217,7 @@ public class ServletContextHandler extends ContextHandler implements Graceful { ServletContextRequest scopedRequest = Request.as(request, ServletContextRequest.class); DispatcherType dispatch = scopedRequest.getHttpServletRequest().getDispatcherType(); - if (dispatch == DispatcherType.REQUEST && isProtectedTarget(request.getPathInContext())) + if (dispatch == DispatcherType.REQUEST && isProtectedTarget(scopedRequest.getPathInContext())) return (req, resp, cb) -> Response.writeError(req, resp, cb, HttpServletResponse.SC_NOT_FOUND, null); return super.processByContextHandler(request); diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java index e585366e0d1..fd1d2dd98b0 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java @@ -138,7 +138,7 @@ public class ServletContextRequest extends ContextRequest implements Runnable PathSpec pathSpec, MatchedPath matchedPath) { - super(servletContextApi.getContextHandler(), servletContextApi.getContext(), request, pathInContext); + super(servletContextApi.getContextHandler(), servletContextApi.getContext(), request); _servletChannel = servletChannel; _httpServletRequest = new ServletApiRequest(); _mappedServlet = mappedServlet; @@ -148,6 +148,11 @@ public class ServletContextRequest extends ContextRequest implements Runnable _matchedPath = matchedPath; } + public String getPathInContext() + { + return _pathInContext; + } + @Override public void process(Request request, Response response, Callback callback) throws Exception { @@ -237,8 +242,8 @@ public class ServletContextRequest extends ContextRequest implements Runnable { case "o.e.j.s.s.ServletScopedRequest.request" -> _httpServletRequest; case "o.e.j.s.s.ServletScopedRequest.response" -> _response.getHttpServletResponse(); - case "o.e.j.s.s.ServletScopedRequest.servlet" -> _mappedServlet.getServletPathMapping(getPathInContext()).getServletName(); - case "o.e.j.s.s.ServletScopedRequest.url-pattern" -> _mappedServlet.getServletPathMapping(getPathInContext()).getPattern(); + case "o.e.j.s.s.ServletScopedRequest.servlet" -> _mappedServlet.getServletPathMapping(_pathInContext).getServletName(); + case "o.e.j.s.s.ServletScopedRequest.url-pattern" -> _mappedServlet.getServletPathMapping(_pathInContext).getPattern(); default -> super.getAttribute(name); }; } diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java index b078971ce9d..02ad570627d 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java @@ -2365,10 +2365,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu protected CoreContextRequest(org.eclipse.jetty.server.handler.ContextHandler contextHandler, org.eclipse.jetty.server.handler.ContextHandler.Context context, org.eclipse.jetty.server.Request wrapped, - String pathInContext, HttpChannel httpChannel) { - super(contextHandler, context, wrapped, pathInContext); + super(contextHandler, context, wrapped); _httpChannel = httpChannel; } @@ -2474,7 +2473,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu httpChannel = new HttpChannel(ContextHandler.this, request.getConnectionMetaData()); } - CoreContextRequest coreContextRequest = new CoreContextRequest(this, this.getContext(), request, pathInContext, httpChannel); + CoreContextRequest coreContextRequest = new CoreContextRequest(this, this.getContext(), request, httpChannel); httpChannel.onRequest(coreContextRequest); return coreContextRequest; } diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Dispatcher.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Dispatcher.java index aa6c1e1bec1..150da3a60c7 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Dispatcher.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Dispatcher.java @@ -305,14 +305,14 @@ public class Dispatcher implements RequestDispatcher if (key.startsWith(__INCLUDE_PREFIX)) return null; - return _attributes.getAttribute(key); + return getWrapped().getAttribute(key); } @Override public Set getAttributeNameSet() { HashSet set = new HashSet<>(); - for (String name : _attributes.getAttributeNameSet()) + for (String name : getWrapped().getAttributeNameSet()) { if (!name.startsWith(__INCLUDE_PREFIX) && !name.startsWith(__FORWARD_PREFIX)) @@ -345,13 +345,13 @@ public class Dispatcher implements RequestDispatcher // name is set here, it will be hidden by this class during the forward, // but revealed after the forward is complete just as if the reserved name // attribute had be set by the application before the forward. - return _attributes.setAttribute(key, value); + return getWrapped().setAttribute(key, value); } @Override public String toString() { - return "FORWARD+" + _attributes.toString(); + return "FORWARD+" + getWrapped().toString(); } @Override @@ -438,14 +438,14 @@ public class Dispatcher implements RequestDispatcher } } - return _attributes.getAttribute(key); + return getWrapped().getAttribute(key); } @Override public Set getAttributeNameSet() { HashSet set = new HashSet<>(); - for (String name : _attributes.getAttributeNameSet()) + for (String name : getWrapped().getAttributeNameSet()) { if (!name.startsWith(__INCLUDE_PREFIX)) set.add(name); @@ -481,13 +481,13 @@ public class Dispatcher implements RequestDispatcher { // Allow any attribute to be set, even if a reserved name. If a reserved // name is set here, it will be revealed after the include is complete. - return _attributes.setAttribute(key, value); + return getWrapped().setAttribute(key, value); } @Override public String toString() { - return "INCLUDE+" + _attributes.toString(); + return "INCLUDE+" + getWrapped().toString(); } @Override From b25f69806c352c6b5525ece7a190af6107ebe460 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 24 Oct 2022 16:30:09 +1100 Subject: [PATCH 12/42] WIP replacing getPathInContext with static method --- .../src/main/java/org/eclipse/jetty/server/Request.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 6d42ac2667f..7099ec83dc1 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -142,6 +142,8 @@ public interface Request extends Attributes, Content.Source /** * @return the HTTP URI of this request + * @see #getContextPath(Request) + * @see #getPathInContext(Request) */ HttpURI getHttpURI(); From 465ddf0932c51eccd6d264d7d3168a235e99a1a2 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 24 Oct 2022 17:55:16 +1100 Subject: [PATCH 13/42] WIP replacing getPathInContext with static method --- .../java/org/eclipse/jetty/server/handler/ContextHandler.java | 2 +- .../test/java/org/eclipse/jetty/ee9/nested/RequestTest.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index eeaadf707d7..596f9e5fe2b 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -95,7 +95,7 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace private String _displayName; private String _contextPath = "/"; - private boolean _rootContext; + private boolean _rootContext = true; private Resource _baseResource; private ClassLoader _classLoader; private Request.Processor _errorProcessor; diff --git a/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/RequestTest.java b/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/RequestTest.java index 2d9622b281d..d24b75893dd 100644 --- a/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/RequestTest.java +++ b/jetty-ee9/jetty-ee9-nested/src/test/java/org/eclipse/jetty/ee9/nested/RequestTest.java @@ -2246,6 +2246,7 @@ public class RequestTest private static class TestCoreRequest implements org.eclipse.jetty.server.Request { + private final Server _server = new Server(); private final ConnectionMetaData _connectionMetaData; private final String _uri; private final HttpFields.Mutable _fields; @@ -2290,7 +2291,7 @@ public class RequestTest @Override public Context getContext() { - return null; + return _server.getContext(); } @Override From 14d912c654bc0d1ec83c86b9e74172310e7cedfd Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 24 Oct 2022 21:02:18 +1100 Subject: [PATCH 14/42] replaced getPathInContext with static method --- .../src/main/java/org/eclipse/jetty/http/HttpURI.java | 11 +++++++++++ .../test/java/org/eclipse/jetty/http/HttpURITest.java | 9 +++++++++ .../main/java/org/eclipse/jetty/server/Request.java | 4 +++- .../eclipse/jetty/ee10/servlet/DefaultServlet.java | 8 +++++++- .../jetty/ee10/servlet/DefaultServletTest.java | 2 +- 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 364870ad9fa..f45e72c9f86 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -894,6 +894,17 @@ public interface HttpURI _uri = null; _path = path; _canonicalPath = null; + + // If the passed path does not have a parameter, then keep the current parameter + // else delete the current parameter + if (_param != null) + { + if (path.indexOf(';') >= 0) + _param = null; + else + _path = _path + ';' + _param; + } + return this; } diff --git a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java index 6851455cd46..3cee87700f5 100644 --- a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +++ b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java @@ -916,4 +916,13 @@ public class HttpURITest .path(""); assertEquals("//host", uri.asString()); } + + @Test + public void testKeepParam() + { + HttpURI orig = HttpURI.from("http://localhost/context/info;param=value"); + HttpURI built = HttpURI.build(orig).path("/context/info").asImmutable(); + assertThat(built.getParam(), is(orig.getParam())); + assertThat(built.toString(), is(orig.toString())); + } } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 7099ec83dc1..e84dc1e1c46 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -705,6 +705,8 @@ public interface Request extends Attributes, Content.Source static HttpURI updateHttpURI(Request request, String newPathInContext) { - return HttpURI.build(request.getHttpURI()).path(URIUtil.addPaths(getContextPath(request), newPathInContext)).asImmutable(); + return HttpURI.build(request.getHttpURI()) + .path(URIUtil.addPaths(getContextPath(request), newPathInContext)) + .asImmutable(); } } diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java index 3142ee8a04e..3aa6313ac2a 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java @@ -34,6 +34,7 @@ import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; +import jakarta.servlet.DispatcherType; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; @@ -426,6 +427,7 @@ public class DefaultServlet extends HttpServlet private final HttpServletRequest _servletRequest; private final Request _request; + private final HttpURI _uri; private final HttpFields _httpFields; ServletCoreRequest(HttpServletRequest request) @@ -447,6 +449,10 @@ public class DefaultServlet extends HttpServlet } } _httpFields = fields.asImmutable(); + + _uri = (request.getDispatcherType() == DispatcherType.REQUEST) + ? _request.getHttpURI() + : Request.updateHttpURI(_request, URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo())); } @Override @@ -464,7 +470,7 @@ public class DefaultServlet extends HttpServlet @Override public HttpURI getHttpURI() { - return Request.updateHttpURI(_request, URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo())); + return _uri; } @Override diff --git a/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java b/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java index 4a2da29c273..762d4b1278b 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java @@ -358,7 +358,7 @@ public class DefaultServletTest FS.ensureDirExists(docRoot.resolve("three")); String resBasePath = docRoot.toAbsolutePath().toString(); - defholder.setInitParameter("resourceBase", resBasePath); + defholder.setInitParameter("baseResource", resBasePath); String req1 = """ GET /context/one/deep/ HTTP/1.1\r From b627814a7be33705c5130f501dc338a3cc02c3d6 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 24 Oct 2022 21:25:38 +1100 Subject: [PATCH 15/42] Implement ErrorPageErrorProcessor to resolve #8726 (#8736) --- .../jetty/server/handler/ErrorProcessor.java | 4 +- .../handler/ReHandlingErrorProcessor.java | 146 ++++++++++++++++++ .../jetty/server/ErrorProcessorTest.java | 111 +++++++++++++ 3 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorProcessor.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorProcessor.java index 9f880e08e7a..7ee3d2d36c9 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorProcessor.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorProcessor.java @@ -110,7 +110,7 @@ public class ErrorProcessor implements Request.Processor try { - generateAcceptableResponse(request, response, code, message, cause, callback); + generateResponse(request, response, code, message, cause, callback); } catch (Throwable x) { @@ -120,7 +120,7 @@ public class ErrorProcessor implements Request.Processor } } - protected void generateAcceptableResponse(Request request, Response response, int code, String message, Throwable cause, Callback callback) throws IOException + protected void generateResponse(Request request, Response response, int code, String message, Throwable cause, Callback callback) throws IOException { List acceptable = request.getHeaders().getQualityCSV(HttpHeader.ACCEPT, QuotedQualityCSV.MOST_SPECIFIC_MIME_ORDERING); if (acceptable.isEmpty()) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java new file mode 100644 index 00000000000..98b0ca0e348 --- /dev/null +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java @@ -0,0 +1,146 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.server.handler; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.util.Callback; +import org.eclipse.jetty.util.ExceptionUtil; +import org.eclipse.jetty.util.URIUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * An ErrorProcessor that can re-handle a request at an error page location. + */ +public abstract class ReHandlingErrorProcessor extends ErrorProcessor +{ + private static final Logger LOG = LoggerFactory.getLogger(ReHandlingErrorProcessor.class); + + private final Handler _handler; + + protected ReHandlingErrorProcessor(Handler handler) + { + _handler = handler; + } + + @Override + public InvocationType getInvocationType() + { + return _handler.getInvocationType(); + } + + @Override + protected void generateResponse(Request request, Response response, int code, String message, Throwable cause, Callback callback) throws IOException + { + if (request.getAttribute(ReHandlingErrorProcessor.class.getName()) == null) + { + String pathInContext = getReHandlePathInContext(request, code, cause); + + if (pathInContext != null) + { + request.setAttribute(ReHandlingErrorProcessor.class.getName(), pathInContext); + HttpURI uri = HttpURI.build(request.getHttpURI()).path(URIUtil.addPaths(request.getContext().getContextPath(), pathInContext)).asImmutable(); + Request.Wrapper wrapper = new ReHandleRequestWrapper(request, uri, uri.getCanonicalPath()); + + try + { + Request.Processor processor = _handler.handle(wrapper); + if (processor != null) + { + response.setStatus(200); + processor.process(wrapper, response, callback); + return; + } + } + catch (Exception e) + { + if (LOG.isDebugEnabled()) + LOG.debug("Unable to process error {}", wrapper, e); + if (cause != null && ExceptionUtil.areNotAssociated(cause, e)) + cause.addSuppressed(e); + response.setStatus(code); + } + } + } + super.generateResponse(request, response, code, message, cause, callback); + } + + protected abstract String getReHandlePathInContext(Request request, int code, Throwable cause); + + /** + * An ErrorPageErrorProcessor that uses a map of error codes to select a page. + */ + public static class ByHttpStatus extends ReHandlingErrorProcessor + { + private final Map _statusMap = new ConcurrentHashMap<>(); + + public ByHttpStatus(Handler handler) + { + super(handler); + } + + @Override + protected String getReHandlePathInContext(Request request, int code, Throwable cause) + { + return get(code); + } + + public String put(int code, String pathInContext) + { + return _statusMap.put(code, pathInContext); + } + + public String get(int code) + { + return _statusMap.get(code); + } + + public String remove(int code) + { + return _statusMap.remove(code); + } + } + + private static class ReHandleRequestWrapper extends Request.Wrapper + { + private final HttpURI _uri; + private final String _pathInContext; + + public ReHandleRequestWrapper(Request request, HttpURI uri, String pathInContext) + { + super(request); + _uri = uri; + _pathInContext = pathInContext; + } + + @Override + public HttpURI getHttpURI() + { + return _uri; + } + + @Override + public String getPathInContext() + { + return _pathInContext; + } + } +} diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java index ae530278deb..de0a09b65c9 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java @@ -25,11 +25,13 @@ import javax.xml.parsers.DocumentBuilderFactory; import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpTester; +import org.eclipse.jetty.io.Content; import org.eclipse.jetty.io.QuietException; import org.eclipse.jetty.logging.StacklessLogging; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.ErrorProcessor; +import org.eclipse.jetty.server.handler.ReHandlingErrorProcessor; import org.eclipse.jetty.server.internal.HttpChannelState; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; @@ -111,6 +113,17 @@ public class ErrorProcessorTest throw new TestException(message); } + // 200 response + if (request.getPathInContext().startsWith("/ok/")) + { + Content.Sink.write( + response, + true, + "%s Error %s : %s%n".formatted(request.getPathInContext(), request.getAttribute(ErrorProcessor.ERROR_STATUS), request.getAttribute(ErrorProcessor.ERROR_MESSAGE)), + callback); + return; + } + Response.writeError(request, response, callback, 404); } }); @@ -689,6 +702,104 @@ public class ErrorProcessorTest assertThat(response, containsString("Server Error")); } + @Test + public void testRootReHandlingErrorProcessor() throws Exception + { + ReHandlingErrorProcessor.ByHttpStatus errorProcessor = new ReHandlingErrorProcessor.ByHttpStatus(server); + errorProcessor.put(400, "/ok/badMessage"); + server.setErrorProcessor(errorProcessor); + + String rawResponse = connector.getResponse(""" + GET /no/host HTTP/1.1 + + """); + + HttpTester.Response response = HttpTester.parseResponse(rawResponse); + + assertThat(response.getStatus(), is(200)); + assertThat(response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0)); + assertThat(response.getContent(), containsString("/ok/badMessage Error 400 : No Host")); + } + + @Test + public void testRootReHandlingErrorProcessorLoop() throws Exception + { + ReHandlingErrorProcessor.ByHttpStatus errorProcessor = new ReHandlingErrorProcessor.ByHttpStatus(server); + errorProcessor.put(404, "/not/found"); + server.setErrorProcessor(errorProcessor); + + String rawResponse = connector.getResponse(""" + GET /not/found HTTP/1.1 + Host: localhost + + """); + + HttpTester.Response response = HttpTester.parseResponse(rawResponse); + + assertThat(response.getStatus(), is(404)); + assertThat(response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0)); + assertThat(response.getContent(), containsString("Error 404 Not Found")); + } + + @Test + public void testRootReHandlingErrorProcessorExceptionLoop() throws Exception + { + ReHandlingErrorProcessor.ByHttpStatus errorProcessor = new ReHandlingErrorProcessor.ByHttpStatus(server); + errorProcessor.put(444, "/badmessage/444"); + server.setErrorProcessor(errorProcessor); + + String rawResponse = connector.getResponse(""" + GET /badmessage/444 HTTP/1.1 + Host: localhost + + """); + + HttpTester.Response response = HttpTester.parseResponse(rawResponse); + + assertThat(response.getStatus(), is(444)); + assertThat(response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0)); + assertThat(response.getContent(), containsString("Error 444")); + } + + @Test + public void testContextReHandlingErrorProcessor() throws Exception + { + server.stop(); + + ContextHandler context = new ContextHandler("/ctx"); + context.setHandler(server.getHandler()); + + ContextHandlerCollection contexts = new ContextHandlerCollection(); + contexts.addHandler(context); + server.setHandler(contexts); + + server.setErrorProcessor(new ErrorProcessor() + { + @Override + public void process(Request request, Response response, Callback callback) + { + throw new UnsupportedOperationException(); + } + }); + + server.start(); + ReHandlingErrorProcessor.ByHttpStatus errorProcessor = new ReHandlingErrorProcessor.ByHttpStatus(context); + errorProcessor.put(444, "/ok/badMessage"); + context.setErrorProcessor(errorProcessor); + + String rawResponse = connector.getResponse(""" + GET /ctx/badmessage/444 HTTP/1.1 + Host: localhost + + """); + + HttpTester.Response response = HttpTester.parseResponse(rawResponse); + + assertThat(response.getStatus(), is(200)); + assertThat(response.getField(HttpHeader.CONTENT_LENGTH).getIntValue(), greaterThan(0)); + assertThat(response.getContent(), containsString("/ok/badMessage Error 444")); + } + static class TestException extends RuntimeException implements QuietException { public TestException(String message) From 3598d7eb453c8d40fb42ebbb36fcf5d96d239527 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 24 Oct 2022 23:34:35 +1100 Subject: [PATCH 16/42] replaced getPathInContext with static method --- .../src/main/java/org/eclipse/jetty/http/HttpURI.java | 9 +++++++++ .../test/java/org/eclipse/jetty/http/HttpURITest.java | 4 ++++ .../java/org/eclipse/jetty/server/ResourceService.java | 2 -- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index f45e72c9f86..9c8ec37a61a 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -875,7 +875,16 @@ public interface HttpURI { _param = param; if (_path != null && _param != null) + { + int lastSlash = _path.lastIndexOf('/'); + if (lastSlash >= 0) + { + int trailingParam = _path.indexOf(';', lastSlash + 1); + if (trailingParam >= 0) + _path = _path.substring(0, trailingParam); + } _path += ";" + _param; + } _uri = null; return this; diff --git a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java index 3cee87700f5..ac233edff79 100644 --- a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +++ b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java @@ -924,5 +924,9 @@ public class HttpURITest HttpURI built = HttpURI.build(orig).path("/context/info").asImmutable(); assertThat(built.getParam(), is(orig.getParam())); assertThat(built.toString(), is(orig.toString())); + + built = HttpURI.build(orig).path("/context/info").param("param=value").asImmutable(); + assertThat(built.getParam(), is(orig.getParam())); + assertThat(built.toString(), is(orig.toString())); } } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index 7558c1dc5e6..4a113fea61d 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -452,9 +452,7 @@ public class ResourceService if (!uri.getCanonicalPath().endsWith("/")) { // TODO need URI util that handles param and query without reconstructing entire URI with scheme and authority - String parameter = uri.getParam(); uri.path(uri.getCanonicalPath() + "/"); - uri.param(parameter); response.getHeaders().putLongField(HttpHeader.CONTENT_LENGTH, 0); // TODO: can writeRedirect (override) also work for WelcomeActionType.REDIRECT? sendRedirect(request, response, callback, uri.getPathQuery()); From 31e4a8234fdc3eae9f1bdfb145da38d2f6b6281c Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 24 Oct 2022 23:36:02 +1100 Subject: [PATCH 17/42] replaced getPathInContext with static method --- .../src/main/java/org/eclipse/jetty/server/ResourceService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index 4a113fea61d..b7c847cedb4 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -538,9 +538,7 @@ public class ResourceService response.getHeaders().putLongField(HttpHeader.CONTENT_LENGTH, 0); // TODO need URI util that handles param and query without reconstructing entire URI with scheme and authority HttpURI.Mutable uri = HttpURI.build(request.getHttpURI()); - String parameter = uri.getParam(); uri.path(URIUtil.addPaths(contextPath, welcomeTarget)); - uri.param(parameter); return new WelcomeAction(WelcomeActionType.REDIRECT, uri.getPathQuery()); } From 660093ff3a48a6f071f3cc0ecbe18426e28a003d Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 24 Oct 2022 16:21:02 +0200 Subject: [PATCH 18/42] Code cleanups. Removed obsolete oej.server.HttpTransport. Cleaned up ConnectionMetaData.Wrapper. Simplified ee10 DefaultServlet.ServletCoreRequest. Other minor cleanups. Signed-off-by: Simone Bordet --- .../jetty/server/ConnectionMetaData.java | 30 +++---- .../server/ForwardedRequestCustomizer.java | 2 +- .../eclipse/jetty/server/HttpTransport.java | 71 --------------- .../server/internal/HttpChannelState.java | 8 +- .../jetty/ee10/servlet/DefaultServlet.java | 86 +------------------ .../jetty/ee10/servlet/ServletChannel.java | 2 - .../eclipse/jetty/ee9/nested/HttpChannel.java | 9 +- .../jetty/ee9/nested/PushBuilderImpl.java | 8 +- 8 files changed, 27 insertions(+), 189 deletions(-) delete mode 100644 jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpTransport.java diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionMetaData.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionMetaData.java index 92218b2248c..c1bac051880 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionMetaData.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionMetaData.java @@ -78,83 +78,81 @@ public interface ConnectionMetaData extends Attributes class Wrapper extends Attributes.Wrapper implements ConnectionMetaData { - private final ConnectionMetaData _wrapped; - public Wrapper(ConnectionMetaData wrapped) { super(wrapped); - _wrapped = wrapped; } - protected ConnectionMetaData getWrappedConnectionMetaData() + @Override + public ConnectionMetaData getWrapped() { - return _wrapped; + return (ConnectionMetaData)super.getWrapped(); } @Override public String getId() { - return _wrapped.getId(); + return getWrapped().getId(); } @Override public HttpConfiguration getHttpConfiguration() { - return _wrapped.getHttpConfiguration(); + return getWrapped().getHttpConfiguration(); } @Override public HttpVersion getHttpVersion() { - return _wrapped.getHttpVersion(); + return getWrapped().getHttpVersion(); } @Override public String getProtocol() { - return _wrapped.getProtocol(); + return getWrapped().getProtocol(); } @Override public Connection getConnection() { - return _wrapped.getConnection(); + return getWrapped().getConnection(); } @Override public Connector getConnector() { - return _wrapped.getConnector(); + return getWrapped().getConnector(); } @Override public boolean isPersistent() { - return _wrapped.isPersistent(); + return getWrapped().isPersistent(); } @Override public boolean isSecure() { - return _wrapped.isSecure(); + return getWrapped().isSecure(); } @Override public SocketAddress getRemoteSocketAddress() { - return _wrapped.getRemoteSocketAddress(); + return getWrapped().getRemoteSocketAddress(); } @Override public SocketAddress getLocalSocketAddress() { - return _wrapped.getLocalSocketAddress(); + return getWrapped().getLocalSocketAddress(); } @Override public HostPort getServerAuthority() { - return _wrapped.getServerAuthority(); + return getWrapped().getServerAuthority(); } } } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java index c440217c736..44a7f3c3413 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java @@ -597,7 +597,7 @@ public class ForwardedRequestCustomizer implements HttpConfiguration.Customizer getId(), remote, authority, - getWrappedConnectionMetaData() + getWrapped() ); } }; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpTransport.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpTransport.java deleted file mode 100644 index efafc4a108f..00000000000 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpTransport.java +++ /dev/null @@ -1,71 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License v. 2.0 which is available at -// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// ======================================================================== -// - -package org.eclipse.jetty.server; - -import java.nio.ByteBuffer; - -import org.eclipse.jetty.http.MetaData; -import org.eclipse.jetty.util.Callback; - -/** - * Abstraction of the outbound HTTP transport. - */ -public interface HttpTransport -{ - String UPGRADE_CONNECTION_ATTRIBUTE = HttpTransport.class.getName() + ".UPGRADE"; - - /** - * Asynchronous call to send a response (or part) over the transport - * - * @param request True if the response if for a HEAD request (and the data should not be sent). - * @param response The header info to send, or null if just sending more data. - * The first call to send for a response must have a non null info. - * @param content A buffer of content to be sent. - * @param lastContent True if the content is the last content for the current response. - * @param callback The Callback instance that success or failure of the send is notified on - */ - void send(MetaData.Request request, MetaData.Response response, ByteBuffer content, boolean lastContent, Callback callback); - - /** - * @return true if responses can be pushed over this transport - */ - boolean isPushSupported(); - - /** - * @param request A request to use as the basis for generating a pushed response. - */ - void push(MetaData.Request request); - - /** - * Called to indicated the end of the current request/response cycle (which may be - * some time after the last content is sent). - */ - void onCompleted(); - - /** - * Aborts this transport. - *

- * This method should terminate the transport in a way that - * can indicate an abnormal response to the client, for example - * by abruptly close the connection. - *

- * This method is called when an error response needs to be sent, - * but the response is already committed, or when a write failure - * is detected. If abort is called, {@link #onCompleted()} is not - * called - * - * @param failure the failure that caused the abort. - */ - void abort(Throwable failure); -} diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpChannelState.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpChannelState.java index 568dcb64658..5b6cfd4c1a8 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpChannelState.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpChannelState.java @@ -796,7 +796,7 @@ public class HttpChannelState implements HttpChannel, Components return _loggedRequest == null ? this : _loggedRequest; } - HttpStream getStream() + HttpStream getHttpStream() { return getHttpChannel()._stream; } @@ -1013,7 +1013,7 @@ public class HttpChannelState implements HttpChannel, Components @Override public void push(MetaData.Request request) { - getStream().push(request); + getHttpStream().push(request); } @Override @@ -1047,7 +1047,7 @@ public class HttpChannelState implements HttpChannel, Components @Override public TunnelSupport getTunnelSupport() { - return getStream().getTunnelSupport(); + return getHttpStream().getTunnelSupport(); } @Override @@ -1468,7 +1468,7 @@ public class HttpChannelState implements HttpChannel, Components public InvocationType getInvocationType() { // TODO review this as it is probably not correct - return _request.getStream().getInvocationType(); + return _request.getHttpStream().getInvocationType(); } } diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java index 25f069278be..fff08e16b09 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java @@ -52,20 +52,13 @@ import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpStatus; -import org.eclipse.jetty.http.HttpURI; -import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.io.ByteBufferInputStream; -import org.eclipse.jetty.io.Content; -import org.eclipse.jetty.server.Components; -import org.eclipse.jetty.server.ConnectionMetaData; -import org.eclipse.jetty.server.Context; import org.eclipse.jetty.server.HttpStream; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.ResourceContentFactory; import org.eclipse.jetty.server.ResourceService; import org.eclipse.jetty.server.Response; -import org.eclipse.jetty.server.TunnelSupport; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.Blocker; import org.eclipse.jetty.util.BufferUtil; @@ -372,7 +365,7 @@ public class DefaultServlet extends HttpServlet if (coreResponse.isCommitted()) { if (LOG.isDebugEnabled()) - LOG.debug("Response already committed for {}", coreRequest._request.getHttpURI()); + LOG.debug("Response already committed for {}", coreRequest.getHttpURI()); return; } @@ -419,19 +412,18 @@ public class DefaultServlet extends HttpServlet doGet(req, resp); } - private static class ServletCoreRequest implements Request + private static class ServletCoreRequest extends Request.Wrapper { // TODO fully implement this class and move it to the top level // TODO Some methods are directed to core that probably should be intercepted private final HttpServletRequest _servletRequest; - private final Request _request; private final HttpFields _httpFields; ServletCoreRequest(HttpServletRequest request) { + super(ServletContextRequest.getServletContextRequest(request)); _servletRequest = request; - _request = ServletContextRequest.getServletContextRequest(request); HttpFields.Mutable fields = HttpFields.build(); @@ -455,108 +447,36 @@ public class DefaultServlet extends HttpServlet return _httpFields; } - @Override - public HttpFields getTrailers() - { - return _request.getTrailers(); - } - - @Override - public HttpURI getHttpURI() - { - return _request.getHttpURI(); - } - @Override public String getPathInContext() { return URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo()); } - @Override - public void demand(Runnable demandCallback) - { - _request.demand(demandCallback); - } - - @Override - public void fail(Throwable failure) - { - _request.fail(failure); - } - @Override public String getId() { return _servletRequest.getRequestId(); } - @Override - public Components getComponents() - { - return _request.getComponents(); - } - - @Override - public ConnectionMetaData getConnectionMetaData() - { - return _request.getConnectionMetaData(); - } - @Override public String getMethod() { return _servletRequest.getMethod(); } - @Override - public Context getContext() - { - return _request.getContext(); - } - - @Override - public long getTimeStamp() - { - return _request.getTimeStamp(); - } - @Override public boolean isSecure() { return _servletRequest.isSecure(); } - @Override - public Content.Chunk read() - { - return _request.read(); - } - - @Override - public boolean isPushSupported() - { - return _request.isPushSupported(); - } - - @Override - public void push(MetaData.Request request) - { - this._request.push(request); - } - @Override public boolean addErrorListener(Predicate onError) { return false; } - @Override - public TunnelSupport getTunnelSupport() - { - return _request.getTunnelSupport(); - } - @Override public void addHttpStreamWrapper(Function wrapper) { diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletChannel.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletChannel.java index c34fed3b173..eaa344a6e16 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletChannel.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletChannel.java @@ -838,8 +838,6 @@ public class ServletChannel implements Runnable /** * If a write or similar operation to this channel fails, * then this method should be called. - *

- * The standard implementation calls {@code HttpTransport#abort(Throwable)}. * * @param failure the failure that caused the abort. */ diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/HttpChannel.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/HttpChannel.java index e5133395990..d07d7b24019 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/HttpChannel.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/HttpChannel.java @@ -65,13 +65,8 @@ import org.slf4j.LoggerFactory; import static org.eclipse.jetty.util.thread.Invocable.InvocationType.NON_BLOCKING; /** - * HttpChannel represents a single endpoint for HTTP semantic processing. - * The HttpChannel is both an HttpParser.RequestHandler, where it passively receives events from - * an incoming HTTP request, and a Runnable, where it actively takes control of the request/response - * life cycle and calls the application (perhaps suspending and resuming with multiple calls to run). - * The HttpChannel signals the switch from passive mode to active mode by returning true to one of the - * HttpParser.RequestHandler callbacks. The completion of the active phase is signalled by a call to - * HttpTransport.completed(). + *

The state machine that processes a request/response + * cycle interpreting the HTTP and Servlet semantic.

*/ public class HttpChannel implements Runnable, HttpOutput.Interceptor { diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/PushBuilderImpl.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/PushBuilderImpl.java index 747d65c275c..37344a1c9d6 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/PushBuilderImpl.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/PushBuilderImpl.java @@ -35,15 +35,15 @@ import org.slf4j.LoggerFactory; public class PushBuilderImpl implements PushBuilder { private static final Logger LOG = LoggerFactory.getLogger(PushBuilderImpl.class); - private static final HttpField JETTY_PUSH = new HttpField("x-http2-push", "PushBuilder"); - private static EnumSet UNSAFE_METHODS = EnumSet.of( + private static final EnumSet UNSAFE_METHODS = EnumSet.of( HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.CONNECT, HttpMethod.OPTIONS, - HttpMethod.TRACE); + HttpMethod.TRACE + ); private final Request _request; private final HttpFields.Mutable _fields; @@ -51,7 +51,6 @@ public class PushBuilderImpl implements PushBuilder private String _queryString; private String _sessionId; private String _path; - private String _lastModified; public PushBuilderImpl(Request request, HttpFields fields, String method, String queryString, String sessionId) { @@ -190,6 +189,5 @@ public class PushBuilderImpl implements PushBuilder _request.getHttpChannel().getCoreRequest().push(push); _path = null; - _lastModified = null; } } From d50510a1fe1c0e6e4d6a73e8b0ab355869604054 Mon Sep 17 00:00:00 2001 From: Gili Tzabari Date: Tue, 18 Oct 2022 16:38:03 -0400 Subject: [PATCH 19/42] Fixes #8723: Provide a thread-safe way to modify HttpClient proxies at runtime. --- .../jetty/client/ProxyConfiguration.java | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java b/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java index c826ced88f2..78a44123196 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java @@ -14,11 +14,11 @@ package org.eclipse.jetty.client; import java.net.URI; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.io.ClientConnectionFactory; import org.eclipse.jetty.util.HostPort; @@ -37,16 +37,45 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; */ public class ProxyConfiguration { - private final List proxies = new ArrayList<>(); + private final List proxies = new CopyOnWriteArrayList<>(); + /** + * @deprecated use {@link #addProxy(Proxy)} and {@link #removeProxy(Proxy)} instead + * @return the forward proxies to use + */ + @Deprecated(since = "10", forRemoval = true) public List getProxies() { return proxies; } + /** + * Adds a proxy. + * + * @param proxy a proxy + * @throws NullPointerException if {@code proxy} is null + */ + public void addProxy(Proxy proxy) + { + if (proxy == null) + throw new NullPointerException("proxy may not be null"); + proxies.add(proxy); + } + + /** + * Removes a proxy. + * + * @param proxy a proxy + * @return true if a match is found + */ + public boolean removeProxy(Proxy proxy) + { + return proxies.remove(proxy); + } + public Proxy match(Origin origin) { - for (Proxy proxy : getProxies()) + for (Proxy proxy : proxies) { if (proxy.matches(origin)) return proxy; From 48b89bdc2aff4ef159dc0ddc038980893ab39590 Mon Sep 17 00:00:00 2001 From: Gili Tzabari Date: Tue, 18 Oct 2022 17:38:21 -0400 Subject: [PATCH 20/42] Fixing checkstyle errors. --- .../main/java/org/eclipse/jetty/client/ProxyConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java b/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java index 78a44123196..127cd69cbb9 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java @@ -17,8 +17,8 @@ import java.net.URI; import java.util.HashSet; import java.util.List; import java.util.Set; - import java.util.concurrent.CopyOnWriteArrayList; + import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.io.ClientConnectionFactory; import org.eclipse.jetty.util.HostPort; From e2e59478ceb63799013600e3e0461ae83865e2cf Mon Sep 17 00:00:00 2001 From: Gili Tzabari Date: Mon, 24 Oct 2022 13:17:25 -0400 Subject: [PATCH 21/42] Update in response to PR comments. --- .../eclipse/jetty/demos/ProxyServerTest.java | 2 +- .../client/http/HTTPClientDocs.java | 4 +-- .../client/websocket/WebSocketClientDocs.java | 2 +- .../jetty/client/ProxyConfiguration.java | 10 +++--- .../client/HttpClientCustomProxyTest.java | 2 +- .../client/HttpClientProxyProtocolTest.java | 2 +- .../jetty/client/HttpClientProxyTest.java | 10 +++--- .../eclipse/jetty/client/Socks4ProxyTest.java | 12 +++---- .../HttpClientTransportOverHTTP2Test.java | 2 +- .../proxy/AsyncMiddleManServletTest.java | 2 +- .../jetty/proxy/ForwardProxyServerTest.java | 6 ++-- .../proxy/ForwardProxyTLSServerTest.java | 32 +++++++++---------- .../jetty/proxy/ProxyServletFailureTest.java | 2 +- .../jetty/proxy/ProxyServletLoadTest.java | 2 +- .../eclipse/jetty/proxy/ProxyServletTest.java | 5 ++- .../unixdomain/server/UnixDomainTest.java | 2 +- .../HttpClientTransportDynamicTest.java | 2 +- .../client/ProxyWithDynamicTransportTest.java | 8 ++--- 18 files changed, 55 insertions(+), 52 deletions(-) diff --git a/demos/embedded/src/test/java/org/eclipse/jetty/demos/ProxyServerTest.java b/demos/embedded/src/test/java/org/eclipse/jetty/demos/ProxyServerTest.java index 1ea27c25a8e..4598ab768b6 100644 --- a/demos/embedded/src/test/java/org/eclipse/jetty/demos/ProxyServerTest.java +++ b/demos/embedded/src/test/java/org/eclipse/jetty/demos/ProxyServerTest.java @@ -40,7 +40,7 @@ public class ProxyServerTest extends AbstractEmbeddedTest server.start(); URI uri = server.getURI(); - client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", uri.getPort())); + client.getProxyConfiguration().addProxy(new HttpProxy("localhost", uri.getPort())); } @AfterEach diff --git a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/http/HTTPClientDocs.java b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/http/HTTPClientDocs.java index 91ddace1291..4b71a9b6978 100644 --- a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/http/HTTPClientDocs.java +++ b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/http/HTTPClientDocs.java @@ -659,7 +659,7 @@ public class HTTPClientDocs // Add the new proxy to the list of proxies already registered. ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration(); - proxyConfig.getProxies().add(proxy); + proxyConfig.addProxy(proxy); ContentResponse response = httpClient.GET("http://domain.com/path"); // end::proxy[] @@ -684,7 +684,7 @@ public class HTTPClientDocs // Proxy configuration. ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration(); HttpProxy proxy = new HttpProxy("proxy.net", 8080); - proxyConfig.getProxies().add(proxy); + proxyConfig.addProxy(proxy); ContentResponse response = httpClient.newRequest(serverURI).send(); // end::proxyAuthentication[] diff --git a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/websocket/WebSocketClientDocs.java b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/websocket/WebSocketClientDocs.java index dce2373692b..85835c4461f 100644 --- a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/websocket/WebSocketClientDocs.java +++ b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/websocket/WebSocketClientDocs.java @@ -54,7 +54,7 @@ public class WebSocketClientDocs // Instantiate and configure HttpClient. HttpClient httpClient = new HttpClient(); // For example, configure a proxy. - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", 8888)); + httpClient.getProxyConfiguration().addProxy(new HttpProxy("localhost", 8888)); // Instantiate WebSocketClient, passing HttpClient to the constructor. WebSocketClient webSocketClient = new WebSocketClient(httpClient); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java b/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java index 127cd69cbb9..cbedf4cef15 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java @@ -16,11 +16,13 @@ package org.eclipse.jetty.client; import java.net.URI; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.io.ClientConnectionFactory; +import org.eclipse.jetty.util.BlockingArrayQueue; import org.eclipse.jetty.util.HostPort; import org.eclipse.jetty.util.ssl.SslContextFactory; @@ -30,14 +32,14 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; * Applications add subclasses of {@link Proxy} to this configuration via: *
  * ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration();
- * proxyConfig.getProxies().add(new HttpProxy(proxyHost, 8080));
+ * proxyConfig.addProxy(new HttpProxy(proxyHost, 8080));
  * 
* * @see HttpClient#getProxyConfiguration() */ public class ProxyConfiguration { - private final List proxies = new CopyOnWriteArrayList<>(); + private final List proxies = new BlockingArrayQueue<>(); /** * @deprecated use {@link #addProxy(Proxy)} and {@link #removeProxy(Proxy)} instead @@ -57,9 +59,7 @@ public class ProxyConfiguration */ public void addProxy(Proxy proxy) { - if (proxy == null) - throw new NullPointerException("proxy may not be null"); - proxies.add(proxy); + proxies.add(Objects.requireNonNull(proxy)); } /** diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientCustomProxyTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientCustomProxyTest.java index 6cb964dcd83..6e0e36a99af 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientCustomProxyTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientCustomProxyTest.java @@ -98,7 +98,7 @@ public class HttpClientCustomProxyTest // Setup the custom proxy int proxyPort = connector.getLocalPort(); int serverPort = proxyPort + 1; // Any port will do for these tests - just not the same as the proxy - client.getProxyConfiguration().getProxies().add(new CAFEBABEProxy(new Origin.Address("localhost", proxyPort), false)); + client.getProxyConfiguration().addProxy(new CAFEBABEProxy(new Origin.Address("localhost", proxyPort), false)); ContentResponse response = client.newRequest(serverHost, serverPort) .timeout(5, TimeUnit.SECONDS) diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java index 9c882e73948..1ecf680d806 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java @@ -231,7 +231,7 @@ public class HttpClientProxyProtocolTest int proxyPort = connector.getLocalPort(); int serverPort = proxyPort + 1; // Any port will do. - client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyPort)); // We are simulating to be a HttpClient inside a proxy. // The server is configured with the PROXY protocol to know the socket address of clients. diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java index 3c158d6888c..c7b00eeba15 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java @@ -60,7 +60,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest int proxyPort = connector.getLocalPort(); int serverPort = proxyPort + 1; // Any port will do for these tests - just not the same as the proxy - client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyPort)); ContentResponse response = client.newRequest(serverHost, serverPort) .scheme(scenario.getScheme()) @@ -108,7 +108,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest String proxyHost = "localhost"; int proxyPort = connector.getLocalPort(); int serverPort = proxyPort + 1; // Any port will do for these tests - just not the same as the proxy - client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); ContentResponse response1 = client.newRequest(serverHost, serverPort) .scheme(scenario.getScheme()) @@ -202,7 +202,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest }); int proxyPort = connector.getLocalPort(); - client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); ContentResponse response1 = client.newRequest(serverHost, serverPort) .scheme(scenario.getScheme()) @@ -290,7 +290,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest client.getAuthenticationStore().addAuthentication(new BasicAuthentication(proxyURI, proxyRealm, "proxyUser", "proxyPassword")); URI serverURI = URI.create(scenario.getScheme() + "://" + serverHost + ":" + serverPort); client.getAuthenticationStore().addAuthentication(new BasicAuthentication(serverURI, serverRealm, "serverUser", "serverPassword")); - client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); final AtomicInteger requests = new AtomicInteger(); client.getRequestListeners().add(new Request.Listener.Adapter() { @@ -361,7 +361,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest int serverPort = proxyPort + 1; URI proxyURI = URI.create(scenario.getScheme() + "://" + proxyHost + ":" + proxyPort); client.getAuthenticationStore().addAuthentication(new BasicAuthentication(proxyURI, proxyRealm, "proxyUser", "proxyPassword")); - client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); final AtomicInteger requests = new AtomicInteger(); client.getRequestListeners().add(new Request.Listener.Adapter() { diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java index 97770100b26..898836eb115 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java @@ -77,7 +77,7 @@ public class Socks4ProxyTest public void testSocks4Proxy() throws Exception { int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy("localhost", proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy("localhost", proxyPort)); CountDownLatch latch = new CountDownLatch(1); @@ -139,7 +139,7 @@ public class Socks4ProxyTest public void testSocks4ProxyWithSplitResponse() throws Exception { int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy("localhost", proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy("localhost", proxyPort)); CountDownLatch latch = new CountDownLatch(1); @@ -215,7 +215,7 @@ public class Socks4ProxyTest // The hostname must be that of the server, not of the proxy. ssl.setHostnameVerifier((hostname, session) -> serverHost.equals(hostname)); }); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); CountDownLatch latch = new CountDownLatch(1); client.newRequest(serverHost, serverPort) @@ -283,7 +283,7 @@ public class Socks4ProxyTest { String proxyHost = "localhost"; int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); long timeout = 1000; Request request = client.newRequest("localhost", proxyPort + 1) @@ -305,7 +305,7 @@ public class Socks4ProxyTest { String proxyHost = "localhost"; int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); long idleTimeout = 1000; client.setIdleTimeout(idleTimeout); @@ -327,7 +327,7 @@ public class Socks4ProxyTest { String proxyHost = "localhost"; int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); Request request = client.newRequest("localhost", proxyPort + 1); FutureResponseListener listener = new FutureResponseListener(request); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java index e8b6d01c9fe..dea91ece9fb 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java @@ -345,7 +345,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest }); int proxyPort = connector.getLocalPort(); - client.getProxyConfiguration().getProxies().add(new HttpProxy(new Origin.Address("localhost", proxyPort), false, new Origin.Protocol(List.of("h2c"), false))); + client.getProxyConfiguration().addProxy(new HttpProxy(new Origin.Address("localhost", proxyPort), false, new Origin.Protocol(List.of("h2c"), false))); int serverPort = proxyPort + 1; // Any port will do, just not the same as the proxy. ContentResponse response = client.newRequest("localhost", serverPort) diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/AsyncMiddleManServletTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/AsyncMiddleManServletTest.java index 554f7a12aba..5e7b212ed34 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/AsyncMiddleManServletTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/AsyncMiddleManServletTest.java @@ -152,7 +152,7 @@ public class AsyncMiddleManServletTest clientPool.setName("client"); client = new HttpClient(); client.setExecutor(clientPool); - client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + client.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort())); client.start(); } diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyServerTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyServerTest.java index 5cc07742f98..c3ec357d463 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyServerTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyServerTest.java @@ -204,7 +204,7 @@ public class ForwardProxyServerTest ClientConnector clientConnector = new ClientConnector(); clientConnector.setSslContextFactory(clientTLS); HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -253,7 +253,7 @@ public class ForwardProxyServerTest }); HttpClient httpClient = new HttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort()) @@ -292,7 +292,7 @@ public class ForwardProxyServerTest }); HttpClient httpClient = new HttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort()) diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyTLSServerTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyTLSServerTest.java index 9c190a99db0..0b25a646fef 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyTLSServerTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyTLSServerTest.java @@ -197,7 +197,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -232,7 +232,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -279,7 +279,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -364,7 +364,7 @@ public class ForwardProxyTLSServerTest }); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); // Short idle timeout for HttpClient. httpClient.setIdleTimeout(idleTimeout); httpClient.start(); @@ -402,7 +402,7 @@ public class ForwardProxyTLSServerTest stopProxy(); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(new Origin.Address("localhost", proxyPort), proxySslContextFactory != null)); + httpClient.getProxyConfiguration().addProxy(new HttpProxy(new Origin.Address("localhost", proxyPort), proxySslContextFactory != null)); httpClient.start(); ExecutionException x = assertThrows(ExecutionException.class, () -> @@ -430,7 +430,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); assertThrows(ExecutionException.class, () -> @@ -462,7 +462,7 @@ public class ForwardProxyTLSServerTest }); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); assertThrows(ExecutionException.class, () -> @@ -485,7 +485,7 @@ public class ForwardProxyTLSServerTest HttpClient httpClient = newHttpClient(); HttpProxy httpProxy = new HttpProxy(new Origin.Address("[::1]", proxyConnector.getLocalPort()), proxyTLS != null); - httpClient.getProxyConfiguration().getProxies().add(httpProxy); + httpClient.getProxyConfiguration().addProxy(httpProxy); httpClient.start(); try @@ -614,7 +614,7 @@ public class ForwardProxyTLSServerTest HttpProxy httpProxy = newHttpProxy(); if (includeAddress) httpProxy.getIncludedAddresses().add("localhost:" + serverConnector.getLocalPort()); - httpClient.getProxyConfiguration().getProxies().add(httpProxy); + httpClient.getProxyConfiguration().addProxy(httpProxy); URI uri = URI.create((proxySslContextFactory == null ? "http" : "https") + "://localhost:" + proxyConnector.getLocalPort()); httpClient.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "proxyUser", "proxyPassword")); httpClient.start(); @@ -696,7 +696,7 @@ public class ForwardProxyTLSServerTest clientConnector.setSelectors(1); clientConnector.setSslContextFactory(clientSslContextFactory); HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -767,7 +767,7 @@ public class ForwardProxyTLSServerTest proxyClientTLS.setEndpointIdentificationAlgorithm(null); proxyClientTLS.start(); HttpProxy httpProxy = new HttpProxy(new Origin.Address("localhost", proxyConnector.getLocalPort()), proxyClientTLS); - httpClient.getProxyConfiguration().getProxies().add(httpProxy); + httpClient.getProxyConfiguration().addProxy(httpProxy); httpClient.start(); try @@ -798,7 +798,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -847,7 +847,7 @@ public class ForwardProxyTLSServerTest }); startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.setConnectTimeout(timeout); httpClient.setIdleTimeout(4 * timeout); httpClient.start(); @@ -883,7 +883,7 @@ public class ForwardProxyTLSServerTest }); startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.setConnectTimeout(timeout); // Short idle timeout for HttpClient. httpClient.setIdleTimeout(timeout); @@ -929,7 +929,7 @@ public class ForwardProxyTLSServerTest } }); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.setConnectTimeout(timeout); httpClient.setIdleTimeout(10 * timeout); httpClient.start(); @@ -978,7 +978,7 @@ public class ForwardProxyTLSServerTest } HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + httpClient.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); httpClient.start(); try diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletFailureTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletFailureTest.java index b891224b89b..ae4ef350c38 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletFailureTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletFailureTest.java @@ -117,7 +117,7 @@ public class ProxyServletFailureTest QueuedThreadPool executor = new QueuedThreadPool(); executor.setName("client"); result.setExecutor(executor); - result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + result.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort())); result.start(); return result; } diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletLoadTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletLoadTest.java index 5fcc4e67766..5cad85f9f25 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletLoadTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletLoadTest.java @@ -109,7 +109,7 @@ public class ProxyServletLoadTest clientPool.setName("client"); HttpClient result = new HttpClient(); result.setExecutor(clientPool); - result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + result.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort())); result.start(); client = result; } diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java index 7f804366de0..964830f2621 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java @@ -62,6 +62,7 @@ import org.eclipse.jetty.client.ConnectionPool; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpDestination; import org.eclipse.jetty.client.HttpProxy; +import org.eclipse.jetty.client.ProxyConfiguration.Proxy; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; @@ -122,6 +123,7 @@ public class ProxyServletTest } private HttpClient client; + private Proxy clientProxy; private Server proxy; private ServerConnector proxyConnector; private ServletContextHandler proxyContext; @@ -196,6 +198,7 @@ public class ProxyServletTest private void startClient(Consumer consumer) throws Exception { + clientProxy = new HttpProxy("localhost", proxyConnector.getLocalPort()); client = prepareClient(consumer); } @@ -205,7 +208,7 @@ public class ProxyServletTest clientPool.setName("client"); HttpClient result = new HttpClient(); result.setExecutor(clientPool); - result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + result.getProxyConfiguration().addProxy(clientProxy); if (consumer != null) consumer.accept(result); result.start(); diff --git a/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java b/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java index d5f7417a071..a86dfc7215b 100644 --- a/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java +++ b/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java @@ -175,7 +175,7 @@ public class UnixDomainTest ClientConnector clientConnector = ClientConnector.forUnixDomain(unixDomainPath); HttpClient httpClient = new HttpClient(new HttpClientTransportDynamic(clientConnector)); - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", fakeProxyPort)); + httpClient.getProxyConfiguration().addProxy(new HttpProxy("localhost", fakeProxyPort)); httpClient.start(); try { diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientTransportDynamicTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientTransportDynamicTest.java index d349c23df5c..5844e0ee07b 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientTransportDynamicTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientTransportDynamicTest.java @@ -586,7 +586,7 @@ public class HttpClientTransportDynamicTest int proxyPort = connector.getLocalPort(); // The proxy speaks both http/1.1 and h2c. Origin.Protocol proxyProtocol = new Origin.Protocol(List.of("http/1.1", "h2c"), false); - client.getProxyConfiguration().getProxies().add(new HttpProxy(new Origin.Address("localhost", proxyPort), false, proxyProtocol)); + client.getProxyConfiguration().addProxy(new HttpProxy(new Origin.Address("localhost", proxyPort), false, proxyProtocol)); // Make an upgrade request from HTTP/1.1 to H2C. int serverPort = proxyPort + 1; // Any port will do. diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java index 9852927687b..72283fd20b8 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java @@ -260,7 +260,7 @@ public class ProxyWithDynamicTransportTest int proxyPort = proxySecure ? proxyTLSConnector.getLocalPort() : proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy proxy = new HttpProxy(proxyAddress, proxySecure, proxyProtocol); - client.getProxyConfiguration().getProxies().add(proxy); + client.getProxyConfiguration().addProxy(proxy); String scheme = serverSecure ? "https" : "http"; int serverPort = serverSecure ? serverTLSConnector.getLocalPort() : serverConnector.getLocalPort(); @@ -296,7 +296,7 @@ public class ProxyWithDynamicTransportTest int proxyPort = proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy proxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false)); - client.getProxyConfiguration().getProxies().add(proxy); + client.getProxyConfiguration().addProxy(proxy); long idleTimeout = 1000; http2Client.setStreamIdleTimeout(idleTimeout); @@ -337,7 +337,7 @@ public class ProxyWithDynamicTransportTest int proxyPort = proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy httpProxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false)); - client.getProxyConfiguration().getProxies().add(httpProxy); + client.getProxyConfiguration().addProxy(httpProxy); proxy.stop(); CountDownLatch latch = new CountDownLatch(1); @@ -372,7 +372,7 @@ public class ProxyWithDynamicTransportTest int proxyPort = proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy httpProxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false)); - client.getProxyConfiguration().getProxies().add(httpProxy); + client.getProxyConfiguration().addProxy(httpProxy); CountDownLatch latch = new CountDownLatch(1); client.newRequest("localhost", serverConnector.getLocalPort()) From 5973ce29413983e8244a10d2105d17475ee95bae Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Tue, 25 Oct 2022 09:52:55 +0200 Subject: [PATCH 22/42] Small additional fixes. * Removed "since" attribute (it's commonly related to Java versions) to avoid confusion. * Avoid using getProxies() to modify the Proxy object in ProxyServletTest. Signed-off-by: Simone Bordet --- .../main/java/org/eclipse/jetty/client/ProxyConfiguration.java | 3 +-- .../test/java/org/eclipse/jetty/proxy/ProxyServletTest.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java b/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java index cbedf4cef15..e3922c4fd43 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java @@ -18,7 +18,6 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.io.ClientConnectionFactory; @@ -45,7 +44,7 @@ public class ProxyConfiguration * @deprecated use {@link #addProxy(Proxy)} and {@link #removeProxy(Proxy)} instead * @return the forward proxies to use */ - @Deprecated(since = "10", forRemoval = true) + @Deprecated(forRemoval = true) public List getProxies() { return proxies; diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java index 964830f2621..1a021a8985c 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java @@ -731,7 +731,7 @@ public class ProxyServletTest startProxy(proxyServletClass); startClient(); int port = serverConnector.getLocalPort(); - client.getProxyConfiguration().getProxies().get(0).getExcludedAddresses().add("127.0.0.1:" + port); + clientProxy.getExcludedAddresses().add("127.0.0.1:" + port); // Try with a proxied host ContentResponse response = client.newRequest("localhost", port) From 0724d1090d780434bbc22318b7ecd8242894645a Mon Sep 17 00:00:00 2001 From: Gili Tzabari Date: Tue, 18 Oct 2022 16:42:01 -0400 Subject: [PATCH 23/42] Fixes #8723: Provide a thread-safe way to modify HttpClient proxies at runtime. --- .../client/http/HTTPClientDocs.java | 4 +-- .../client/websocket/WebSocketClientDocs.java | 2 +- .../jetty/client/ProxyConfiguration.java | 30 +++++++++++++---- .../client/HttpClientCustomProxyTest.java | 2 +- .../client/HttpClientProxyProtocolTest.java | 2 +- .../jetty/client/HttpClientProxyTest.java | 10 +++--- .../eclipse/jetty/client/Socks4ProxyTest.java | 12 +++---- .../HttpClientTransportOverHTTP2Test.java | 2 +- .../org/eclipse/jetty/proxy/ProxyHandler.java | 2 +- .../ForwardProxyWithDynamicTransportTest.java | 8 ++--- .../ForwardProxyWithDynamicTransportTest.java | 8 ++--- .../HttpClientTransportDynamicTest.java | 2 +- .../unixdomain/server/UnixDomainTest.java | 2 +- .../jetty/ee10/demos/ProxyServerTest.java | 2 +- .../ee10/proxy/AsyncMiddleManServletTest.java | 2 +- .../ee10/proxy/ForwardProxyServerTest.java | 6 ++-- .../ee10/proxy/ForwardProxyTLSServerTest.java | 32 +++++++++---------- .../ee10/proxy/ProxyServletFailureTest.java | 2 +- .../ee10/proxy/ProxyServletLoadTest.java | 2 +- .../jetty/ee10/proxy/ProxyServletTest.java | 7 ++-- .../jetty/ee9/demos/ProxyServerTest.java | 2 +- .../ee9/proxy/AsyncMiddleManServletTest.java | 2 +- .../ee9/proxy/ForwardProxyServerTest.java | 6 ++-- .../ee9/proxy/ForwardProxyTLSServerTest.java | 26 +++++++-------- .../ee9/proxy/ProxyServletFailureTest.java | 2 +- .../jetty/ee9/proxy/ProxyServletLoadTest.java | 2 +- .../jetty/ee9/proxy/ProxyServletTest.java | 9 ++++-- 27 files changed, 107 insertions(+), 81 deletions(-) diff --git a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/http/HTTPClientDocs.java b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/http/HTTPClientDocs.java index 24ab4cc57a9..c5264d962c7 100644 --- a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/http/HTTPClientDocs.java +++ b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/http/HTTPClientDocs.java @@ -659,7 +659,7 @@ public class HTTPClientDocs // Add the new proxy to the list of proxies already registered. ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration(); - proxyConfig.getProxies().add(proxy); + proxyConfig.addProxy(proxy); ContentResponse response = httpClient.GET("http://domain.com/path"); // end::proxy[] @@ -684,7 +684,7 @@ public class HTTPClientDocs // Proxy configuration. ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration(); HttpProxy proxy = new HttpProxy("proxy.net", 8080); - proxyConfig.getProxies().add(proxy); + proxyConfig.addProxy(proxy); ContentResponse response = httpClient.newRequest(serverURI).send(); // end::proxyAuthentication[] diff --git a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/websocket/WebSocketClientDocs.java b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/websocket/WebSocketClientDocs.java index e1078a0fb4c..8bb09a96c00 100644 --- a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/websocket/WebSocketClientDocs.java +++ b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/client/websocket/WebSocketClientDocs.java @@ -54,7 +54,7 @@ public class WebSocketClientDocs // Instantiate and configure HttpClient. HttpClient httpClient = new HttpClient(); // For example, configure a proxy. - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", 8888)); + httpClient.getProxyConfiguration().addProxy(new HttpProxy("localhost", 8888)); // Instantiate WebSocketClient, passing HttpClient to the constructor. WebSocketClient webSocketClient = new WebSocketClient(httpClient); diff --git a/jetty-core/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java b/jetty-core/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java index c826ced88f2..ef68b543655 100644 --- a/jetty-core/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java +++ b/jetty-core/jetty-client/src/main/java/org/eclipse/jetty/client/ProxyConfiguration.java @@ -14,13 +14,14 @@ package org.eclipse.jetty.client; import java.net.URI; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.io.ClientConnectionFactory; +import org.eclipse.jetty.util.BlockingArrayQueue; import org.eclipse.jetty.util.HostPort; import org.eclipse.jetty.util.ssl.SslContextFactory; @@ -30,23 +31,40 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; * Applications add subclasses of {@link Proxy} to this configuration via: *
  * ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration();
- * proxyConfig.getProxies().add(new HttpProxy(proxyHost, 8080));
+ * proxyConfig.addProxy(new HttpProxy(proxyHost, 8080));
  * 
* * @see HttpClient#getProxyConfiguration() */ public class ProxyConfiguration { - private final List proxies = new ArrayList<>(); + private final List proxies = new BlockingArrayQueue<>(); - public List getProxies() + /** + * Adds a proxy. + * + * @param proxy a proxy + * @throws NullPointerException if {@code proxy} is null + */ + public void addProxy(Proxy proxy) { - return proxies; + proxies.add(Objects.requireNonNull(proxy)); + } + + /** + * Removes a proxy. + * + * @param proxy a proxy + * @return true if a match is found + */ + public boolean removeProxy(Proxy proxy) + { + return proxies.remove(proxy); } public Proxy match(Origin origin) { - for (Proxy proxy : getProxies()) + for (Proxy proxy : proxies) { if (proxy.matches(origin)) return proxy; diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientCustomProxyTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientCustomProxyTest.java index 4321165ff5b..869530c8e67 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientCustomProxyTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientCustomProxyTest.java @@ -95,7 +95,7 @@ public class HttpClientCustomProxyTest // Setup the custom proxy int proxyPort = connector.getLocalPort(); int serverPort = proxyPort + 1; // Any port will do for these tests - just not the same as the proxy - client.getProxyConfiguration().getProxies().add(new CAFEBABEProxy(new Origin.Address("localhost", proxyPort), false)); + client.getProxyConfiguration().addProxy(new CAFEBABEProxy(new Origin.Address("localhost", proxyPort), false)); ContentResponse response = client.newRequest(serverHost, serverPort) .timeout(5, TimeUnit.SECONDS) diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java index 40831e51a0c..9ff4caca856 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyProtocolTest.java @@ -231,7 +231,7 @@ public class HttpClientProxyProtocolTest int proxyPort = connector.getLocalPort(); int serverPort = proxyPort + 1; // Any port will do. - client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyPort)); // We are simulating to be a HttpClient inside a proxy. // The server is configured with the PROXY protocol to know the socket address of clients. diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java index fefe462df57..deae38fb6f0 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientProxyTest.java @@ -57,7 +57,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest int proxyPort = connector.getLocalPort(); int serverPort = proxyPort + 1; // Any port will do for these tests - just not the same as the proxy - client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyPort)); ContentResponse response = client.newRequest(serverHost, serverPort) .scheme(scenario.getScheme()) @@ -104,7 +104,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest String proxyHost = "localhost"; int proxyPort = connector.getLocalPort(); int serverPort = proxyPort + 1; // Any port will do for these tests - just not the same as the proxy - client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); ContentResponse response1 = client.newRequest(serverHost, serverPort) .scheme(scenario.getScheme()) @@ -202,7 +202,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest }); int proxyPort = connector.getLocalPort(); - client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); ContentResponse response1 = client.newRequest(serverHost, serverPort) .scheme(scenario.getScheme()) @@ -289,7 +289,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest client.getAuthenticationStore().addAuthentication(new BasicAuthentication(proxyURI, proxyRealm, "proxyUser", "proxyPassword")); URI serverURI = URI.create(scenario.getScheme() + "://" + serverHost + ":" + serverPort); client.getAuthenticationStore().addAuthentication(new BasicAuthentication(serverURI, serverRealm, "serverUser", "serverPassword")); - client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); final AtomicInteger requests = new AtomicInteger(); client.getRequestListeners().add(new Request.Listener.Adapter() { @@ -359,7 +359,7 @@ public class HttpClientProxyTest extends AbstractHttpClientServerTest int serverPort = proxyPort + 1; URI proxyURI = URI.create(scenario.getScheme() + "://" + proxyHost + ":" + proxyPort); client.getAuthenticationStore().addAuthentication(new BasicAuthentication(proxyURI, proxyRealm, "proxyUser", "proxyPassword")); - client.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); final AtomicInteger requests = new AtomicInteger(); client.getRequestListeners().add(new Request.Listener.Adapter() { diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java index 97770100b26..898836eb115 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java @@ -77,7 +77,7 @@ public class Socks4ProxyTest public void testSocks4Proxy() throws Exception { int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy("localhost", proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy("localhost", proxyPort)); CountDownLatch latch = new CountDownLatch(1); @@ -139,7 +139,7 @@ public class Socks4ProxyTest public void testSocks4ProxyWithSplitResponse() throws Exception { int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy("localhost", proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy("localhost", proxyPort)); CountDownLatch latch = new CountDownLatch(1); @@ -215,7 +215,7 @@ public class Socks4ProxyTest // The hostname must be that of the server, not of the proxy. ssl.setHostnameVerifier((hostname, session) -> serverHost.equals(hostname)); }); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); CountDownLatch latch = new CountDownLatch(1); client.newRequest(serverHost, serverPort) @@ -283,7 +283,7 @@ public class Socks4ProxyTest { String proxyHost = "localhost"; int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); long timeout = 1000; Request request = client.newRequest("localhost", proxyPort + 1) @@ -305,7 +305,7 @@ public class Socks4ProxyTest { String proxyHost = "localhost"; int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); long idleTimeout = 1000; client.setIdleTimeout(idleTimeout); @@ -327,7 +327,7 @@ public class Socks4ProxyTest { String proxyHost = "localhost"; int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().getProxies().add(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); Request request = client.newRequest("localhost", proxyPort + 1); FutureResponseListener listener = new FutureResponseListener(request); diff --git a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HttpClientTransportOverHTTP2Test.java b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HttpClientTransportOverHTTP2Test.java index ec3941bb4c8..8669677896e 100644 --- a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HttpClientTransportOverHTTP2Test.java +++ b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HttpClientTransportOverHTTP2Test.java @@ -422,7 +422,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest }); int proxyPort = connector.getLocalPort(); - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(new Origin.Address("localhost", proxyPort), false, new Origin.Protocol(List.of("h2c"), false))); + httpClient.getProxyConfiguration().addProxy(new HttpProxy(new Origin.Address("localhost", proxyPort), false, new Origin.Protocol(List.of("h2c"), false))); int serverPort = proxyPort + 1; // Any port will do, just not the same as the proxy. ContentResponse response = httpClient.newRequest("localhost", serverPort) diff --git a/jetty-core/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyHandler.java b/jetty-core/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyHandler.java index b71e2d23bda..5a58a5a64a8 100644 --- a/jetty-core/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyHandler.java +++ b/jetty-core/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyHandler.java @@ -480,7 +480,7 @@ public abstract class ProxyHandler extends Handler.Processor *

Forward proxies are configured in client applications that use * {@link HttpClient} in this way:

*
{@code
-     * httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort));
+     * httpClient.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort));
      * }
* * @see org.eclipse.jetty.client.ProxyConfiguration diff --git a/jetty-core/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyWithDynamicTransportTest.java b/jetty-core/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyWithDynamicTransportTest.java index 48bb1cbf38c..9157c6c49f0 100644 --- a/jetty-core/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyWithDynamicTransportTest.java +++ b/jetty-core/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyWithDynamicTransportTest.java @@ -257,7 +257,7 @@ public class ForwardProxyWithDynamicTransportTest int proxyPort = proxySecure ? proxyTLSConnector.getLocalPort() : proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy proxy = new HttpProxy(proxyAddress, proxySecure, proxyProtocol); - client.getProxyConfiguration().getProxies().add(proxy); + client.getProxyConfiguration().addProxy(proxy); String scheme = serverSecure ? "https" : "http"; int serverPort = serverSecure ? serverTLSConnector.getLocalPort() : serverConnector.getLocalPort(); @@ -293,7 +293,7 @@ public class ForwardProxyWithDynamicTransportTest int proxyPort = proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy proxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false)); - client.getProxyConfiguration().getProxies().add(proxy); + client.getProxyConfiguration().addProxy(proxy); long idleTimeout = 1000; http2Client.setStreamIdleTimeout(idleTimeout); @@ -334,7 +334,7 @@ public class ForwardProxyWithDynamicTransportTest int proxyPort = proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy httpProxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false)); - client.getProxyConfiguration().getProxies().add(httpProxy); + client.getProxyConfiguration().addProxy(httpProxy); proxy.stop(); CountDownLatch latch = new CountDownLatch(1); @@ -369,7 +369,7 @@ public class ForwardProxyWithDynamicTransportTest int proxyPort = proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy httpProxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false)); - client.getProxyConfiguration().getProxies().add(httpProxy); + client.getProxyConfiguration().addProxy(httpProxy); CountDownLatch latch = new CountDownLatch(1); client.newRequest("localhost", serverConnector.getLocalPort()) diff --git a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ForwardProxyWithDynamicTransportTest.java b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ForwardProxyWithDynamicTransportTest.java index 5efd7e0692d..07c7ccad741 100644 --- a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ForwardProxyWithDynamicTransportTest.java +++ b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ForwardProxyWithDynamicTransportTest.java @@ -261,7 +261,7 @@ public class ForwardProxyWithDynamicTransportTest int proxyPort = proxySecure ? proxyTLSConnector.getLocalPort() : proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy proxy = new HttpProxy(proxyAddress, proxySecure, proxyProtocol); - client.getProxyConfiguration().getProxies().add(proxy); + client.getProxyConfiguration().addProxy(proxy); String scheme = serverSecure ? "https" : "http"; int serverPort = serverSecure ? serverTLSConnector.getLocalPort() : serverConnector.getLocalPort(); @@ -298,7 +298,7 @@ public class ForwardProxyWithDynamicTransportTest int proxyPort = proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy proxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false)); - client.getProxyConfiguration().getProxies().add(proxy); + client.getProxyConfiguration().addProxy(proxy); long idleTimeout = 1000; http2Client.setStreamIdleTimeout(idleTimeout); @@ -339,7 +339,7 @@ public class ForwardProxyWithDynamicTransportTest int proxyPort = proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy httpProxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false)); - client.getProxyConfiguration().getProxies().add(httpProxy); + client.getProxyConfiguration().addProxy(httpProxy); proxy.stop(); CountDownLatch latch = new CountDownLatch(1); @@ -376,7 +376,7 @@ public class ForwardProxyWithDynamicTransportTest int proxyPort = proxyConnector.getLocalPort(); Origin.Address proxyAddress = new Origin.Address("localhost", proxyPort); HttpProxy httpProxy = new HttpProxy(proxyAddress, false, new Origin.Protocol(List.of("h2c"), false)); - client.getProxyConfiguration().getProxies().add(httpProxy); + client.getProxyConfiguration().addProxy(httpProxy); CountDownLatch latch = new CountDownLatch(1); client.newRequest("localhost", serverConnector.getLocalPort()) diff --git a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTransportDynamicTest.java b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTransportDynamicTest.java index 5dc87fece89..263769a5931 100644 --- a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTransportDynamicTest.java +++ b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTransportDynamicTest.java @@ -585,7 +585,7 @@ public class HttpClientTransportDynamicTest int proxyPort = connector.getLocalPort(); // The proxy speaks both http/1.1 and h2c. Origin.Protocol proxyProtocol = new Origin.Protocol(List.of("http/1.1", "h2c"), false); - client.getProxyConfiguration().getProxies().add(new HttpProxy(new Origin.Address("localhost", proxyPort), false, proxyProtocol)); + client.getProxyConfiguration().addProxy(new HttpProxy(new Origin.Address("localhost", proxyPort), false, proxyProtocol)); // Make an upgrade request from HTTP/1.1 to H2C. int serverPort = proxyPort + 1; // Any port will do. diff --git a/jetty-core/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java b/jetty-core/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java index 96bf751ddaf..47ab1260833 100644 --- a/jetty-core/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java +++ b/jetty-core/jetty-unixdomain-server/src/test/java/org/eclipse/jetty/unixdomain/server/UnixDomainTest.java @@ -174,7 +174,7 @@ public class UnixDomainTest ClientConnector clientConnector = ClientConnector.forUnixDomain(unixDomainPath); HttpClient httpClient = new HttpClient(new HttpClientTransportDynamic(clientConnector)); - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", fakeProxyPort)); + httpClient.getProxyConfiguration().addProxy(new HttpProxy("localhost", fakeProxyPort)); httpClient.start(); try { diff --git a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/ProxyServerTest.java b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/ProxyServerTest.java index 18bfd4f1773..8dcb0c6bf1a 100644 --- a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/ProxyServerTest.java +++ b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/ProxyServerTest.java @@ -42,7 +42,7 @@ public class ProxyServerTest extends AbstractEmbeddedTest server.start(); URI uri = server.getURI(); - client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", uri.getPort())); + client.getProxyConfiguration().addProxy(new HttpProxy("localhost", uri.getPort())); } @AfterEach diff --git a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/AsyncMiddleManServletTest.java b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/AsyncMiddleManServletTest.java index 38d60b7a759..9f270f235b0 100644 --- a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/AsyncMiddleManServletTest.java +++ b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/AsyncMiddleManServletTest.java @@ -153,7 +153,7 @@ public class AsyncMiddleManServletTest clientPool.setName("client"); client = new HttpClient(); client.setExecutor(clientPool); - client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + client.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort())); client.start(); } diff --git a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyServerTest.java b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyServerTest.java index 22f914a89bc..55d2806417b 100644 --- a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyServerTest.java +++ b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyServerTest.java @@ -205,7 +205,7 @@ public class ForwardProxyServerTest ClientConnector clientConnector = new ClientConnector(); clientConnector.setSslContextFactory(clientTLS); HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -253,7 +253,7 @@ public class ForwardProxyServerTest }); HttpClient httpClient = new HttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort()) @@ -291,7 +291,7 @@ public class ForwardProxyServerTest }); HttpClient httpClient = new HttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort()) diff --git a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyTLSServerTest.java b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyTLSServerTest.java index 768613919a2..4630430efcc 100644 --- a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyTLSServerTest.java +++ b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ForwardProxyTLSServerTest.java @@ -198,7 +198,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -233,7 +233,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -280,7 +280,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -365,7 +365,7 @@ public class ForwardProxyTLSServerTest }); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); // Short idle timeout for HttpClient. httpClient.setIdleTimeout(idleTimeout); httpClient.start(); @@ -403,7 +403,7 @@ public class ForwardProxyTLSServerTest stopProxy(); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(new Origin.Address("localhost", proxyPort), proxySslContextFactory != null)); + httpClient.getProxyConfiguration().addProxy(new HttpProxy(new Origin.Address("localhost", proxyPort), proxySslContextFactory != null)); httpClient.start(); ExecutionException x = assertThrows(ExecutionException.class, () -> @@ -431,7 +431,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); assertThrows(ExecutionException.class, () -> @@ -463,7 +463,7 @@ public class ForwardProxyTLSServerTest }); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); assertThrows(ExecutionException.class, () -> @@ -486,7 +486,7 @@ public class ForwardProxyTLSServerTest HttpClient httpClient = newHttpClient(); HttpProxy httpProxy = new HttpProxy(new Origin.Address("[::1]", proxyConnector.getLocalPort()), proxyTLS != null); - httpClient.getProxyConfiguration().getProxies().add(httpProxy); + httpClient.getProxyConfiguration().addProxy(httpProxy); httpClient.start(); try @@ -619,7 +619,7 @@ public class ForwardProxyTLSServerTest HttpProxy httpProxy = newHttpProxy(); if (includeAddress) httpProxy.getIncludedAddresses().add("localhost:" + serverConnector.getLocalPort()); - httpClient.getProxyConfiguration().getProxies().add(httpProxy); + httpClient.getProxyConfiguration().addProxy(httpProxy); URI uri = URI.create((proxySslContextFactory == null ? "http" : "https") + "://localhost:" + proxyConnector.getLocalPort()); httpClient.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "proxyUser", "proxyPassword")); httpClient.start(); @@ -700,7 +700,7 @@ public class ForwardProxyTLSServerTest clientConnector.setSelectors(1); clientConnector.setSslContextFactory(clientSslContextFactory); HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -771,7 +771,7 @@ public class ForwardProxyTLSServerTest proxyClientTLS.setEndpointIdentificationAlgorithm(null); proxyClientTLS.start(); HttpProxy httpProxy = new HttpProxy(new Origin.Address("localhost", proxyConnector.getLocalPort()), proxyClientTLS); - httpClient.getProxyConfiguration().getProxies().add(httpProxy); + httpClient.getProxyConfiguration().addProxy(httpProxy); httpClient.start(); try @@ -802,7 +802,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -851,7 +851,7 @@ public class ForwardProxyTLSServerTest }); startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.setConnectTimeout(timeout); httpClient.setIdleTimeout(4 * timeout); httpClient.start(); @@ -887,7 +887,7 @@ public class ForwardProxyTLSServerTest }); startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.setConnectTimeout(timeout); // Short idle timeout for HttpClient. httpClient.setIdleTimeout(timeout); @@ -926,7 +926,7 @@ public class ForwardProxyTLSServerTest } }); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.setConnectTimeout(timeout); httpClient.setIdleTimeout(10 * timeout); httpClient.start(); @@ -975,7 +975,7 @@ public class ForwardProxyTLSServerTest } HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + httpClient.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); httpClient.start(); try diff --git a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletFailureTest.java b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletFailureTest.java index 3cfccf19a71..74fd65d1d94 100644 --- a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletFailureTest.java +++ b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletFailureTest.java @@ -116,7 +116,7 @@ public class ProxyServletFailureTest QueuedThreadPool executor = new QueuedThreadPool(); executor.setName("client"); result.setExecutor(executor); - result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + result.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort())); result.start(); return result; } diff --git a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletLoadTest.java b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletLoadTest.java index 9835d66d866..c5a6c568727 100644 --- a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletLoadTest.java +++ b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletLoadTest.java @@ -109,7 +109,7 @@ public class ProxyServletLoadTest clientPool.setName("client"); HttpClient result = new HttpClient(); result.setExecutor(clientPool); - result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + result.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort())); result.start(); client = result; } diff --git a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletTest.java b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletTest.java index 8b30fa9e3c4..80b2d1c8285 100644 --- a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletTest.java +++ b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/ProxyServletTest.java @@ -62,6 +62,7 @@ import org.eclipse.jetty.client.ConnectionPool; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpDestination; import org.eclipse.jetty.client.HttpProxy; +import org.eclipse.jetty.client.ProxyConfiguration.Proxy; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; @@ -124,6 +125,7 @@ public class ProxyServletTest } private HttpClient client; + private Proxy clientProxy; private Server proxy; private ServerConnector proxyConnector; private ServletContextHandler proxyContext; @@ -198,6 +200,7 @@ public class ProxyServletTest private void startClient(Consumer consumer) throws Exception { + clientProxy = new HttpProxy("localhost", proxyConnector.getLocalPort()); client = prepareClient(consumer); } @@ -207,7 +210,7 @@ public class ProxyServletTest clientPool.setName("client"); HttpClient result = new HttpClient(); result.setExecutor(clientPool); - result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + result.getProxyConfiguration().addProxy(clientProxy); if (consumer != null) consumer.accept(result); result.start(); @@ -730,7 +733,7 @@ public class ProxyServletTest startProxy(proxyServletClass); startClient(); int port = serverConnector.getLocalPort(); - client.getProxyConfiguration().getProxies().get(0).getExcludedAddresses().add("127.0.0.1:" + port); + clientProxy.getExcludedAddresses().add("127.0.0.1:" + port); // Try with a proxied host ContentResponse response = client.newRequest("localhost", port) diff --git a/jetty-ee9/jetty-ee9-demos/jetty-ee9-demo-embedded/src/test/java/org/eclipse/jetty/ee9/demos/ProxyServerTest.java b/jetty-ee9/jetty-ee9-demos/jetty-ee9-demo-embedded/src/test/java/org/eclipse/jetty/ee9/demos/ProxyServerTest.java index 2b0571c0397..d61ae56c456 100644 --- a/jetty-ee9/jetty-ee9-demos/jetty-ee9-demo-embedded/src/test/java/org/eclipse/jetty/ee9/demos/ProxyServerTest.java +++ b/jetty-ee9/jetty-ee9-demos/jetty-ee9-demo-embedded/src/test/java/org/eclipse/jetty/ee9/demos/ProxyServerTest.java @@ -40,7 +40,7 @@ public class ProxyServerTest extends AbstractEmbeddedTest server.start(); URI uri = server.getURI(); - client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", uri.getPort())); + client.getProxyConfiguration().addProxy(new HttpProxy("localhost", uri.getPort())); } @AfterEach diff --git a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/AsyncMiddleManServletTest.java b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/AsyncMiddleManServletTest.java index df5acb633ab..ae2cf713455 100644 --- a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/AsyncMiddleManServletTest.java +++ b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/AsyncMiddleManServletTest.java @@ -153,7 +153,7 @@ public class AsyncMiddleManServletTest clientPool.setName("client"); client = new HttpClient(); client.setExecutor(clientPool); - client.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + client.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort())); client.start(); } diff --git a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyServerTest.java b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyServerTest.java index 582ce7f2286..1592f23211b 100644 --- a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyServerTest.java +++ b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyServerTest.java @@ -205,7 +205,7 @@ public class ForwardProxyServerTest ClientConnector clientConnector = new ClientConnector(); clientConnector.setSslContextFactory(clientTLS); HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -253,7 +253,7 @@ public class ForwardProxyServerTest }); HttpClient httpClient = new HttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort()) @@ -291,7 +291,7 @@ public class ForwardProxyServerTest }); HttpClient httpClient = new HttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort()) diff --git a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyTLSServerTest.java b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyTLSServerTest.java index 5e4b0edc453..6c4b2c3f84e 100644 --- a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyTLSServerTest.java +++ b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ForwardProxyTLSServerTest.java @@ -196,7 +196,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -231,7 +231,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -278,7 +278,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -363,7 +363,7 @@ public class ForwardProxyTLSServerTest }); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); // Short idle timeout for HttpClient. httpClient.setIdleTimeout(idleTimeout); httpClient.start(); @@ -401,7 +401,7 @@ public class ForwardProxyTLSServerTest stopProxy(); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(new Origin.Address("localhost", proxyPort), proxySslContextFactory != null)); + httpClient.getProxyConfiguration().addProxy(new HttpProxy(new Origin.Address("localhost", proxyPort), proxySslContextFactory != null)); httpClient.start(); ExecutionException x = assertThrows(ExecutionException.class, () -> @@ -429,7 +429,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); assertThrows(ExecutionException.class, () -> @@ -461,7 +461,7 @@ public class ForwardProxyTLSServerTest }); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); assertThrows(ExecutionException.class, () -> @@ -484,7 +484,7 @@ public class ForwardProxyTLSServerTest HttpClient httpClient = newHttpClient(); HttpProxy httpProxy = new HttpProxy(new Origin.Address("[::1]", proxyConnector.getLocalPort()), proxyTLS != null); - httpClient.getProxyConfiguration().getProxies().add(httpProxy); + httpClient.getProxyConfiguration().addProxy(httpProxy); httpClient.start(); try @@ -617,7 +617,7 @@ public class ForwardProxyTLSServerTest HttpProxy httpProxy = newHttpProxy(); if (includeAddress) httpProxy.getIncludedAddresses().add("localhost:" + serverConnector.getLocalPort()); - httpClient.getProxyConfiguration().getProxies().add(httpProxy); + httpClient.getProxyConfiguration().addProxy(httpProxy); URI uri = URI.create((proxySslContextFactory == null ? "http" : "https") + "://localhost:" + proxyConnector.getLocalPort()); httpClient.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "proxyUser", "proxyPassword")); httpClient.start(); @@ -698,7 +698,7 @@ public class ForwardProxyTLSServerTest clientConnector.setSelectors(1); clientConnector.setSslContextFactory(clientSslContextFactory); HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -769,7 +769,7 @@ public class ForwardProxyTLSServerTest proxyClientTLS.setEndpointIdentificationAlgorithm(null); proxyClientTLS.start(); HttpProxy httpProxy = new HttpProxy(new Origin.Address("localhost", proxyConnector.getLocalPort()), proxyClientTLS); - httpClient.getProxyConfiguration().getProxies().add(httpProxy); + httpClient.getProxyConfiguration().addProxy(httpProxy); httpClient.start(); try @@ -800,7 +800,7 @@ public class ForwardProxyTLSServerTest startProxy(proxyTLS); HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); + httpClient.getProxyConfiguration().addProxy(newHttpProxy()); httpClient.start(); try @@ -851,7 +851,7 @@ public class ForwardProxyTLSServerTest } HttpClient httpClient = newHttpClient(); - httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); + httpClient.getProxyConfiguration().addProxy(new HttpProxy(proxyHost, proxyPort)); httpClient.start(); try diff --git a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletFailureTest.java b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletFailureTest.java index 44a59df19be..9a286f1eb27 100644 --- a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletFailureTest.java +++ b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletFailureTest.java @@ -116,7 +116,7 @@ public class ProxyServletFailureTest QueuedThreadPool executor = new QueuedThreadPool(); executor.setName("client"); result.setExecutor(executor); - result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + result.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort())); result.start(); return result; } diff --git a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletLoadTest.java b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletLoadTest.java index 047f87bf6f6..648925a6341 100644 --- a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletLoadTest.java +++ b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletLoadTest.java @@ -109,7 +109,7 @@ public class ProxyServletLoadTest clientPool.setName("client"); HttpClient result = new HttpClient(); result.setExecutor(clientPool); - result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + result.getProxyConfiguration().addProxy(new HttpProxy("localhost", proxyConnector.getLocalPort())); result.start(); client = result; } diff --git a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletTest.java b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletTest.java index ac731694235..2088c7df455 100644 --- a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletTest.java +++ b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/ProxyServletTest.java @@ -26,7 +26,9 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; @@ -62,6 +64,7 @@ import org.eclipse.jetty.client.ConnectionPool; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpDestination; import org.eclipse.jetty.client.HttpProxy; +import org.eclipse.jetty.client.ProxyConfiguration.Proxy; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; @@ -123,6 +126,7 @@ public class ProxyServletTest } private HttpClient client; + private Proxy clientProxy; private Server proxy; private ServerConnector proxyConnector; private ServletContextHandler proxyContext; @@ -197,6 +201,7 @@ public class ProxyServletTest private void startClient(Consumer consumer) throws Exception { + clientProxy = new HttpProxy("localhost", proxyConnector.getLocalPort()); client = prepareClient(consumer); } @@ -206,7 +211,7 @@ public class ProxyServletTest clientPool.setName("client"); HttpClient result = new HttpClient(); result.setExecutor(clientPool); - result.getProxyConfiguration().getProxies().add(new HttpProxy("localhost", proxyConnector.getLocalPort())); + result.getProxyConfiguration().addProxy(clientProxy); if (consumer != null) consumer.accept(result); result.start(); @@ -729,7 +734,7 @@ public class ProxyServletTest startProxy(proxyServletClass); startClient(); int port = serverConnector.getLocalPort(); - client.getProxyConfiguration().getProxies().get(0).getExcludedAddresses().add("127.0.0.1:" + port); + clientProxy.getExcludedAddresses().add("127.0.0.1:" + port); // Try with a proxied host ContentResponse response = client.newRequest("localhost", port) From 3b2d4048fdc7b256dd91f035f9245e92d6250dea Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 25 Oct 2022 21:11:10 +1100 Subject: [PATCH 24/42] replaced getPathInContext with static method updates from review --- .../java/org/eclipse/jetty/http/HttpURI.java | 2 +- .../jetty/rewrite/handler/CompactPathRule.java | 8 ++++---- .../java/org/eclipse/jetty/server/Context.java | 10 ++++++++-- .../java/org/eclipse/jetty/server/Request.java | 14 +++++++++++--- .../eclipse/jetty/server/ResourceService.java | 1 - .../java/org/eclipse/jetty/server/Server.java | 4 ++-- .../jetty/server/handler/ContextHandler.java | 12 ++++++------ .../server/handler/MovedContextHandler.java | 5 +++-- .../handler/ReHandlingErrorProcessor.java | 2 +- .../jetty/server/handler/ResourceHandler.java | 5 +++-- .../jetty/server/handler/TryPathsHandler.java | 2 +- .../jetty/server/ErrorProcessorTest.java | 17 +++++++++-------- .../java/org/eclipse/jetty/util/Attributes.java | 14 +++++++------- .../java/org/eclipse/jetty/util/URIUtil.java | 6 +++--- .../jetty/ee10/servlet/DefaultServlet.java | 2 +- .../ee10/servlet/ServletContextHandler.java | 4 +++- .../ee10/servlet/ServletContextRequest.java | 4 ++-- .../authentication/FormAuthenticator.java | 5 +++-- .../org/eclipse/jetty/ee9/nested/Request.java | 5 +++-- 19 files changed, 71 insertions(+), 51 deletions(-) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 9c8ec37a61a..4ad2b6f3837 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -898,7 +898,7 @@ public interface HttpURI { if (hasAuthority() && !isPathValidForAuthority(path)) throw new IllegalArgumentException("Relative path with authority"); - if (!URIUtil.isLegalPath(path)) + if (!URIUtil.isValidPath(path)) throw new IllegalArgumentException("Path not correctly encoded: " + path); _uri = null; _path = path; diff --git a/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java b/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java index fadab27eae8..40f33902a17 100644 --- a/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java +++ b/jetty-core/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java @@ -26,17 +26,17 @@ import org.eclipse.jetty.util.URIUtil; public class CompactPathRule extends Rule { @Override - public Request.WrapperProcessor matchAndApply(Request.WrapperProcessor input) throws IOException + public Request.WrapperProcessor matchAndApply(Request.WrapperProcessor request) throws IOException { - String path = Request.getPathInContext(input); + String path = request.getHttpURI().getCanonicalPath(); String compacted = URIUtil.compactPath(path); if (path.equals(compacted)) return null; - HttpURI uri = Request.updateHttpURI(input, compacted); + HttpURI uri = Request.newHttpURIFrom(request, compacted); - return new Request.WrapperProcessor(input) + return new Request.WrapperProcessor(request) { @Override public HttpURI getHttpURI() diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java index 31c29c9a34d..4715ff637f4 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java @@ -57,6 +57,12 @@ public interface Context extends Attributes, Decorator, Executor /** scope the calling thread to the context and request and run the runnable. */ void run(Runnable runnable, Request request); - /** Return a URI path scoped to this context **/ - String pathInContext(String path); + /** + *

Get a URI path scoped to a context. For example if the context path is "/ctx" then a + * full path of "/ctx/foo/bar" will return "/foo/bar".

+ * @param fullPath A full URI path + * @return The URI path scoped to the context, or null if the fullPath is not in the context. + * The empty string is returned if the fullPath is exactly the context path. + */ + String getPathInContext(String fullPath); } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index e84dc1e1c46..4aa156b9220 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -166,13 +166,15 @@ public interface Request extends Attributes, Content.Source /** *

Get the canonically encoded path of the URI, scoped to the current context.

- *

The pathInContext represents the targeted resource within the current content for the request.

+ *

For example, when the request has a {@link Context} with {@code contextPath=/ctx} and the requests + * {@link HttpURI} has{@code canonicalPath=/ctx/foo}, then the path in context is {@code /foo}.

* @return The part of the canonically encoded path of the URI after any context path prefix has been removed. * @see HttpURI#getCanonicalPath() + * @see Context#getContextPath() */ static String getPathInContext(Request request) { - return request.getContext().pathInContext(request.getHttpURI().getCanonicalPath()); + return request.getContext().getPathInContext(request.getHttpURI().getCanonicalPath()); } /** @@ -703,7 +705,13 @@ public interface Request extends Attributes, Content.Source } } - static HttpURI updateHttpURI(Request request, String newPathInContext) + /** + *

Create a new {@link HttpURI} for a request by replacing the path in context

+ * @param request The request to base the HttpURI on. + * @param newPathInContext The new path in context for the URI + * @return A new immutable HttpURI for the request with the path replaced (but parameters and query string retained). + */ + static HttpURI newHttpURIFrom(Request request, String newPathInContext) { return HttpURI.build(request.getHttpURI()) .path(URIUtil.addPaths(getContextPath(request), newPathInContext)) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index b7c847cedb4..7e41050a20e 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -536,7 +536,6 @@ public class ResourceService { // Redirect to the index response.getHeaders().putLongField(HttpHeader.CONTENT_LENGTH, 0); - // TODO need URI util that handles param and query without reconstructing entire URI with scheme and authority HttpURI.Mutable uri = HttpURI.build(request.getHttpURI()); uri.path(URIUtil.addPaths(contextPath, welcomeTarget)); return new WelcomeAction(WelcomeActionType.REDIRECT, uri.getPathQuery()); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index e7c387a456c..78ce8581b71 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -787,9 +787,9 @@ public class Server extends Handler.Wrapper implements Attributes } @Override - public String pathInContext(String path) + public String getPathInContext(String fullPath) { - return path; + return fullPath; } } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 596f9e5fe2b..c68e4ea684c 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -1168,17 +1168,17 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace } @Override - public String pathInContext(String path) + public String getPathInContext(String fullPath) { if (_rootContext) - return path; - if (!path.startsWith(_contextPath)) + return fullPath; + if (!fullPath.startsWith(_contextPath)) return null; - if (path.length() == _contextPath.length()) + if (fullPath.length() == _contextPath.length()) return ""; - if (path.charAt(_contextPath.length()) != '/') + if (fullPath.charAt(_contextPath.length()) != '/') return null; - return path.substring(_contextPath.length()); + return fullPath.substring(_contextPath.length()); } } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java index ec2d58f69ca..83f00743993 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/MovedContextHandler.java @@ -102,8 +102,9 @@ public class MovedContextHandler extends ContextHandler return; String path = _newContextURL; - if (!_discardPathInfo && Request.getPathInContext(request) != null) - path = URIUtil.addPaths(path, Request.getPathInContext(request)); + String pathInContext = Request.getPathInContext(request); + if (!_discardPathInfo && pathInContext != null) + path = URIUtil.addPaths(path, pathInContext); HttpURI uri = request.getHttpURI(); StringBuilder location = new StringBuilder(); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java index 97cd2bbed5a..6d6e49e1b86 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ReHandlingErrorProcessor.java @@ -56,7 +56,7 @@ public abstract class ReHandlingErrorProcessor extends ErrorProcessor if (pathInContext != null) { request.setAttribute(ReHandlingErrorProcessor.class.getName(), pathInContext); - HttpURI uri = Request.updateHttpURI(request, pathInContext); + HttpURI uri = Request.newHttpURIFrom(request, pathInContext); Request.Wrapper wrapper = new ReHandleRequestWrapper(request, uri); try diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java index fe78924e1e3..f456b01ca31 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java @@ -92,8 +92,9 @@ public class ResourceHandler extends Handler.Wrapper for (String welcome : _welcomes) { - String welcomeInContext = URIUtil.addPaths(Request.getPathInContext(request), welcome); - Resource welcomePath = _resourceBase.resolve(Request.getPathInContext(request)).resolve(welcome); + String pathInContext = Request.getPathInContext(request); + String welcomeInContext = URIUtil.addPaths(pathInContext, welcome); + Resource welcomePath = _resourceBase.resolve(pathInContext).resolve(welcome); if (Resources.isReadableFile(welcomePath)) return welcomeInContext; } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java index 6935719544d..a33b08e63de 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java @@ -90,7 +90,7 @@ public class TryPathsHandler extends Handler.Wrapper public TryPathsRequest(Request wrapped, String pathInContext) { super(wrapped); - _uri = Request.updateHttpURI(wrapped, URIUtil.canonicalPath(pathInContext)); + _uri = Request.newHttpURIFrom(wrapped, URIUtil.canonicalPath(pathInContext)); } @Override diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java index cf10662a627..1734e320e7b 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ErrorProcessorTest.java @@ -73,21 +73,22 @@ public class ErrorProcessorTest @Override public void process(Request request, Response response, Callback callback) { - if (Request.getPathInContext(request).startsWith("/badmessage/")) + String pathInContext = Request.getPathInContext(request); + if (pathInContext.startsWith("/badmessage/")) { - int code = Integer.parseInt(Request.getPathInContext(request).substring(Request.getPathInContext(request).lastIndexOf('/') + 1)); + int code = Integer.parseInt(pathInContext.substring(pathInContext.lastIndexOf('/') + 1)); throw new BadMessageException(code); } // produce an exception with an JSON formatted cause message - if (Request.getPathInContext(request).startsWith("/jsonmessage/")) + if (pathInContext.startsWith("/jsonmessage/")) { String message = "\"}, \"glossary\": {\n \"title\": \"example\"\n }\n {\""; throw new TestException(message); } // produce an exception with an XML cause message - if (Request.getPathInContext(request).startsWith("/xmlmessage/")) + if (pathInContext.startsWith("/xmlmessage/")) { String message = "\n" + @@ -98,14 +99,14 @@ public class ErrorProcessorTest } // produce an exception with an HTML cause message - if (Request.getPathInContext(request).startsWith("/htmlmessage/")) + if (pathInContext.startsWith("/htmlmessage/")) { String message = "
%3Cscript%3E"; throw new TestException(message); } // produce an exception with a UTF-8 cause message - if (Request.getPathInContext(request).startsWith("/utf8message/")) + if (pathInContext.startsWith("/utf8message/")) { // @checkstyle-disable-check : AvoidEscapedUnicodeCharacters String message = "Euro is € and \u20AC and %E2%82%AC"; @@ -114,12 +115,12 @@ public class ErrorProcessorTest } // 200 response - if (Request.getPathInContext(request).startsWith("/ok/")) + if (pathInContext.startsWith("/ok/")) { Content.Sink.write( response, true, - "%s Error %s : %s%n".formatted(Request.getPathInContext(request), request.getAttribute(ErrorProcessor.ERROR_STATUS), request.getAttribute(ErrorProcessor.ERROR_MESSAGE)), + "%s Error %s : %s%n".formatted(pathInContext, request.getAttribute(ErrorProcessor.ERROR_STATUS), request.getAttribute(ErrorProcessor.ERROR_MESSAGE)), callback); return; } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java index ff2611e39e4..b2ba83379ab 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java @@ -185,45 +185,45 @@ public interface Attributes @Override public Object removeAttribute(String name) { - return _wrapped.removeAttribute(name); + return getWrapped().removeAttribute(name); } @Override public Object setAttribute(String name, Object attribute) { - return _wrapped.setAttribute(name, attribute); + return getWrapped().setAttribute(name, attribute); } @Override public Object getAttribute(String name) { - return _wrapped.getAttribute(name); + return getWrapped().getAttribute(name); } @Override public Set getAttributeNameSet() { - return _wrapped.getAttributeNameSet(); + return getWrapped().getAttributeNameSet(); } @Override public void clearAttributes() { - _wrapped.clearAttributes(); + getWrapped().clearAttributes(); } // TODO: remove? or fix (don't want the wrapped and wrapper to match) @Override public int hashCode() { - return _wrapped.hashCode(); + return getWrapped().hashCode(); } // TODO: remove? or fix (don't want the wrapped and wrapper to match) @Override public boolean equals(Object obj) { - return _wrapped.equals(obj); + return getWrapped().equals(obj); } } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java index 31dc97ed0e8..4944e1c6a13 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java @@ -698,10 +698,10 @@ public final class URIUtil } /** - * @param path The path to check for legality - * @return True if the path does not contain any illegal path characters + * @param path The path to check for validity + * @return True if the path does not contain any invalid path characters */ - public static boolean isLegalPath(String path) + public static boolean isValidPath(String path) { if (path == null) return true; diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java index 46ffeca8b7a..def3df7ce17 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java @@ -444,7 +444,7 @@ public class DefaultServlet extends HttpServlet _httpFields = fields.asImmutable(); _uri = (request.getDispatcherType() == DispatcherType.REQUEST) ? getWrapped().getHttpURI() - : Request.updateHttpURI(getWrapped(), URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo())); + : Request.newHttpURIFrom(getWrapped(), URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo())); } @Override diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java index 09fb8e18f57..d80b4c4352e 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java @@ -1187,7 +1187,9 @@ public class ServletContextHandler extends ContextHandler implements Graceful @Override protected ServletContextRequest wrap(Request request) { - String pathInContext = getContext().pathInContext(request.getHttpURI().getCanonicalPath()); + // we need to directly ask the context for the pathInContext rather than use the utility static method, as + // we have not yet wrapped the request in this context. + String pathInContext = getContext().getPathInContext(request.getHttpURI().getCanonicalPath()); MatchedResource matchedResource = _servletHandler.getMatchedServlet(pathInContext); if (matchedResource == null) return null; diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java index fd1d2dd98b0..4e975402dc7 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextRequest.java @@ -242,8 +242,8 @@ public class ServletContextRequest extends ContextRequest implements Runnable { case "o.e.j.s.s.ServletScopedRequest.request" -> _httpServletRequest; case "o.e.j.s.s.ServletScopedRequest.response" -> _response.getHttpServletResponse(); - case "o.e.j.s.s.ServletScopedRequest.servlet" -> _mappedServlet.getServletPathMapping(_pathInContext).getServletName(); - case "o.e.j.s.s.ServletScopedRequest.url-pattern" -> _mappedServlet.getServletPathMapping(_pathInContext).getPattern(); + case "o.e.j.s.s.ServletScopedRequest.servlet" -> _mappedServlet.getServletPathMapping(getPathInContext()).getServletName(); + case "o.e.j.s.s.ServletScopedRequest.url-pattern" -> _mappedServlet.getServletPathMapping(getPathInContext()).getPattern(); default -> super.getAttribute(name); }; } diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java index bddb2328dc8..6b10a2f03cd 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/security/authentication/FormAuthenticator.java @@ -223,12 +223,13 @@ public class FormAuthenticator extends LoginAuthenticator ServletContextRequest servletContextRequest = Request.as(req, ServletContextRequest.class); ServletContextRequest.ServletApiRequest servletApiRequest = servletContextRequest.getServletApiRequest(); - boolean jSecurityCheck = isJSecurityCheck(Request.getPathInContext(req)); + String pathInContext = servletContextRequest.getPathInContext(); + boolean jSecurityCheck = isJSecurityCheck(pathInContext); mandatory |= jSecurityCheck; if (!mandatory) return new DeferredAuthentication(this); - if (isLoginOrErrorPage(Request.getPathInContext(req)) && !DeferredAuthentication.isDeferred(res)) + if (isLoginOrErrorPage(pathInContext) && !DeferredAuthentication.isDeferred(res)) return new DeferredAuthentication(this); // Handle a request for authentication. diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java index ac6b3642c8b..dcd49572522 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java @@ -1545,9 +1545,10 @@ public class Request implements HttpServletRequest _method = coreRequest.getMethod(); _uri = coreRequest.getHttpURI(); + String pathInContext = org.eclipse.jetty.server.Request.getPathInContext(coreRequest); _pathInContext = _context.getContextHandler().isCanonicalEncodingURIs() - ? org.eclipse.jetty.server.Request.getPathInContext(coreRequest) - : URIUtil.decodePath(org.eclipse.jetty.server.Request.getPathInContext(coreRequest)); + ? pathInContext + : URIUtil.decodePath(pathInContext); _httpFields = coreRequest.getHeaders(); setSecure(coreRequest.isSecure()); From 58bfda7cf901afd9a8af6ba7a472a4210159c682 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 25 Oct 2022 21:47:21 +1100 Subject: [PATCH 25/42] replaced getPathInContext with static method updates from review --- .../src/main/java/org/eclipse/jetty/server/Request.java | 4 ++-- .../main/java/org/eclipse/jetty/server/ResourceService.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 4aa156b9220..b595b9d859a 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -153,10 +153,10 @@ public interface Request extends Attributes, Content.Source Context getContext(); /** - *

Get the context pat. this is equivalent to request.getContext().getContextPath() + *

Get the context path. This is equivalent to {@code request.getContext().getContextPath()}. * * @param request The request to get the context path from. - * @return The contextPath of the request. . + * @return The contextPath of the request. * @see Context#getContextPath() */ static String getContextPath(Request request) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index 7e41050a20e..dcb4dc54b85 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -451,7 +451,6 @@ public class ResourceService HttpURI.Mutable uri = HttpURI.build(request.getHttpURI()); if (!uri.getCanonicalPath().endsWith("/")) { - // TODO need URI util that handles param and query without reconstructing entire URI with scheme and authority uri.path(uri.getCanonicalPath() + "/"); response.getHeaders().putLongField(HttpHeader.CONTENT_LENGTH, 0); // TODO: can writeRedirect (override) also work for WelcomeActionType.REDIRECT? From cf366b332379f445a7327777b2c39296daf1ddf8 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Tue, 25 Oct 2022 15:42:49 +0200 Subject: [PATCH 26/42] Improved javadocs. Signed-off-by: Simone Bordet --- .../java/org/eclipse/jetty/http/HttpURI.java | 2 +- .../org/eclipse/jetty/server/Context.java | 12 +++++---- .../org/eclipse/jetty/server/Request.java | 25 ++++++++++++------- .../jetty/server/handler/ContextHandler.java | 5 ++-- .../java/org/eclipse/jetty/util/URIUtil.java | 2 +- .../ee10/servlet/ServletContextHandler.java | 4 +-- 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 4ad2b6f3837..6ee13c3c6b9 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -898,7 +898,7 @@ public interface HttpURI { if (hasAuthority() && !isPathValidForAuthority(path)) throw new IllegalArgumentException("Relative path with authority"); - if (!URIUtil.isValidPath(path)) + if (!URIUtil.isPathValid(path)) throw new IllegalArgumentException("Path not correctly encoded: " + path); _uri = null; _path = path; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java index 4715ff637f4..c3daec8cad3 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Context.java @@ -35,7 +35,7 @@ import org.eclipse.jetty.util.resource.Resource; public interface Context extends Attributes, Decorator, Executor { /** - *

Get the context path of this Context.

+ * @return the context path of this Context */ String getContextPath(); @@ -58,11 +58,13 @@ public interface Context extends Attributes, Decorator, Executor void run(Runnable runnable, Request request); /** - *

Get a URI path scoped to a context. For example if the context path is "/ctx" then a - * full path of "/ctx/foo/bar" will return "/foo/bar".

+ *

Returns a URI path scoped to this Context.

+ *

For example, if the context path is {@code /ctx} then a + * full path of {@code /ctx/foo/bar} will return {@code /foo/bar}.

+ * * @param fullPath A full URI path - * @return The URI path scoped to the context, or null if the fullPath is not in the context. - * The empty string is returned if the fullPath is exactly the context path. + * @return The URI path scoped to this Context, or {@code null} if the full path does not match this Context. + * The empty string is returned if the full path is exactly the context path. */ String getPathInContext(String fullPath); } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index b595b9d859a..c385cd787c7 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -121,6 +121,7 @@ public interface Request extends Attributes, Content.Source /** * an ID unique within the lifetime scope of the {@link ConnectionMetaData#getId()}). * This may be a protocol ID (eg HTTP/2 stream ID) or it may be unrelated to the protocol. + * * @see HttpStream#getId() */ String getId(); @@ -143,7 +144,7 @@ public interface Request extends Attributes, Content.Source /** * @return the HTTP URI of this request * @see #getContextPath(Request) - * @see #getPathInContext(Request) + * @see #getPathInContext(Request) */ HttpURI getHttpURI(); @@ -153,7 +154,8 @@ public interface Request extends Attributes, Content.Source Context getContext(); /** - *

Get the context path. This is equivalent to {@code request.getContext().getContextPath()}. + *

Returns the context path of this Request.

+ *

This is equivalent to {@code request.getContext().getContextPath()}.

* * @param request The request to get the context path from. * @return The contextPath of the request. @@ -165,9 +167,10 @@ public interface Request extends Attributes, Content.Source } /** - *

Get the canonically encoded path of the URI, scoped to the current context.

- *

For example, when the request has a {@link Context} with {@code contextPath=/ctx} and the requests - * {@link HttpURI} has{@code canonicalPath=/ctx/foo}, then the path in context is {@code /foo}.

+ *

Returns the canonically encoded path of the URI, scoped to the current context.

+ *

For example, when the request has a {@link Context} with {@code contextPath=/ctx} and the request's + * {@link HttpURI} canonical path is {@code canonicalPath=/ctx/foo}, then {@code pathInContext=/foo}.

+ * * @return The part of the canonically encoded path of the URI after any context path prefix has been removed. * @see HttpURI#getCanonicalPath() * @see Context#getContextPath() @@ -706,10 +709,14 @@ public interface Request extends Attributes, Content.Source } /** - *

Create a new {@link HttpURI} for a request by replacing the path in context

- * @param request The request to base the HttpURI on. - * @param newPathInContext The new path in context for the URI - * @return A new immutable HttpURI for the request with the path replaced (but parameters and query string retained). + *

Creates a new {@link HttpURI} from the given Request's HttpURI and the given path in context.

+ *

For example, for {@code contextPath=/ctx}, {@code request.httpURI=http://host/ctx/path?a=b}, and + * {@code newPathInContext=/newPath}, the returned HttpURI is {@code http://host/ctx/newPath?a=b}.

+ * + * @param request The request to base the new HttpURI on. + * @param newPathInContext The new path in context for the new HttpURI + * @return A new immutable HttpURI with the path in context replaced, but query string and path + * parameters retained. */ static HttpURI newHttpURIFrom(Request request, String newPathInContext) { diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index c68e4ea684c..ec91a81c036 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -610,11 +610,10 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace if (!checkVirtualHost(request)) return null; - // Root context accepts all requests + // The root context handles all requests. if (!_rootContext) { - // Otherwise check the path - + // Otherwise match the path. String path = request.getHttpURI().getCanonicalPath(); if (path == null || !path.startsWith(_contextPath)) return null; diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java index 4944e1c6a13..ce4540d0aa6 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java @@ -701,7 +701,7 @@ public final class URIUtil * @param path The path to check for validity * @return True if the path does not contain any invalid path characters */ - public static boolean isValidPath(String path) + public static boolean isPathValid(String path) { if (path == null) return true; diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java index d80b4c4352e..30a32c7e931 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java @@ -1187,8 +1187,8 @@ public class ServletContextHandler extends ContextHandler implements Graceful @Override protected ServletContextRequest wrap(Request request) { - // we need to directly ask the context for the pathInContext rather than use the utility static method, as - // we have not yet wrapped the request in this context. + // Need to ask directly to the Context for the pathInContext, rather than using + // Request.getPathInContext(), as the request is not yet wrapped in this Context. String pathInContext = getContext().getPathInContext(request.getHttpURI().getCanonicalPath()); MatchedResource matchedResource = _servletHandler.getMatchedServlet(pathInContext); if (matchedResource == null) From 05e17220452cae414f15761376c1f2f898dfcc70 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Tue, 25 Oct 2022 15:53:07 +0200 Subject: [PATCH 27/42] Relax test case assert. The test may fail either for a SocketTimeoutException, or a NoRouteToHostException. Signed-off-by: Simone Bordet --- .../java/org/eclipse/jetty/http2/tests/ConnectTimeoutTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/ConnectTimeoutTest.java b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/ConnectTimeoutTest.java index 231ed3f4003..8948ab54b73 100644 --- a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/ConnectTimeoutTest.java +++ b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/ConnectTimeoutTest.java @@ -25,8 +25,6 @@ import org.eclipse.jetty.util.Promise; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; import static org.junit.jupiter.api.Assertions.assertTrue; public class ConnectTimeoutTest extends AbstractTest @@ -49,7 +47,6 @@ public class ConnectTimeoutTest extends AbstractTest @Override public void failed(Throwable x) { - assertThat(x, instanceOf(SocketTimeoutException.class)); latch.countDown(); } }); From 8eb10b2d7441ab98cb61e811af8225f32c5541f1 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 25 Oct 2022 10:04:33 -0500 Subject: [PATCH 28/42] Jetty 12 - Introduce PathMappingsHandler (#8748) * Introduce PathMappingsHandler --- .../jetty/http/pathmap/PathMappings.java | 6 + .../server/handler/PathMappingsHandler.java | 103 +++++++ .../server/handler/ContextHandlerTest.java | 26 ++ .../handler/PathMappingsHandlerTest.java | 283 ++++++++++++++++++ 4 files changed, 418 insertions(+) create mode 100644 jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/PathMappingsHandler.java create mode 100644 jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/PathMappingsHandlerTest.java diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathMappings.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathMappings.java index 8664fbf3896..bd339006fc3 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathMappings.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/pathmap/PathMappings.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.function.Predicate; +import java.util.stream.Stream; import org.eclipse.jetty.util.Index; import org.eclipse.jetty.util.annotation.ManagedAttribute; @@ -88,6 +89,11 @@ public class PathMappings implements Iterable>, Dumpable _suffixMap.clear(); } + public Stream> streamResources() + { + return _mappings.stream(); + } + public void removeIf(Predicate> predicate) { _mappings.removeIf(predicate); diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/PathMappingsHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/PathMappingsHandler.java new file mode 100644 index 00000000000..3dffc3e3acd --- /dev/null +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/PathMappingsHandler.java @@ -0,0 +1,103 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.server.handler; + +import java.io.IOException; +import java.util.List; +import java.util.function.Supplier; + +import org.eclipse.jetty.http.pathmap.MappedResource; +import org.eclipse.jetty.http.pathmap.MatchedResource; +import org.eclipse.jetty.http.pathmap.PathMappings; +import org.eclipse.jetty.http.pathmap.PathSpec; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.util.component.Dumpable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A Handler that delegates to other handlers through a configured {@link PathMappings}. + */ + +public class PathMappingsHandler extends Handler.AbstractContainer +{ + private static final Logger LOG = LoggerFactory.getLogger(PathMappingsHandler.class); + + private final PathMappings mappings = new PathMappings<>(); + + @Override + public void addHandler(Handler handler) + { + throw new UnsupportedOperationException("Arbitrary addHandler() not supported, use addMapping() instead"); + } + + @Override + public void addHandler(Supplier supplier) + { + throw new UnsupportedOperationException("Arbitrary addHandler() not supported, use addMapping() instead"); + } + + @Override + public List getHandlers() + { + return mappings.streamResources().map(MappedResource::getResource).toList(); + } + + public void addMapping(PathSpec pathSpec, Handler handler) + { + if (isStarted()) + throw new IllegalStateException("Cannot add mapping: " + this); + + // check that self isn't present + if (handler == this || handler instanceof Handler.Container container && container.getDescendants().contains(this)) + throw new IllegalStateException("Unable to addHandler of self: " + handler); + + // check existing mappings + for (MappedResource entry : mappings) + { + Handler entryHandler = entry.getResource(); + + if (entryHandler == this || + entryHandler == handler || + (entryHandler instanceof Handler.Container container && container.getDescendants().contains(this))) + throw new IllegalStateException("addMapping loop detected: " + handler); + } + + mappings.put(pathSpec, handler); + addBean(handler); + } + + @Override + public void dump(Appendable out, String indent) throws IOException + { + Dumpable.dumpObjects(out, indent, this, mappings); + } + + @Override + public Request.Processor handle(Request request) throws Exception + { + String pathInContext = request.getPathInContext(); + MatchedResource matchedResource = mappings.getMatched(pathInContext); + if (matchedResource == null) + { + if (LOG.isDebugEnabled()) + LOG.debug("No match on pathInContext of {}", pathInContext); + return null; + } + if (LOG.isDebugEnabled()) + LOG.debug("Matched pathInContext of {} to {} -> {}", pathInContext, matchedResource.getPathSpec(), matchedResource.getResource()); + return matchedResource.getResource().handle(request); + } +} diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java index 2b4e8f3ea4e..74b8b61ef25 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java @@ -60,6 +60,7 @@ import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; public class ContextHandlerTest @@ -586,6 +587,31 @@ public class ContextHandlerTest assertThat(result.get(), equalTo("OK")); } + @Test + public void testSetHandlerLoopSelf() + { + ContextHandler contextHandlerA = new ContextHandler(); + assertThrows(IllegalStateException.class, () -> contextHandlerA.setHandler(contextHandlerA)); + } + + @Test + public void testSetHandlerLoopDeepWrapper() + { + ContextHandler contextHandlerA = new ContextHandler(); + Handler.Wrapper handlerWrapper = new Handler.Wrapper(); + contextHandlerA.setHandler(handlerWrapper); + assertThrows(IllegalStateException.class, () -> handlerWrapper.setHandler(contextHandlerA)); + } + + @Test + public void testAddHandlerLoopDeep() + { + ContextHandler contextHandlerA = new ContextHandler(); + Handler.Collection handlerCollection = new Handler.Collection(); + contextHandlerA.setHandler(handlerCollection); + assertThrows(IllegalStateException.class, () -> handlerCollection.addHandler(contextHandlerA)); + } + private static class ScopeListener implements ContextHandler.ContextScopeListener { private static final Request NULL = new Request.Wrapper(null); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/PathMappingsHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/PathMappingsHandlerTest.java new file mode 100644 index 00000000000..95af61ccc32 --- /dev/null +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/PathMappingsHandlerTest.java @@ -0,0 +1,283 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.server.handler; + +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.HttpTester; +import org.eclipse.jetty.http.pathmap.ServletPathSpec; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.LocalConnector; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.Callback; +import org.eclipse.jetty.util.component.LifeCycle; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class PathMappingsHandlerTest +{ + private Server server; + private LocalConnector connector; + + public void startServer(Handler handler) throws Exception + { + server = new Server(); + connector = new LocalConnector(server); + server.addConnector(connector); + + server.addHandler(handler); + server.start(); + } + + @AfterEach + public void stopServer() + { + LifeCycle.stop(server); + } + + public HttpTester.Response executeRequest(String rawRequest) throws Exception + { + String rawResponse = connector.getResponse(rawRequest); + return HttpTester.parseResponse(rawResponse); + } + + /** + * Test where there are no mappings, and no wrapper. + */ + @Test + public void testEmpty() throws Exception + { + ContextHandler contextHandler = new ContextHandler(); + contextHandler.setContextPath("/"); + + PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(); + contextHandler.setHandler(pathMappingsHandler); + + startServer(contextHandler); + + HttpTester.Response response = executeRequest(""" + GET / HTTP/1.1\r + Host: local\r + Connection: close\r + + """); + assertEquals(HttpStatus.NOT_FOUND_404, response.getStatus()); + } + + /** + * Test where there is only a single mapping, and no wrapper. + */ + @Test + public void testOnlyMappingSuffix() throws Exception + { + ContextHandler contextHandler = new ContextHandler(); + contextHandler.setContextPath("/"); + + PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(); + pathMappingsHandler.addMapping(new ServletPathSpec("*.php"), new SimpleHandler("PhpExample Hit")); + contextHandler.setHandler(pathMappingsHandler); + + startServer(contextHandler); + + HttpTester.Response response = executeRequest(""" + GET /hello HTTP/1.1\r + Host: local\r + Connection: close\r + + """); + assertEquals(HttpStatus.NOT_FOUND_404, response.getStatus()); + + response = executeRequest(""" + GET /hello.php HTTP/1.1\r + Host: local\r + Connection: close\r + + """); + assertEquals(HttpStatus.OK_200, response.getStatus()); + assertEquals("PhpExample Hit", response.getContent()); + } + + public static Stream severalMappingsInput() + { + return Stream.of( + Arguments.of("/hello", HttpStatus.OK_200, "FakeResourceHandler Hit"), + Arguments.of("/index.html", HttpStatus.OK_200, "FakeSpecificStaticHandler Hit"), + Arguments.of("/index.php", HttpStatus.OK_200, "PhpHandler Hit"), + Arguments.of("/config.php", HttpStatus.OK_200, "PhpHandler Hit"), + Arguments.of("/css/main.css", HttpStatus.OK_200, "FakeResourceHandler Hit") + ); + } + + /** + * Test where there are a few mappings, with a root mapping, and no wrapper. + * This means the wrapper would not ever be hit, as all inputs would match at + * least 1 mapping. + */ + @ParameterizedTest + @MethodSource("severalMappingsInput") + public void testSeveralMappingAndNoWrapper(String requestPath, int expectedStatus, String expectedResponseBody) throws Exception + { + ContextHandler contextHandler = new ContextHandler(); + contextHandler.setContextPath("/"); + + PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(); + pathMappingsHandler.addMapping(new ServletPathSpec("/"), new SimpleHandler("FakeResourceHandler Hit")); + pathMappingsHandler.addMapping(new ServletPathSpec("/index.html"), new SimpleHandler("FakeSpecificStaticHandler Hit")); + pathMappingsHandler.addMapping(new ServletPathSpec("*.php"), new SimpleHandler("PhpHandler Hit")); + contextHandler.setHandler(pathMappingsHandler); + + startServer(contextHandler); + + HttpTester.Response response = executeRequest(""" + GET %s HTTP/1.1\r + Host: local\r + Connection: close\r + + """.formatted(requestPath)); + assertEquals(expectedStatus, response.getStatus()); + assertEquals(expectedResponseBody, response.getContent()); + } + + @Test + public void testDump() throws Exception + { + ContextHandler contextHandler = new ContextHandler(); + contextHandler.setContextPath("/"); + + PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(); + pathMappingsHandler.addMapping(new ServletPathSpec("/"), new SimpleHandler("FakeResourceHandler Hit")); + pathMappingsHandler.addMapping(new ServletPathSpec("/index.html"), new SimpleHandler("FakeSpecificStaticHandler Hit")); + pathMappingsHandler.addMapping(new ServletPathSpec("*.php"), new SimpleHandler("PhpHandler Hit")); + contextHandler.setHandler(pathMappingsHandler); + + startServer(contextHandler); + + String dump = contextHandler.dump(); + assertThat(dump, containsString("FakeResourceHandler")); + assertThat(dump, containsString("FakeSpecificStaticHandler")); + assertThat(dump, containsString("PhpHandler")); + assertThat(dump, containsString("PathMappings[size=3]")); + + } + + @Test + public void testGetDescendantsSimple() + { + ContextHandler contextHandler = new ContextHandler(); + contextHandler.setContextPath("/"); + + PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(); + pathMappingsHandler.addMapping(new ServletPathSpec("/"), new SimpleHandler("default")); + pathMappingsHandler.addMapping(new ServletPathSpec("/index.html"), new SimpleHandler("specific")); + pathMappingsHandler.addMapping(new ServletPathSpec("*.php"), new SimpleHandler("php")); + + List actualHandlers = pathMappingsHandler.getDescendants().stream().map(Objects::toString).toList(); + + String[] expectedHandlers = { + "SimpleHandler[msg=\"default\"]", + "SimpleHandler[msg=\"specific\"]", + "SimpleHandler[msg=\"php\"]" + }; + assertThat(actualHandlers, containsInAnyOrder(expectedHandlers)); + } + + @Test + public void testGetDescendantsDeep() + { + ContextHandler contextHandler = new ContextHandler(); + contextHandler.setContextPath("/"); + + Handler.Collection handlerCollection = new Handler.Collection(); + handlerCollection.addHandler(new SimpleHandler("phpIndex")); + Handler.Wrapper handlerWrapper = new Handler.Wrapper(new SimpleHandler("other")); + handlerCollection.addHandler(handlerWrapper); + + PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(); + pathMappingsHandler.addMapping(new ServletPathSpec("/"), new SimpleHandler("default")); + pathMappingsHandler.addMapping(new ServletPathSpec("/index.html"), new SimpleHandler("specific")); + pathMappingsHandler.addMapping(new ServletPathSpec("*.php"), handlerCollection); + + List actualHandlers = pathMappingsHandler.getDescendants().stream().map(Objects::toString).toList(); + + String[] expectedHandlers = { + "SimpleHandler[msg=\"default\"]", + "SimpleHandler[msg=\"specific\"]", + handlerCollection.toString(), + handlerWrapper.toString(), + "SimpleHandler[msg=\"phpIndex\"]", + "SimpleHandler[msg=\"other\"]" + }; + assertThat(actualHandlers, containsInAnyOrder(expectedHandlers)); + } + + @Test + public void testAddLoopSelf() + { + PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(); + assertThrows(IllegalStateException.class, () -> pathMappingsHandler.addMapping(new ServletPathSpec("/self"), pathMappingsHandler)); + } + + @Test + public void testAddLoopContext() + { + ContextHandler contextHandler = new ContextHandler(); + PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(); + contextHandler.setHandler(pathMappingsHandler); + + assertThrows(IllegalStateException.class, () -> pathMappingsHandler.addMapping(new ServletPathSpec("/loop"), contextHandler)); + } + + private static class SimpleHandler extends Handler.Processor + { + private final String message; + + public SimpleHandler(String message) + { + this.message = message; + } + + @Override + public void process(Request request, Response response, Callback callback) + { + assertTrue(isStarted()); + response.setStatus(HttpStatus.OK_200); + response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/plain; charset=utf-8"); + response.write(true, BufferUtil.toBuffer(message, StandardCharsets.UTF_8), callback); + } + + @Override + public String toString() + { + return String.format("%s[msg=\"%s\"]", SimpleHandler.class.getSimpleName(), message); + } + } +} From 97b61292ab4909c55fd1d0f393425aeb0a293f44 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 25 Oct 2022 12:01:37 -0500 Subject: [PATCH 29/42] Bump stCarolas/setup-maven to version 4.5 --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ddb9fe165ce..96fca6df909 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -71,7 +71,7 @@ jobs: # queries: security-extended,security-and-quality - name: Set up Maven - uses: stCarolas/setup-maven@v4 + uses: stCarolas/setup-maven@v4.5 with: maven-version: 3.8.6 From 9bbac09a117433f315378826ffe5e21944c6f32f Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 25 Oct 2022 13:30:50 -0500 Subject: [PATCH 30/42] Fixing version reference for node-16 - see https://github.com/stCarolas/setup-maven/issues/30 --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 96fca6df909..92e3b29728d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -71,7 +71,7 @@ jobs: # queries: security-extended,security-and-quality - name: Set up Maven - uses: stCarolas/setup-maven@v4.5 + uses: stCarolas/setup-maven@v.4.5 with: maven-version: 3.8.6 From 508e0a4484f59da57f3ebbcb98fdd13b7a0faa8a Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 25 Oct 2022 15:32:58 -0500 Subject: [PATCH 31/42] fixing compilation --- .../org/eclipse/jetty/server/handler/PathMappingsHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/PathMappingsHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/PathMappingsHandler.java index 3dffc3e3acd..54c0b8198ba 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/PathMappingsHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/PathMappingsHandler.java @@ -88,7 +88,7 @@ public class PathMappingsHandler extends Handler.AbstractContainer @Override public Request.Processor handle(Request request) throws Exception { - String pathInContext = request.getPathInContext(); + String pathInContext = Request.getPathInContext(request); MatchedResource matchedResource = mappings.getMatched(pathInContext); if (matchedResource == null) { From 6ca9c4f87884aaa9280317660ce162db758b54e9 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 27 Oct 2022 10:46:40 +0200 Subject: [PATCH 32/42] Fixed test case. Signed-off-by: Simone Bordet --- .../src/test/java/org/eclipse/jetty/http/MultiPartTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartTest.java b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartTest.java index 5d2afeb3126..a9c4de79849 100644 --- a/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartTest.java +++ b/jetty-core/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartTest.java @@ -519,6 +519,10 @@ public class MultiPartTest { byte[] random = new byte[8192]; ThreadLocalRandom.current().nextBytes(random); + // Make sure the last 2 bytes are not \r\n, + // otherwise the multipart parser gets confused. + random[random.length - 2] = 0; + random[random.length - 1] = 0; TestPartsListener listener = new TestPartsListener(); MultiPart.Parser parser = new MultiPart.Parser("BOUNDARY", listener); @@ -526,7 +530,7 @@ public class MultiPartTest String preamble = "Blah blah blah\r\n--BOUNDARY\r\n\r\n"; parser.parse(Content.Chunk.from(BufferUtil.toBuffer(preamble), false)); parser.parse(Content.Chunk.from(ByteBuffer.wrap(random), false)); - String epilogue = "\r\n--BOUNDARY\r\nBlah blah blah!\r\n"; + String epilogue = "\r\n--BOUNDARY--\r\nBlah blah blah!\r\n"; ByteBuffer epilogueBuffer = BufferUtil.toBuffer(epilogue); parser.parse(Content.Chunk.from(epilogueBuffer, true)); From 72d27249064a751694c75fe0c631bfff140af865 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 27 Oct 2022 11:40:37 +0200 Subject: [PATCH 33/42] Fixed build with Java 17+. Signed-off-by: Simone Bordet --- .../jetty-quic-quiche-foreign-incubator/pom.xml | 5 +---- jetty-core/jetty-quic/jetty-quic-quiche/pom.xml | 13 +------------ jetty-core/jetty-quic/jetty-quic-server/pom.xml | 2 +- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign-incubator/pom.xml b/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign-incubator/pom.xml index 6daadd721be..eea0a67b409 100644 --- a/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign-incubator/pom.xml +++ b/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign-incubator/pom.xml @@ -8,7 +8,7 @@ 4.0.0 jetty-quic-quiche-foreign-incubator - Jetty Core :: QUIC :: Quiche :: Foreign Binding (incubator) + Jetty Core :: QUIC :: Quiche :: Foreign (Java 17) ${project.groupId}.quic-quiche-foreign-incubator @@ -20,9 +20,6 @@ maven-compiler-plugin - 17 - 17 - 17 --add-modules jdk.incubator.foreign diff --git a/jetty-core/jetty-quic/jetty-quic-quiche/pom.xml b/jetty-core/jetty-quic/jetty-quic-quiche/pom.xml index 826848b5069..fb0165ba288 100644 --- a/jetty-core/jetty-quic/jetty-quic-quiche/pom.xml +++ b/jetty-core/jetty-quic/jetty-quic-quiche/pom.xml @@ -14,17 +14,6 @@ jetty-quic-quiche-common jetty-quic-quiche-jna + jetty-quic-quiche-foreign-incubator - - - - jdk17 - - 17 - - - jetty-quic-quiche-foreign-incubator - - - diff --git a/jetty-core/jetty-quic/jetty-quic-server/pom.xml b/jetty-core/jetty-quic/jetty-quic-server/pom.xml index 0cbaffc476a..9a999c3a530 100644 --- a/jetty-core/jetty-quic/jetty-quic-server/pom.xml +++ b/jetty-core/jetty-quic/jetty-quic-server/pom.xml @@ -42,7 +42,7 @@ jdk17 - [17,) + 17 From b39d1144ec31d0ef031c4127e98f799c65ea9ed0 Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Fri, 28 Oct 2022 06:07:25 +1000 Subject: [PATCH 34/42] limit build history to 60 Signed-off-by: Olivier Lamy --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 1e9baa18d30..37a13a4f407 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,6 +6,7 @@ pipeline { options { skipDefaultCheckout() durabilityHint('PERFORMANCE_OPTIMIZED') + buildDiscarder logRotator( numToKeepStr: '60' ) } stages { stage("Parallel Stage") { From 35af8e5c71918f84a9c552617ebdd3de2ebb21a3 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Fri, 28 Oct 2022 13:33:28 +0200 Subject: [PATCH 35/42] Fixed tests that fail when localhost resolves to more than one address. On Windows, Mac, OpenSolaris (verified) and probably Docker (did not verify, but likely), DNS resolution of "localhost" yields [127.0.0.1, ::1], while on Linux only [127.0.0.1]. HttpClient will try the first address, and in case of failure will try the second address. For those tests that want to explicitly fail the connection attempt, we don't want them to try the second address, which likely yields test failures because of unexpected results (for example, a different exception type). Signed-off-by: Simone Bordet --- .../eclipse/jetty/client/Socks4ProxyTest.java | 34 +++++++++++-------- .../proxy/ForwardProxyTLSServerTest.java | 5 +-- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java index 898836eb115..8d710cf7557 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/Socks4ProxyTest.java @@ -54,7 +54,7 @@ public class Socks4ProxyTest public void prepare() throws Exception { proxy = ServerSocketChannel.open(); - proxy.bind(new InetSocketAddress("localhost", 0)); + proxy.bind(new InetSocketAddress("127.0.0.1", 0)); ClientConnector connector = new ClientConnector(); QueuedThreadPool clientThreads = new QueuedThreadPool(); @@ -77,7 +77,7 @@ public class Socks4ProxyTest public void testSocks4Proxy() throws Exception { int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().addProxy(new Socks4Proxy("localhost", proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy("127.0.0.1", proxyPort)); CountDownLatch latch = new CountDownLatch(1); @@ -139,7 +139,7 @@ public class Socks4ProxyTest public void testSocks4ProxyWithSplitResponse() throws Exception { int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().addProxy(new Socks4Proxy("localhost", proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy("127.0.0.1", proxyPort)); CountDownLatch latch = new CountDownLatch(1); @@ -196,7 +196,6 @@ public class Socks4ProxyTest @Test public void testSocks4ProxyWithTLSServer() throws Exception { - String proxyHost = "localhost"; int proxyPort = proxy.socket().getLocalPort(); String serverHost = "127.0.0.13"; // Server host different from proxy host. @@ -215,7 +214,7 @@ public class Socks4ProxyTest // The hostname must be that of the server, not of the proxy. ssl.setHostnameVerifier((hostname, session) -> serverHost.equals(hostname)); }); - client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy("127.0.0.1", proxyPort)); CountDownLatch latch = new CountDownLatch(1); client.newRequest(serverHost, serverPort) @@ -281,12 +280,15 @@ public class Socks4ProxyTest @Test public void testRequestTimeoutWhenSocksProxyDoesNotRespond() throws Exception { - String proxyHost = "localhost"; int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy("127.0.0.1", proxyPort)); long timeout = 1000; - Request request = client.newRequest("localhost", proxyPort + 1) + + // Use an address to avoid resolution of "localhost" to multiple addresses. + String serverHost = "127.0.0.13"; + int serverPort = proxyPort + 1; // Any port will do + Request request = client.newRequest(serverHost, serverPort) .timeout(timeout, TimeUnit.MILLISECONDS); FutureResponseListener listener = new FutureResponseListener(request); request.send(listener); @@ -303,13 +305,15 @@ public class Socks4ProxyTest @Test public void testIdleTimeoutWhenSocksProxyDoesNotRespond() throws Exception { - String proxyHost = "localhost"; int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy("127.0.0.1", proxyPort)); long idleTimeout = 1000; client.setIdleTimeout(idleTimeout); - Request request = client.newRequest("localhost", proxyPort + 1); + // Use an address to avoid resolution of "localhost" to multiple addresses. + String serverHost = "127.0.0.13"; + int serverPort = proxyPort + 1; // Any port will do + Request request = client.newRequest(serverHost, serverPort); FutureResponseListener listener = new FutureResponseListener(request); request.send(listener); @@ -325,11 +329,13 @@ public class Socks4ProxyTest @Test public void testSocksProxyClosesConnectionImmediately() throws Exception { - String proxyHost = "localhost"; int proxyPort = proxy.socket().getLocalPort(); - client.getProxyConfiguration().addProxy(new Socks4Proxy(proxyHost, proxyPort)); + client.getProxyConfiguration().addProxy(new Socks4Proxy("127.0.0.1", proxyPort)); - Request request = client.newRequest("localhost", proxyPort + 1); + // Use an address to avoid resolution of "localhost" to multiple addresses. + String serverHost = "127.0.0.13"; + int serverPort = proxyPort + 1; // Any port will do + Request request = client.newRequest(serverHost, serverPort); FutureResponseListener listener = new FutureResponseListener(request); request.send(listener); diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyTLSServerTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyTLSServerTest.java index 0b25a646fef..95b7434ee30 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyTLSServerTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ForwardProxyTLSServerTest.java @@ -130,7 +130,8 @@ public class ForwardProxyTLSServerTest protected HttpProxy newHttpProxy() { - return new HttpProxy(new Origin.Address("localhost", proxyConnector.getLocalPort()), proxySslContextFactory != null); + // Use an address to avoid resolution of "localhost" to multiple addresses. + return new HttpProxy(new Origin.Address("127.0.0.1", proxyConnector.getLocalPort()), proxySslContextFactory != null); } private HttpClient newHttpClient() @@ -615,7 +616,7 @@ public class ForwardProxyTLSServerTest if (includeAddress) httpProxy.getIncludedAddresses().add("localhost:" + serverConnector.getLocalPort()); httpClient.getProxyConfiguration().addProxy(httpProxy); - URI uri = URI.create((proxySslContextFactory == null ? "http" : "https") + "://localhost:" + proxyConnector.getLocalPort()); + URI uri = URI.create((proxySslContextFactory == null ? "http" : "https") + "://127.0.0.1:" + proxyConnector.getLocalPort()); httpClient.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "proxyUser", "proxyPassword")); httpClient.start(); From dee5d14130b61afeeb756bf71f1ba0299ed26ac2 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Fri, 28 Oct 2022 10:06:52 -0500 Subject: [PATCH 36/42] Jetty 12 - Alternate `TryPathsHandler` based on `Request.Processor` existence (#8781) Now using TryPathsHandler with a PathMappingsHandler. Introduced original[Path|Query]Attribute. Signed-off-by: Simone Bordet Co-authored-by: Simone Bordet --- .../jetty/server/handler/TryPathsHandler.java | 161 +++++++++++++----- .../server/handler/TryPathsHandlerTest.java | 152 ++++++++++++++--- 2 files changed, 253 insertions(+), 60 deletions(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java index a33b08e63de..47675831199 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/TryPathsHandler.java @@ -16,36 +16,110 @@ package org.eclipse.jetty.server.handler; import java.util.List; import org.eclipse.jetty.http.HttpURI; -import org.eclipse.jetty.server.Context; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.util.URIUtil; -import org.eclipse.jetty.util.resource.Resource; /** *

Inspired by nginx's {@code try_files} functionality.

- *

This handler can be configured with a list of URI paths. - * The special token {@code $path} represents the current request URI - * path (the portion after the context path).

+ * + *

This handler can be configured with a list of rewrite URI paths. + * The special token {@code $path} represents the current request + * {@code pathInContext} (the portion after the context path).

+ * *

Typical example of how this handler can be configured is the following:

*
{@code
- * TryPathsHandler tryPaths = new TryPathsHandler();
- * tryPaths.setPaths("/maintenance.html", "$path", "/index.php?p=$path");
+ * TryPathsHandler tryPathsHandler = new TryPathsHandler();
+ * tryPathsHandler.setPaths("/maintenance.html", "$path", "/index.php?p=$path");
+ *
+ * PathMappingsHandler pathMappingsHandler = new PathMappingsHandler();
+ * tryPathsHandler.setHandler(pathMappingsHandler);
+ *
+ * pathMappingsHandler.addMapping(new ServletPathSpec("*.php"), new PHPHandler());
+ * pathMappingsHandler.addMapping(new ServletPathSpec("/"), new ResourceHandler());
  * }
- *

For a request such as {@code /context/path/to/resource.ext}, this - * handler will try to serve the {@code /maintenance.html} file if it finds - * it; failing that, it will try to serve the {@code /path/to/resource.ext} - * file if it finds it; failing that it will forward the request to - * {@code /index.php?p=/path/to/resource.ext} to the next handler.

- *

The last URI path specified in the list is therefore the "fallback" to - * which the request is forwarded to in case no previous files can be found.

- *

The file paths are resolved against {@link Context#getBaseResource()} - * to make sure that only files visible to the application are served.

+ * + *

For a request such as {@code /context/path/to/resource.ext}:

+ *
    + *
  • This handler rewrites the request {@code pathInContext} to + * {@code /maintenance.html} and forwards the request to the next handler, + * where it matches the {@code /} mapping, hitting the {@code ResourceHandler} + * that serves the file if it exists.
  • + *
  • Otherwise, this handler rewrites the request {@code pathInContext} to + * {@code /path/to/resource.ext} and forwards the request to the next handler, + * where it matches the {@code /} mapping, hitting the {@code ResourceHandler} + * that serves the file if it exists.
  • + *
  • Otherwise, this handler rewrites the request {@code pathInContext} to + * {@code /index.php?p=/path/to/resource.ext} and forwards the request to + * the next handler, where it matches the {@code *.php} mapping, hitting + * the {@code PHPHandler}.
  • + *
+ * + *

The original path and query may be stored as request attributes, + * under the names specified by {@link #setOriginalPathAttribute(String)} + * and {@link #setOriginalQueryAttribute(String)}.

*/ public class TryPathsHandler extends Handler.Wrapper { + private String originalPathAttribute; + private String originalQueryAttribute; private List paths; + /** + * @return the attribute name of the original request path + */ + public String getOriginalPathAttribute() + { + return originalPathAttribute; + } + + /** + *

Sets the request attribute name to use to + * retrieve the original request path.

+ * + * @param originalPathAttribute the attribute name of the original + * request path + */ + public void setOriginalPathAttribute(String originalPathAttribute) + { + this.originalPathAttribute = originalPathAttribute; + } + + /** + * @return the attribute name of the original request query + */ + public String getOriginalQueryAttribute() + { + return originalQueryAttribute; + } + + /** + *

Sets the request attribute name to use to + * retrieve the original request query.

+ * + * @param originalQueryAttribute the attribute name of the original + * request query + */ + public void setOriginalQueryAttribute(String originalQueryAttribute) + { + this.originalQueryAttribute = originalQueryAttribute; + } + + /** + * @return the rewrite URI paths + */ + public List getPaths() + { + return paths; + } + + /** + *

Sets a list of rewrite URI paths.

+ *

The special token {@code $path} represents the current request + * {@code pathInContext} (the portion after the context path).

+ * + * @param paths the rewrite URI paths + */ public void setPaths(List paths) { this.paths = paths; @@ -54,27 +128,15 @@ public class TryPathsHandler extends Handler.Wrapper @Override public Request.Processor handle(Request request) throws Exception { - String interpolated = interpolate(request, "$path"); - Resource rootResource = request.getContext().getBaseResource(); - if (rootResource != null) + for (String path : paths) { - for (String path : paths) - { - interpolated = interpolate(request, path); - Resource resource = rootResource.resolve(interpolated); - if (resource != null && resource.exists()) - break; - } + String interpolated = interpolate(request, path); + Request.WrapperProcessor result = new Request.WrapperProcessor(new TryPathsRequest(request, interpolated)); + Request.Processor childProcessor = super.handle(result); + if (childProcessor != null) + return result.wrapProcessor(childProcessor); } - Request.WrapperProcessor result = new Request.WrapperProcessor(new TryPathsRequest(request, interpolated)); - return result.wrapProcessor(super.handle(result)); - } - - private Request.Processor fallback(Request request) throws Exception - { - String fallback = paths.isEmpty() ? "$path" : paths.get(paths.size() - 1); - String interpolated = interpolate(request, fallback); - return super.handle(new TryPathsRequest(request, interpolated)); + return null; } private String interpolate(Request request, String value) @@ -83,14 +145,37 @@ public class TryPathsHandler extends Handler.Wrapper return value.replace("$path", path); } - private static class TryPathsRequest extends Request.Wrapper + private class TryPathsRequest extends Request.Wrapper { private final HttpURI _uri; - public TryPathsRequest(Request wrapped, String pathInContext) + public TryPathsRequest(Request wrapped, String newPathQuery) { super(wrapped); - _uri = Request.newHttpURIFrom(wrapped, URIUtil.canonicalPath(pathInContext)); + + HttpURI originalURI = wrapped.getHttpURI(); + + String originalPathAttribute = getOriginalPathAttribute(); + if (originalPathAttribute != null) + setAttribute(originalPathAttribute, Request.getPathInContext(wrapped)); + String originalQueryAttribute = getOriginalQueryAttribute(); + if (originalQueryAttribute != null) + setAttribute(originalQueryAttribute, originalURI.getQuery()); + + String originalContextPath = Request.getContextPath(wrapped); + HttpURI.Mutable rewrittenURI = HttpURI.build(originalURI); + int queryIdx = newPathQuery.indexOf('?'); + if (queryIdx >= 0) + { + String path = newPathQuery.substring(0, queryIdx); + rewrittenURI.path(URIUtil.addPaths(originalContextPath, path)); + rewrittenURI.query(newPathQuery.substring(queryIdx + 1)); + } + else + { + rewrittenURI.path(URIUtil.addPaths(originalContextPath, newPathQuery)); + } + _uri = rewrittenURI.asImmutable(); } @Override diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java index ea1d98f160c..5453689d85f 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/TryPathsHandlerTest.java @@ -22,16 +22,18 @@ import java.nio.file.StandardOpenOption; import java.util.List; import javax.net.ssl.SSLSocket; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.http.pathmap.ServletPathSpec; +import org.eclipse.jetty.io.Content; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.toolchain.test.FS; -import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.toolchain.test.jupiter.WorkDir; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.component.LifeCycle; @@ -41,18 +43,20 @@ import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.startsWith; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; public class TryPathsHandlerTest { + public WorkDir workDir; + private static final String CONTEXT_PATH = "/ctx"; private Server server; private SslContextFactory.Server sslContextFactory; private ServerConnector connector; private ServerConnector sslConnector; private Path rootPath; - private String contextPath; private void start(List paths, Handler handler) throws Exception { @@ -66,22 +70,18 @@ public class TryPathsHandlerTest sslConnector = new ServerConnector(server, 1, 1, sslContextFactory); server.addConnector(sslConnector); - contextPath = "/ctx"; - ContextHandler context = new ContextHandler(contextPath); - rootPath = Files.createDirectories(MavenTestingUtils.getTargetTestingPath(getClass().getSimpleName())); - FS.cleanDirectory(rootPath); + ContextHandler context = new ContextHandler(CONTEXT_PATH); + rootPath = workDir.getEmptyPathDir(); context.setBaseResourceAsPath(rootPath); server.setHandler(context); TryPathsHandler tryPaths = new TryPathsHandler(); context.setHandler(tryPaths); + tryPaths.setPaths(paths); + tryPaths.setHandler(handler); - ResourceHandler resourceHandler = new ResourceHandler(); - tryPaths.setHandler(resourceHandler); - - resourceHandler.setHandler(handler); - + server.setDumpAfterStart(true); server.start(); } @@ -94,47 +94,155 @@ public class TryPathsHandlerTest @Test public void testTryPaths() throws Exception { - start(List.of("/maintenance.txt", "$path", "/forward?p=$path"), new Handler.Processor() + ResourceHandler resourceHandler = new ResourceHandler(); + resourceHandler.setDirAllowed(false); + resourceHandler.setHandler(new Handler.Abstract() { @Override - public void process(Request request, Response response, Callback callback) + public Request.Processor handle(Request request) { - assertThat(Request.getPathInContext(request), equalTo("/forward%3Fp=/last")); - response.setStatus(HttpStatus.NO_CONTENT_204); - callback.succeeded(); + if (!Request.getPathInContext(request).startsWith("/forward")) + return null; + + return new Handler.Processor() + { + public void process(Request request, Response response, Callback callback) + { + assertThat(Request.getPathInContext(request), equalTo("/forward")); + assertThat(request.getHttpURI().getQuery(), equalTo("p=/last")); + response.setStatus(HttpStatus.NO_CONTENT_204); + callback.succeeded(); + } + }; } }); + start(List.of("/maintenance.txt", "$path", "/forward?p=$path"), resourceHandler); + try (SocketChannel channel = SocketChannel.open()) { channel.connect(new InetSocketAddress("localhost", connector.getLocalPort())); // Make a first request without existing file paths. HttpTester.Request request = HttpTester.newRequest(); - request.setURI(contextPath + "/last"); + request.setURI(CONTEXT_PATH + "/last"); channel.write(request.generate()); HttpTester.Response response = HttpTester.parseResponse(channel); assertNotNull(response); assertEquals(HttpStatus.NO_CONTENT_204, response.getStatus()); - // Create the specific file that is requested. + // Create the specific static file that is requested. String path = "idx.txt"; Files.writeString(rootPath.resolve(path), "hello", StandardOpenOption.CREATE); // Make a second request with the specific file. request = HttpTester.newRequest(); - request.setURI(contextPath + "/" + path); + request.setURI(CONTEXT_PATH + "/" + path); channel.write(request.generate()); response = HttpTester.parseResponse(channel); assertNotNull(response); assertEquals(HttpStatus.OK_200, response.getStatus()); assertEquals("hello", response.getContent()); + // Create the "maintenance" file, it should be served first. + path = "maintenance.txt"; + Files.writeString(rootPath.resolve(path), "maintenance", StandardOpenOption.CREATE); + // Make a third request with any path, we should get the maintenance file. + request = HttpTester.newRequest(); + request.setURI(CONTEXT_PATH + "/whatever"); + channel.write(request.generate()); + response = HttpTester.parseResponse(channel); + assertNotNull(response); + assertEquals(HttpStatus.OK_200, response.getStatus()); + assertEquals("maintenance", response.getContent()); + } + } + + @Test + public void testTryPathsWithPathMappings() throws Exception + { + ResourceHandler resourceHandler = new ResourceHandler(); + resourceHandler.setDirAllowed(false); + + PathMappingsHandler pathMappingsHandler = new PathMappingsHandler(); + pathMappingsHandler.addMapping(new ServletPathSpec("/"), resourceHandler); + pathMappingsHandler.addMapping(new ServletPathSpec("*.php"), new Handler.Abstract() + { + @Override + public Request.Processor handle(Request request) + { + return new Processor() + { + @Override + public void process(Request request, Response response, Callback callback) + { + response.setStatus(HttpStatus.OK_200); + response.getHeaders().put(HttpHeader.CONTENT_TYPE, "text/plain; charset=utf-8"); + String message = "PHP: pathInContext=%s, query=%s".formatted(Request.getPathInContext(request), request.getHttpURI().getQuery()); + Content.Sink.write(response, true, message, callback); + } + }; + } + }); + pathMappingsHandler.addMapping(new ServletPathSpec("/forward"), new Handler.Abstract() + { + @Override + public Request.Processor handle(Request request) + { + return new Handler.Processor() + { + public void process(Request request, Response response, Callback callback) + { + assertThat(Request.getPathInContext(request), equalTo("/forward")); + assertThat(request.getHttpURI().getQuery(), equalTo("p=/last")); + response.setStatus(HttpStatus.NO_CONTENT_204); + callback.succeeded(); + } + }; + } + }); + + start(List.of("/maintenance.txt", "$path", "/forward?p=$path"), pathMappingsHandler); + + try (SocketChannel channel = SocketChannel.open()) + { + channel.connect(new InetSocketAddress("localhost", connector.getLocalPort())); + + // Make a first request without existing file paths. + HttpTester.Request request = HttpTester.newRequest(); + request.setURI(CONTEXT_PATH + "/last"); + channel.write(request.generate()); + HttpTester.Response response = HttpTester.parseResponse(channel); + assertNotNull(response); + assertEquals(HttpStatus.NO_CONTENT_204, response.getStatus()); + + // Create the specific static file that is requested. + String path = "idx.txt"; + Files.writeString(rootPath.resolve(path), "hello", StandardOpenOption.CREATE); + // Make a second request with the specific file. + request = HttpTester.newRequest(); + request.setURI(CONTEXT_PATH + "/" + path); + channel.write(request.generate()); + response = HttpTester.parseResponse(channel); + assertNotNull(response); + assertEquals(HttpStatus.OK_200, response.getStatus()); + assertEquals("hello", response.getContent()); + + // Request an existing PHP file. + Files.writeString(rootPath.resolve("index.php"), "raw-php-contents", StandardOpenOption.CREATE); + request = HttpTester.newRequest(); + request.setURI(CONTEXT_PATH + "/index.php"); + channel.write(request.generate()); + response = HttpTester.parseResponse(channel); + assertNotNull(response); + assertEquals(HttpStatus.OK_200, response.getStatus()); + assertThat(response.getContent(), startsWith("PHP: pathInContext=/index.php")); + // Create the "maintenance" file, it should be served first. path = "maintenance.txt"; Files.writeString(rootPath.resolve(path), "maintenance", StandardOpenOption.CREATE); // Make a second request with any path, we should get the maintenance file. request = HttpTester.newRequest(); - request.setURI(contextPath + "/whatever"); + request.setURI(CONTEXT_PATH + "/whatever"); channel.write(request.generate()); response = HttpTester.parseResponse(channel); assertNotNull(response); @@ -165,7 +273,7 @@ public class TryPathsHandlerTest sslSocket.connect(new InetSocketAddress("localhost", sslConnector.getLocalPort())); HttpTester.Request request = HttpTester.newRequest(); - request.setURI(contextPath + path); + request.setURI(CONTEXT_PATH + path); OutputStream output = sslSocket.getOutputStream(); output.write(BufferUtil.toArray(request.generate())); output.flush(); From 336bba04c5bd0e6ab9e2f920b83378408d03507a Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 31 Oct 2022 15:15:40 +1100 Subject: [PATCH 37/42] Re-introduced JMH tests Added stream vs iterator --- tests/jetty-jmh/pom.xml | 4 - .../client/jmh/ConnectionPoolsBenchmark.java | 31 +---- .../jetty/util/PoolStrategyBenchmark.java | 2 +- .../jetty/util/StreamVsIteratorBenchmark.java | 108 ++++++++++++++++++ tests/pom.xml | 4 +- 5 files changed, 113 insertions(+), 36 deletions(-) create mode 100644 tests/jetty-jmh/src/main/java/org/eclipse/jetty/util/StreamVsIteratorBenchmark.java diff --git a/tests/jetty-jmh/pom.xml b/tests/jetty-jmh/pom.xml index 18cafe7be75..39f40b8876f 100644 --- a/tests/jetty-jmh/pom.xml +++ b/tests/jetty-jmh/pom.xml @@ -72,10 +72,6 @@ org.eclipse.jetty jetty-http
- - org.eclipse.jetty.toolchain - jetty-jakarta-servlet-api - org.slf4j slf4j-api diff --git a/tests/jetty-jmh/src/main/java/org/eclipse/jetty/client/jmh/ConnectionPoolsBenchmark.java b/tests/jetty-jmh/src/main/java/org/eclipse/jetty/client/jmh/ConnectionPoolsBenchmark.java index 942baae890f..8d1dac31d39 100644 --- a/tests/jetty-jmh/src/main/java/org/eclipse/jetty/client/jmh/ConnectionPoolsBenchmark.java +++ b/tests/jetty-jmh/src/main/java/org/eclipse/jetty/client/jmh/ConnectionPoolsBenchmark.java @@ -13,41 +13,13 @@ package org.eclipse.jetty.client.jmh; -import java.net.URI; -import java.util.ArrayList; -import java.util.concurrent.ThreadLocalRandom; - -import org.eclipse.jetty.client.ConnectionPool; -import org.eclipse.jetty.client.DuplexConnectionPool; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpConversation; -import org.eclipse.jetty.client.HttpDestination; -import org.eclipse.jetty.client.HttpExchange; -import org.eclipse.jetty.client.HttpRequest; -import org.eclipse.jetty.client.MultiplexConnectionPool; -import org.eclipse.jetty.client.Origin; -import org.eclipse.jetty.client.RoundRobinConnectionPool; -import org.eclipse.jetty.client.api.Connection; -import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.client.api.Response; -import org.eclipse.jetty.util.Attachable; -import org.eclipse.jetty.util.Callback; -import org.eclipse.jetty.util.Promise; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.TearDown; -import org.openjdk.jmh.infra.Blackhole; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; @State(Scope.Benchmark) public class ConnectionPoolsBenchmark { + /** TODO private ConnectionPool pool; @Param({"round-robin", "cached/multiplex", "uncached/multiplex", "cached/duplex", "uncached/duplex"}) @@ -166,4 +138,5 @@ public class ConnectionPoolsBenchmark return attachment; } } + **/ } diff --git a/tests/jetty-jmh/src/main/java/org/eclipse/jetty/util/PoolStrategyBenchmark.java b/tests/jetty-jmh/src/main/java/org/eclipse/jetty/util/PoolStrategyBenchmark.java index c6192f7bd05..3f6cf01a675 100644 --- a/tests/jetty-jmh/src/main/java/org/eclipse/jetty/util/PoolStrategyBenchmark.java +++ b/tests/jetty-jmh/src/main/java/org/eclipse/jetty/util/PoolStrategyBenchmark.java @@ -83,7 +83,7 @@ public class PoolStrategyBenchmark for (int i = 0; i < SIZE; i++) { - pool.reserve(1).enable(Integer.toString(i), false); + pool.reserve().enable(Integer.toString(i), false); } } diff --git a/tests/jetty-jmh/src/main/java/org/eclipse/jetty/util/StreamVsIteratorBenchmark.java b/tests/jetty-jmh/src/main/java/org/eclipse/jetty/util/StreamVsIteratorBenchmark.java new file mode 100644 index 00000000000..66134500ee7 --- /dev/null +++ b/tests/jetty-jmh/src/main/java/org/eclipse/jetty/util/StreamVsIteratorBenchmark.java @@ -0,0 +1,108 @@ +// +// ======================================================================== +// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +@Fork(value = 3) +@State(Scope.Benchmark) +@Warmup(iterations = 4, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 4, time = 1, timeUnit = TimeUnit.SECONDS) +public class StreamVsIteratorBenchmark +{ + @Param({"0", "1", "10", "100"}) + int size; + + Supplier> _iteratorSupplier; + Supplier> _streamSupplier; + + @Setup(Level.Trial) + public void setupTrial() + { + switch (size) + { + case 0 -> + { + _iteratorSupplier = Collections.emptyList()::iterator; + _streamSupplier = Stream::empty; + } + case 1 -> + { + Object item = System.nanoTime(); + _iteratorSupplier = List.of(item)::iterator; + _streamSupplier = () -> Stream.of(item); + } + default -> + { + List list = new ArrayList<>(); + for (int i = 0; i < size; i++) + list.add(System.nanoTime()); + _iteratorSupplier = list::iterator; + _streamSupplier = list::stream; + } + } + } + + @Benchmark + public long testIterator() + { + long result = 0; + for (Iterator i = _iteratorSupplier.get(); i.hasNext();) + { + Object o = i.next(); + long h = o.hashCode(); + if (h % 2 == 0) + result ^= h; + } + return result; + } + + @Benchmark + public long testStream() + { + return _streamSupplier.get().mapToLong(Objects::hashCode).filter(h -> h % 2 != 0).sum(); + } + + public static void main(String[] args) throws RunnerException + { + Options opt = new OptionsBuilder() + .include(StreamVsIteratorBenchmark.class.getSimpleName()) +// .addProfiler(GCProfiler.class) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/tests/pom.xml b/tests/pom.xml index 0068fb1e66e..f3ec63bc7ca 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -17,10 +17,10 @@ true - - + jetty-jmh test-distribution test-integration + From 47d2b062f02c6c2419b41b1b71a991b41c4c1585 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Mon, 31 Oct 2022 11:57:05 -0500 Subject: [PATCH 38/42] Jetty 12 - Fix demo-ee10 `LikeJettyXml` (and testcase) (#8771) * Remove DebugBinding config (doesn't exist anymore) * Make LikeJettyXml work (and test) --- .../src/main/config/etc/jetty-deploy.xml | 8 +- .../jetty/ee10/demos/LikeJettyXml.java | 396 ++++++++++-------- .../main/resources/demo/webdefault-ee10.xml | 8 - .../jetty/ee10/demos/LikeJettyXmlTest.java | 6 +- 4 files changed, 232 insertions(+), 186 deletions(-) diff --git a/jetty-core/jetty-deploy/src/main/config/etc/jetty-deploy.xml b/jetty-core/jetty-deploy/src/main/config/etc/jetty-deploy.xml index bf042bf2179..d35c988c4b2 100644 --- a/jetty-core/jetty-deploy/src/main/config/etc/jetty-deploy.xml +++ b/jetty-core/jetty-deploy/src/main/config/etc/jetty-deploy.xml @@ -23,13 +23,7 @@ starting customise - - - - customise - - - --> + --> diff --git a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/java/org/eclipse/jetty/ee10/demos/LikeJettyXml.java b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/java/org/eclipse/jetty/ee10/demos/LikeJettyXml.java index 5275941edd9..b1946da1d61 100644 --- a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/java/org/eclipse/jetty/ee10/demos/LikeJettyXml.java +++ b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/java/org/eclipse/jetty/ee10/demos/LikeJettyXml.java @@ -13,176 +13,240 @@ package org.eclipse.jetty.ee10.demos; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.eclipse.jetty.deploy.DeploymentManager; +import org.eclipse.jetty.deploy.providers.ContextProvider; +import org.eclipse.jetty.ee.Deployable; +import org.eclipse.jetty.ee10.annotations.AnnotationConfiguration; +import org.eclipse.jetty.ee10.plus.webapp.EnvConfiguration; +import org.eclipse.jetty.ee10.plus.webapp.PlusConfiguration; +import org.eclipse.jetty.ee10.servlet.DebugListener; +import org.eclipse.jetty.ee10.servlet.security.HashLoginService; +import org.eclipse.jetty.ee10.webapp.Configurations; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.io.ConnectionStatistics; +import org.eclipse.jetty.jmx.MBeanContainer; +import org.eclipse.jetty.rewrite.handler.InvalidURIRule; +import org.eclipse.jetty.rewrite.handler.RewriteHandler; +import org.eclipse.jetty.server.AsyncRequestLogWriter; +import org.eclipse.jetty.server.CustomRequestLog; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.LowResourceMonitor; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.StatisticsHandler; +import org.eclipse.jetty.util.component.Environment; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.util.resource.ResourceFactory; +import org.eclipse.jetty.util.resource.Resources; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; +import org.eclipse.jetty.xml.EnvironmentBuilder; +import org.slf4j.LoggerFactory; + /** * Starts the Jetty Distribution's demo-base directory using entirely * embedded jetty techniques. */ public class LikeJettyXml { - // TODO -// public static Server createServer(int port, int securePort, boolean addDebugListener) throws Exception -// { -// Path configDir = Paths.get("src/main/resources/demo").toAbsolutePath(); -// Path runtimeDir = Paths.get("target/embedded/" + LikeJettyXml.class.getSimpleName()).toAbsolutePath(); -// mkdir(runtimeDir); -// -// // === jetty.xml === -// // Setup Threadpool -// QueuedThreadPool threadPool = new QueuedThreadPool(); -// threadPool.setMaxThreads(500); -// -// // Server -// Server server = new Server(threadPool); -// -// // Scheduler -// server.addBean(new ScheduledExecutorScheduler(null, false)); -// -// // HTTP Configuration -// HttpConfiguration httpConfig = new HttpConfiguration(); -// httpConfig.setSecureScheme("https"); -// httpConfig.setSecurePort(securePort); -// httpConfig.setOutputBufferSize(32768); -// httpConfig.setRequestHeaderSize(8192); -// httpConfig.setResponseHeaderSize(8192); -// httpConfig.setSendServerVersion(true); -// httpConfig.setSendDateHeader(false); -// // httpConfig.addCustomizer(new ForwardedRequestCustomizer()); -// -// // Handler Structure -// ContextHandlerCollection contexts = new ContextHandlerCollection(); -// server.setHandler(new HandlerList(contexts, new DefaultHandler())); -// -// // === jetty-jmx.xml === -// MBeanContainer mbContainer = new MBeanContainer( -// ManagementFactory.getPlatformMBeanServer()); -// server.addBean(mbContainer); -// -// // === jetty-http.xml === -// ServerConnector http = new ServerConnector(server, -// new HttpConnectionFactory(httpConfig)); -// http.setPort(port); -// http.setIdleTimeout(30000); -// server.addConnector(http); -// -// // === jetty-https.xml === -// // SSL Context Factory -// Path keystorePath = Paths.get("src/main/resources/etc/keystore.p12").toAbsolutePath(); -// if (!Files.exists(keystorePath)) -// throw new FileNotFoundException(keystorePath.toString()); -// SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); -// sslContextFactory.setKeyStorePath(keystorePath.toString()); -// sslContextFactory.setKeyStorePassword("storepwd"); -// sslContextFactory.setTrustStorePath(keystorePath.toString()); -// sslContextFactory.setTrustStorePassword("storepwd"); -// -// // SSL HTTP Configuration -// HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig); -// httpsConfig.addCustomizer(new SecureRequestCustomizer()); -// -// // SSL Connector -// ServerConnector sslConnector = new ServerConnector(server, -// new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), -// new HttpConnectionFactory(httpsConfig)); -// sslConnector.setPort(securePort); -// server.addConnector(sslConnector); -// -// // === jetty-deploy.xml === -// DeploymentManager deployer = new DeploymentManager(); -// if (addDebugListener) -// { -// DebugListener debug = new DebugListener(System.err, true, true, true); -// server.addBean(debug); -// deployer.addLifeCycleBinding(new DebugListenerBinding(debug)); -// } -// deployer.setContexts(contexts); -// deployer.setContextAttribute( -// "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", -// ".*/jetty-jakarta-servlet-api-[^/]*\\.jar$|.*/jakarta.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$"); -// -// Path webappsDir = runtimeDir.resolve("webapps"); -// mkdir(webappsDir); -// -// Path testWebapp = webappsDir.resolve("test.war"); -// if (!Files.exists(testWebapp)) -// { -// Path testWebappSrc = JettyDemos.find("demo-simple-webapp/target/demo-simple-webapp-@VER@.war"); -// Files.copy(testWebappSrc, testWebapp); -// } -// -// WebAppProvider webAppProvider = new WebAppProvider(); -// webAppProvider.setMonitoredDirName(webappsDir.toString()); -// webAppProvider.setDefaultsDescriptor(configDir.resolve("webdefault-ee10.xml").toString()); -// webAppProvider.setScanInterval(1); -// webAppProvider.setExtractWars(true); -// webAppProvider.setConfigurationManager(new PropertiesConfigurationManager()); -// -// deployer.addAppProvider(webAppProvider); -// server.addBean(deployer); -// -// // === setup jetty plus == -// Configurations.setServerDefault(server).add(new EnvConfiguration(), new PlusConfiguration(), new AnnotationConfiguration()); -// -// // === jetty-stats.xml === -// StatisticsHandler stats = new StatisticsHandler(); -// stats.setHandler(server.getHandler()); -// server.setHandler(stats); -// server.addBeanToAllConnectors(new ConnectionStatistics()); -// -// // === Rewrite Handler -// RewriteHandler rewrite = new RewriteHandler(); -// rewrite.setHandler(server.getHandler()); -// server.setHandler(rewrite); -// rewrite.addRule(new InvalidURIRule()); -// -// // === jetty-requestlog.xml === -// Path logsDir = runtimeDir.resolve("logs"); -// mkdir(logsDir); -// AsyncRequestLogWriter logWriter = new AsyncRequestLogWriter(logsDir.resolve("yyyy_mm_dd.request.log").toString()); -// logWriter.setFilenameDateFormat("yyyy_MM_dd"); -// logWriter.setRetainDays(90); -// logWriter.setTimeZone("GMT"); -// CustomRequestLog requestLog = new CustomRequestLog(logWriter, CustomRequestLog.EXTENDED_NCSA_FORMAT + " \"%C\""); -// server.setRequestLog(requestLog); -// -// // === jetty-lowresources.xml === -// LowResourceMonitor lowResourcesMonitor = new LowResourceMonitor(server); -// lowResourcesMonitor.setPeriod(1000); -// lowResourcesMonitor.setLowResourcesIdleTimeout(200); -// lowResourcesMonitor.setMonitorThreads(true); -// lowResourcesMonitor.setMaxMemory(0); -// lowResourcesMonitor.setMaxLowResourcesTime(5000); -// server.addBean(lowResourcesMonitor); -// -// // === test-realm.xml === -// HashLoginService login = new HashLoginService(); -// login.setName("Test Realm"); -// login.setConfig(configDir.resolve("demo-realm.properties").toString()); -// login.setHotReload(false); -// server.addBean(login); -// -// return server; -// } -// -// private static void mkdir(Path path) throws IOException -// { -// if (Files.exists(path)) -// return; -// Files.createDirectories(path); -// } -// -// public static void main(String[] args) throws Exception -// { -// int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); -// int securePort = ExampleUtil.getPort(args, "jetty.https.port", 8443); -// Server server = createServer(port, securePort, true); -// -// // Extra options -// server.setDumpAfterStart(true); -// server.setDumpBeforeStop(false); -// server.setStopAtShutdown(true); -// -// // Start the server -// server.start(); -// server.join(); -// } + public static Server createServer(int port, int securePort, boolean addDebugListener) throws Exception + { + Path configDir = Path.of("src/main/resources/demo").toAbsolutePath(); + Path runtimeDir = Path.of("target/embedded/" + LikeJettyXml.class.getSimpleName()).toAbsolutePath(); + mkdir(runtimeDir); + + // === jetty.xml === + // Setup Threadpool + QueuedThreadPool threadPool = new QueuedThreadPool(); + threadPool.setMaxThreads(500); + + // Server + Server server = new Server(threadPool); + + // Scheduler + server.addBean(new ScheduledExecutorScheduler(null, false, -1)); + + // HTTP Configuration + HttpConfiguration httpConfig = new HttpConfiguration(); + httpConfig.setSecureScheme("https"); + httpConfig.setSecurePort(securePort); + httpConfig.setOutputBufferSize(32768); + httpConfig.setRequestHeaderSize(8192); + httpConfig.setResponseHeaderSize(8192); + httpConfig.setSendServerVersion(true); + httpConfig.setSendDateHeader(false); + // httpConfig.addCustomizer(new ForwardedRequestCustomizer()); + + // Handler Structure + ContextHandlerCollection contexts = new ContextHandlerCollection(); + DefaultHandler defaultHandler = new DefaultHandler(); + + Handler.Collection handlers = new Handler.Collection(); + handlers.setHandlers(contexts, defaultHandler); + server.setHandler(handlers); + + // === jetty-jmx.xml === + MBeanContainer mbContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer()); + mbContainer.beanAdded(null, LoggerFactory.getILoggerFactory()); + server.addBean(mbContainer); + + // === jetty-http.xml === + ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(httpConfig)); + http.setHost("0.0.0.0"); + http.setPort(port); + http.setIdleTimeout(30000); + server.addConnector(http); + + // === jetty-ssl-context.xml === + // SSL Context Factory + Path keystorePath = Paths.get("src/main/resources/etc/keystore.p12").toAbsolutePath(); + if (!Files.exists(keystorePath)) + throw new FileNotFoundException(keystorePath.toString()); + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); + sslContextFactory.setKeyStorePath(keystorePath.toString()); + sslContextFactory.setKeyStorePassword("storepwd"); + sslContextFactory.setTrustStorePath(keystorePath.toString()); + sslContextFactory.setTrustStorePassword("storepwd"); + + // === jetty-ssl.xml === + // SSL HTTP Configuration + HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig); + httpsConfig.addCustomizer(new SecureRequestCustomizer()); + + // === jetty-https.xml === + // SSL Connector + ServerConnector sslConnector = new ServerConnector(server, + new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), + new HttpConnectionFactory(httpsConfig)); + sslConnector.setPort(securePort); + server.addConnector(sslConnector); + + // === jetty-deploy.xml === + DeploymentManager deployer = new DeploymentManager(); + if (addDebugListener) + { + DebugListener debug = new DebugListener(System.err, true, true, true); + server.addBean(debug); + } + deployer.setContexts(contexts); + + Path webappsDir = runtimeDir.resolve("webapps"); + mkdir(webappsDir); + + Path testWebapp = webappsDir.resolve("test.war"); + if (!Files.exists(testWebapp)) + { + Path testWebappSrc = JettyDemos.find("jetty-ee10-demo-simple-webapp/target/jetty-ee10-demo-simple-webapp-@VER@.war"); + Files.copy(testWebappSrc, testWebapp); + } + + // == Build ee10 Environment == + // Support for environment specific classpath / modulepath goes here + String environmentName = "ee10"; + Environment ee10 = Environment.get(environmentName); + if (ee10 == null) + { + ee10 = new EnvironmentBuilder(environmentName).build(); + Environment.set(ee10); + } + + // === jetty-ee10-deploy.xml === + ee10.setAttribute("contextHandlerClass", org.eclipse.jetty.ee10.webapp.WebAppContext.class.getName()); + ContextProvider webAppProvider = new ContextProvider(); + webAppProvider.setEnvironmentName(environmentName); + webAppProvider.setMonitoredDirName(webappsDir.toString()); + webAppProvider.setDefaultsDescriptor(configDir.resolve("webdefault-ee10.xml").toString()); + webAppProvider.setScanInterval(1); + webAppProvider.setExtractWars(true); + webAppProvider.getProperties().put(Deployable.CONTAINER_SCAN_JARS, + ".*/jakarta.servlet-api-[^/]*\\.jar$|.*jakarta.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$"); + + deployer.addAppProvider(webAppProvider); + server.addBean(deployer); + + // === setup jetty plus == + Configurations.setServerDefault(server) + .add(new EnvConfiguration(), new PlusConfiguration(), new AnnotationConfiguration()); + + // === jetty-stats.xml === + StatisticsHandler stats = new StatisticsHandler(); + stats.setHandler(server.getHandler()); + server.setHandler(stats); + server.addBeanToAllConnectors(new ConnectionStatistics()); + + // === Rewrite Handler + RewriteHandler rewrite = new RewriteHandler(); + rewrite.setHandler(server.getHandler()); + server.setHandler(rewrite); + rewrite.addRule(new InvalidURIRule()); + + // === jetty-requestlog.xml === + Path logsDir = runtimeDir.resolve("logs"); + mkdir(logsDir); + AsyncRequestLogWriter logWriter = new AsyncRequestLogWriter(logsDir.resolve("yyyy_mm_dd.request.log").toString()); + logWriter.setFilenameDateFormat("yyyy_MM_dd"); + logWriter.setRetainDays(90); + logWriter.setTimeZone("GMT"); + CustomRequestLog requestLog = new CustomRequestLog(logWriter, CustomRequestLog.EXTENDED_NCSA_FORMAT + " \"%C\""); + server.setRequestLog(requestLog); + + // === jetty-lowresources.xml === + LowResourceMonitor lowResourcesMonitor = new LowResourceMonitor(server); + lowResourcesMonitor.setPeriod(1000); + lowResourcesMonitor.setLowResourcesIdleTimeout(200); + lowResourcesMonitor.setMonitorThreads(true); + lowResourcesMonitor.setMaxMemory(0); + lowResourcesMonitor.setMaxLowResourcesTime(5000); + server.addBean(lowResourcesMonitor); + + // === Realm === + HashLoginService login = new HashLoginService(); + login.setName("Test Realm"); + Path realmFile = configDir.resolve("ee10-demo-realm.properties"); + Resource realmResource = ResourceFactory.of(server).newResource(realmFile); + if (!Resources.isReadableFile(realmResource)) + throw new FileNotFoundException("Unable to find config: " + realmFile); + login.setConfig(realmResource); + login.setHotReload(false); + server.addBean(login); + + return server; + } + + private static void mkdir(Path path) throws IOException + { + if (Files.exists(path)) + return; + Files.createDirectories(path); + } + + public static void main(String[] args) throws Exception + { + int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); + int securePort = ExampleUtil.getPort(args, "jetty.https.port", 8443); + Server server = createServer(port, securePort, true); + + // Extra options + server.setDumpAfterStart(true); + server.setDumpBeforeStop(false); + server.setStopAtShutdown(true); + + // Start the server + server.start(); + server.join(); + } } diff --git a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/resources/demo/webdefault-ee10.xml b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/resources/demo/webdefault-ee10.xml index ce3e9359124..94b79c2bdd3 100644 --- a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/resources/demo/webdefault-ee10.xml +++ b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/main/resources/demo/webdefault-ee10.xml @@ -29,14 +29,6 @@ This file is applied to a Web application before its own WEB_INF/web.xml file - - - - - - org.eclipse.jetty.ee10.servlet.listener.ELContextCleaner - - diff --git a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/LikeJettyXmlTest.java b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/LikeJettyXmlTest.java index ec4b615eb05..dabbcc3dff1 100644 --- a/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/LikeJettyXmlTest.java +++ b/jetty-ee10/jetty-ee10-demos/jetty-ee10-demo-embedded/src/test/java/org/eclipse/jetty/ee10/demos/LikeJettyXmlTest.java @@ -23,7 +23,6 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.component.LifeCycle; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; @@ -39,8 +38,7 @@ public class LikeJettyXmlTest extends AbstractEmbeddedTest @BeforeEach public void startServer() throws Exception { - //TODO fix me - //server = LikeJettyXml.createServer(0, 0, false); + server = LikeJettyXml.createServer(0, 0, false); server.start(); Map ports = ServerUtil.fixDynamicPortConfigurations(server); @@ -57,7 +55,6 @@ public class LikeJettyXmlTest extends AbstractEmbeddedTest LifeCycle.stop(server); } - @Disabled //TODO @Test public void testGetTest() throws Exception { @@ -74,7 +71,6 @@ public class LikeJettyXmlTest extends AbstractEmbeddedTest assertThat("Response Content", responseBody, containsString("Hello")); } - @Disabled //TODO @Test public void testGetTestSsl() throws Exception { From 4225054b6269af30ba099dea666e684f3433d0b5 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 1 Nov 2022 11:16:57 +1100 Subject: [PATCH 39/42] Improve comments --- .../org/eclipse/jetty/server/handler/ContextHandler.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index ec91a81c036..5cf3ff98339 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -639,11 +639,16 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Grace if (contextRequest == null) return null; + // Does this handler want to process the request itself? Request.Processor processor = processByContextHandler(contextRequest); if (processor != null) return processor; - return contextRequest.wrapProcessor(_context.get(contextRequest, contextRequest)); + // The contextRequest is-a Supplier that calls effectively calls getHandler().handle(request). + // Call this supplier in the scope of the context. + Request.Processor contextScopedProcessor = _context.get(contextRequest, contextRequest); + // Wrap the contextScopedProcessor with a wrapper that uses the wrapped request + return contextRequest.wrapProcessor(contextScopedProcessor); } protected void processMovedPermanently(Request request, Response response, Callback callback) From 976ab3df8dbc869683db66ea63d2966426495938 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 1 Nov 2022 15:54:50 +1100 Subject: [PATCH 40/42] ResourceCollection should not have a path (#8711) ResourceCollection should not have a path Nor name, nor filename unless all resources agree on it. revert combine and related methods to return Resource and not explicitly a ResourceCollection, as if there is only 1, then a collection is not needed cleanup ResourceCollection creation. Avoid sanity checks on resolved resources. --- .../util/resource}/AttributeNormalizer.java | 221 ++++----- ...eCollection.java => CombinedResource.java} | 158 ++---- .../eclipse/jetty/util/resource/Resource.java | 21 +- .../jetty/util/resource/ResourceFactory.java | 22 +- .../resource}/AttributeNormalizerTest.java | 121 +++-- ...AttributeNormalizerToCanonicalUriTest.java | 2 +- ...ionTest.java => CombinedResourceTest.java} | 26 +- .../plugin/MavenQuickStartConfiguration.java | 6 +- .../ee10/maven/plugin/MavenWebAppContext.java | 4 +- .../maven/plugin/WebAppPropertyConverter.java | 6 +- .../plugin/TestWebAppPropertyConverter.java | 13 +- .../ee10/quickstart/AttributeNormalizer.java | 469 ------------------ .../QuickStartDescriptorProcessor.java | 1 + .../QuickStartGeneratorConfiguration.java | 1 + .../quickstart/AttributeNormalizerTest.java | 347 ------------- ...AttributeNormalizerToCanonicalUriTest.java | 64 --- .../ee10/webapp/MetaInfConfiguration.java | 4 - .../jetty/ee10/webapp/WebAppClassLoader.java | 34 +- .../jetty/ee10/webapp/WebAppContext.java | 16 +- .../plugin/MavenQuickStartConfiguration.java | 6 +- .../ee9/maven/plugin/MavenWebAppContext.java | 4 +- .../maven/plugin/WebAppPropertyConverter.java | 6 +- .../plugin/TestWebAppPropertyConverter.java | 8 +- .../QuickStartDescriptorProcessor.java | 1 + .../QuickStartGeneratorConfiguration.java | 1 + .../ee9/webapp/MetaInfConfiguration.java | 2 - .../jetty/ee9/webapp/WebAppClassLoader.java | 36 +- .../jetty/ee9/webapp/WebAppContext.java | 16 +- 28 files changed, 360 insertions(+), 1256 deletions(-) rename {jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart => jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource}/AttributeNormalizer.java (70%) rename jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/{ResourceCollection.java => CombinedResource.java} (66%) rename {jetty-ee9/jetty-ee9-tests/jetty-ee9-test-quickstart/src/test/java/org/eclipse/jetty/ee9/quickstart => jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource}/AttributeNormalizerTest.java (73%) rename {jetty-ee9/jetty-ee9-tests/jetty-ee9-test-quickstart/src/test/java/org/eclipse/jetty/ee9/quickstart => jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource}/AttributeNormalizerToCanonicalUriTest.java (98%) rename jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/{ResourceCollectionTest.java => CombinedResourceTest.java} (94%) delete mode 100644 jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizer.java delete mode 100644 jetty-ee10/jetty-ee10-tests/jetty-ee10-test-quickstart/src/test/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizerTest.java delete mode 100644 jetty-ee10/jetty-ee10-tests/jetty-ee10-test-quickstart/src/test/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizerToCanonicalUriTest.java diff --git a/jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/AttributeNormalizer.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/AttributeNormalizer.java similarity index 70% rename from jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/AttributeNormalizer.java rename to jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/AttributeNormalizer.java index ee84abce54c..2b6371a1b60 100644 --- a/jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/AttributeNormalizer.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/AttributeNormalizer.java @@ -11,7 +11,7 @@ // ======================================================================== // -package org.eclipse.jetty.ee9.quickstart; +package org.eclipse.jetty.util.resource; import java.io.File; import java.io.IOException; @@ -22,18 +22,15 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; +import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Stack; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.util.resource.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -165,81 +162,79 @@ public class AttributeNormalizer } } - private static Comparator attrComparator = new Comparator() + private static final Comparator attrComparator = (o1, o2) -> { - @Override - public int compare(Attribute o1, Attribute o2) + if ((o1.value == null) && (o2.value != null)) { - if ((o1.value == null) && (o2.value != null)) - { - return -1; - } - - if ((o1.value != null) && (o2.value == null)) - { - return 1; - } - - if ((o1.value == null) && (o2.value == null)) - { - return 0; - } - - // Different lengths? - int diff = o2.value.length() - o1.value.length(); - if (diff != 0) - { - return diff; - } - - // Different names? - diff = o2.value.compareTo(o1.value); - if (diff != 0) - { - return diff; - } - - // The paths are the same, base now on weight - return o2.weight - o1.weight; + return -1; } + + if ((o1.value != null) && (o2.value == null)) + { + return 1; + } + + if (o1.value == null) + { + return 0; + } + + // Different lengths? + int diff = o2.value.length() - o1.value.length(); + if (diff != 0) + { + return diff; + } + + // Different names? + diff = o2.value.compareTo(o1.value); + if (diff != 0) + { + return diff; + } + + // The paths are the same, base now on weight + return o2.weight - o1.weight; }; - private URI warURI; - private Map attributes = new HashMap<>(); - private List paths = new ArrayList<>(); - private List uris = new ArrayList<>(); + private final List paths = new ArrayList<>(); + private final List uris = new ArrayList<>(); public AttributeNormalizer(Resource baseResource) { if (baseResource == null) throw new IllegalArgumentException("No base resource!"); - warURI = toCanonicalURI(baseResource.getURI()); - if (!warURI.isAbsolute()) - throw new IllegalArgumentException("WAR URI is not absolute: " + warURI); - addSystemProperty("jetty.base", 9); addSystemProperty("jetty.home", 8); addSystemProperty("user.home", 7); addSystemProperty("user.dir", 6); - if (warURI.getScheme().equalsIgnoreCase("file")) - paths.add(new PathAttribute("WAR.path", toCanonicalPath(new File(warURI).toString()), 10)); - uris.add(new URIAttribute("WAR.uri", warURI, 9)); // preferred encoding - uris.add(new URIAttribute("WAR", warURI, 8)); // legacy encoding + Set rootPaths = new HashSet<>(); + for (Resource r : baseResource) + { + if (r instanceof MountedPathResource mpr && rootPaths.contains(mpr.getContainerPath())) + return; - Collections.sort(paths, attrComparator); - Collections.sort(uris, attrComparator); + URI warURI = toCanonicalURI(r.getURI()); + if (!warURI.isAbsolute()) + throw new IllegalArgumentException("WAR URI is not absolute: " + warURI); - Stream.concat(paths.stream(), uris.stream()).forEach(a -> attributes.put(a.key, a)); + Path path = r.getPath(); + if (path != null) + { + rootPaths.add(path); + paths.add(new PathAttribute("WAR.path", toCanonicalPath(path), 10)); + } + uris.add(new URIAttribute("WAR.uri", warURI, 9)); // preferred encoding + uris.add(new URIAttribute("WAR", warURI, 8)); // legacy encoding + } + + paths.sort(attrComparator); + uris.sort(attrComparator); if (LOG.isDebugEnabled()) - { - for (Attribute attr : attributes.values()) - { - LOG.debug(attr.toString()); - } - } + Stream.concat(paths.stream(), uris.stream()).map(Object::toString).forEach(LOG::debug); } private void addSystemProperty(String key, int weight) @@ -352,7 +347,7 @@ public class AttributeNormalizer return String.format("${%s}", a.key); String s = uPath.substring(aPath.length()); - if (s.length() > 0 && s.charAt(0) != '/') + if (s.charAt(0) != '/') continue; return String.format("${%s}%s", a.key, s); @@ -375,95 +370,79 @@ public class AttributeNormalizer } if (path.startsWith(a.path)) - return String.format("${%s}%c%s", a.key, File.separatorChar, a.path.relativize(path).toString()); + return String.format("${%s}%c%s", a.key, File.separatorChar, a.path.relativize(path)); } return path.toString(); } public String expand(String str) - { - return expand(str, new Stack()); - } - - public String expand(String str, Stack seenStack) { if (str == null) { return str; } - if (str.indexOf("${") < 0) + if (!str.contains("${")) { // Contains no potential expressions. return str; } Matcher mat = __propertyPattern.matcher(str); - StringBuilder expanded = new StringBuilder(); - int offset = 0; - String property; - String value; - while (mat.find(offset)) + if (mat.find(0)) { - property = mat.group(1); - - // Loop detection - if (seenStack.contains(property)) - { - StringBuilder err = new StringBuilder(); - err.append("Property expansion loop detected: "); - int idx = seenStack.lastIndexOf(property); - for (int i = idx; i < seenStack.size(); i++) - { - err.append(seenStack.get(i)); - err.append(" -> "); - } - err.append(property); - throw new RuntimeException(err.toString()); - } - - seenStack.push(property); - - // find property name - expanded.append(str.subSequence(offset, mat.start())); - // get property value - value = getString(property); - if (value == null) - { - if (LOG.isDebugEnabled()) - LOG.debug("Unable to expand: {}", property); - expanded.append(mat.group()); - } - else - { - // recursively expand - value = expand(value, seenStack); - expanded.append(value); - } - // update offset - offset = mat.end(); + String prefix = str.substring(0, mat.start()); + String property = mat.group(1); + String suffix = str.substring(mat.end()); + str = expand(prefix, property, suffix); } - // leftover - expanded.append(str.substring(offset)); - - return StringUtil.replace(expanded.toString(), "$$", "$"); + return StringUtil.replace(str, "$$", "$"); } - private String getString(String property) + private String expand(String prefix, String property, String suffix) { if (property == null) - { return null; + + for (URIAttribute attr : uris) + { + if (property.equals(attr.key)) + { + try + { + String uri = prefix + attr.value + suffix; + Resource resource = ResourceFactory.root().newResource(uri); + if (resource.exists()) + return uri; + } + catch (Exception ex) + { + if (LOG.isDebugEnabled()) + LOG.trace("ignored", ex); + } + } } - Attribute a = attributes.get(property); - if (a != null) - return a.value; + for (PathAttribute attr : paths) + { + if (property.equals(attr.key)) + { + String path = prefix + attr.value + suffix; + if (Files.exists(Path.of(path))) + return path; + } + } // Use system properties next - return System.getProperty(property); + String system = System.getProperty(property); + if (system != null) + return prefix + system + suffix; + + String unexpanded = prefix + "${" + property + "}" + suffix; + LOG.warn("Cannot expand: {}", unexpanded); + return unexpanded; } } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceCollection.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/CombinedResource.java similarity index 66% rename from jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceCollection.java rename to jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/CombinedResource.java index dcd8147b986..896f18fbe3b 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceCollection.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/CombinedResource.java @@ -13,11 +13,8 @@ package org.eclipse.jetty.util.resource; -import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; import java.net.URI; -import java.nio.channels.ReadableByteChannel; import java.nio.file.Path; import java.time.Instant; import java.util.ArrayList; @@ -30,32 +27,34 @@ import java.util.stream.Collectors; import org.eclipse.jetty.util.URIUtil; /** - * A collection of Resources. - * Allows webapps to have multiple sources. - * The first resource in the collection is the main resource. - * If a resource is not found in the main resource, it looks it up in - * the order the provided in the constructors + * Multiple resource directories presented as a single Resource. */ -public class ResourceCollection extends Resource +public class CombinedResource extends Resource { - private final List _resources; - /** - * Instantiates a new resource collection. - * - * @param resources the resources to be added to collection + *

Make a Resource containing a combination of other resources

+ * @param resources multiple resources to combine as a single resource. Typically, they are directories. + * @return A Resource of multiple resources or a single resource if only 1 is passed, or null if none are passed + * @see CombinedResource */ - ResourceCollection(List resources) + static Resource combine(List resources) { - List res = new ArrayList<>(); - gatherUniqueFlatResourceList(res, resources); - _resources = Collections.unmodifiableList(res); + resources = CombinedResource.gatherUniqueFlatResourceList(resources); + + if (resources == null || resources.isEmpty()) + return null; + if (resources.size() == 1) + return resources.get(0); + + return new CombinedResource(resources); } - private static void gatherUniqueFlatResourceList(List unique, List resources) + static List gatherUniqueFlatResourceList(List resources) { if (resources == null || resources.isEmpty()) - throw new IllegalArgumentException("Empty Resource collection"); + return null; + + List unique = new ArrayList<>(resources.size()); for (Resource r : resources) { @@ -64,9 +63,9 @@ public class ResourceCollection extends Resource throw new IllegalArgumentException("Null Resource entry encountered"); } - if (r instanceof ResourceCollection resourceCollection) + if (r instanceof CombinedResource resourceCollection) { - gatherUniqueFlatResourceList(unique, resourceCollection.getResources()); + unique.addAll(gatherUniqueFlatResourceList(resourceCollection.getResources())); } else { @@ -89,6 +88,19 @@ public class ResourceCollection extends Resource unique.add(r); } } + return unique; + } + + private final List _resources; + + /** + * Instantiates a new resource collection. + * + * @param resources the resources to be added to collection + */ + CombinedResource(List resources) + { + _resources = Collections.unmodifiableList(resources); } /** @@ -127,127 +139,67 @@ public class ResourceCollection extends Resource ArrayList resources = null; // Attempt a simple (single) Resource lookup that exists - Resource addedResource = null; + Resource resolved = null; for (Resource res : _resources) { - addedResource = res.resolve(subUriPath); - if (Resources.missing(addedResource)) + resolved = res.resolve(subUriPath); + if (Resources.missing(resolved)) continue; // skip, doesn't exist - if (!addedResource.isDirectory()) - return addedResource; // Return simple (non-directory) Resource + if (!resolved.isDirectory()) + return resolved; // Return simple (non-directory) Resource if (resources == null) resources = new ArrayList<>(); - resources.add(addedResource); + resources.add(resolved); } if (resources == null) - return addedResource; // This will not exist + return resolved; // This will not exist if (resources.size() == 1) return resources.get(0); - return new ResourceCollection(resources); + return new CombinedResource(resources); } @Override public boolean exists() { - for (Resource r : _resources) - { - if (r.exists()) - { - return true; - } - } - - return false; + return _resources.stream().anyMatch(Resource::exists); } @Override public Path getPath() { - for (Resource r : _resources) - { - Path p = r.getPath(); - if (p != null) - return p; - } - return null; - } - - @Override - public InputStream newInputStream() throws IOException - { - for (Resource r : _resources) - { - if (!r.exists()) - { - // Skip, cannot open anyway - continue; - } - InputStream is = r.newInputStream(); - if (is != null) - { - return is; - } - } - - throw new FileNotFoundException("Resource does not exist"); - } - - @Override - public ReadableByteChannel newReadableByteChannel() throws IOException - { - for (Resource r : _resources) - { - ReadableByteChannel channel = r.newReadableByteChannel(); - if (channel != null) - { - return channel; - } - } return null; } @Override public String getName() { - for (Resource r : _resources) - { - String name = r.getName(); - if (name != null) - { - return name; - } - } return null; } @Override public String getFileName() { + String filename = null; + // return a non-null filename only if all resources agree on the same name. for (Resource r : _resources) { - String filename = r.getFileName(); - if (filename != null) - { - return filename; - } + String fn = r.getFileName(); + if (fn == null) + return null; + if (filename == null) + filename = fn; + else if (!filename.equals(fn)) + return null; } - return null; + return filename; } @Override public URI getURI() { - for (Resource r : _resources) - { - URI uri = r.getURI(); - if (uri != null) - { - return uri; - } - } return null; } @@ -326,7 +278,7 @@ public class ResourceCollection extends Resource return true; if (o == null || getClass() != o.getClass()) return false; - ResourceCollection other = (ResourceCollection)o; + CombinedResource other = (CombinedResource)o; return Objects.equals(_resources, other._resources); } @@ -343,7 +295,7 @@ public class ResourceCollection extends Resource public String toString() { return _resources.stream() - .map(Resource::getName) + .map(Resource::toString) .collect(Collectors.joining(", ", "[", "]")); } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java index 793bc1d4c45..302ef729241 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java @@ -113,11 +113,8 @@ public abstract class Resource implements Iterable public abstract boolean isContainedIn(Resource r); /** - * Return an Iterator of all Resource's referenced in this Resource. - * - *

- * This is meaningful if you have a Composite Resource, otherwise it will be a single entry Iterator. - *

+ *

Return an Iterator of all Resource's referenced in this Resource.

+ *

This is meaningful if you have a Composite Resource, otherwise it will be a single entry Iterator of this resource.

* * @return the iterator of Resources. */ @@ -198,22 +195,28 @@ public abstract class Resource implements Iterable /** * Creates a new input stream to the resource. * - * @return an input stream to the resource - * @throws IOException if unable to open the input stream + * @return an input stream to the resource or null if one is not available. + * @throws IOException if there is a problem opening the input stream */ public InputStream newInputStream() throws IOException { - return Files.newInputStream(getPath(), StandardOpenOption.READ); + Path path = getPath(); + if (path == null) + return null; + return Files.newInputStream(path, StandardOpenOption.READ); } /** * Readable ByteChannel for the resource. * - * @return an readable bytechannel to the resource or null if one is not available. + * @return a readable {@link java.nio.channels.ByteChannel} to the resource or null if one is not available. * @throws IOException if unable to open the readable bytechannel for the resource. */ public ReadableByteChannel newReadableByteChannel() throws IOException { + Path path = getPath(); + if (path == null) + return null; return Files.newByteChannel(getPath(), StandardOpenOption.READ); } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceFactory.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceFactory.java index 4de67898aa6..cf6f6acb2f7 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceFactory.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceFactory.java @@ -35,27 +35,23 @@ public interface ResourceFactory /** *

Make a Resource containing a collection of other resources

* @param resources multiple resources to combine as a single resource. Typically, they are directories. - * @return A Resource of multiple resources. - * @see ResourceCollection + * @return A Resource of multiple resources or a single resource if only 1 is passed, or null if none are passed + * @see CombinedResource */ - static ResourceCollection combine(List resources) + static Resource combine(List resources) { - if (resources == null || resources.isEmpty()) - throw new IllegalArgumentException("No resources"); - return new ResourceCollection(resources); + return CombinedResource.combine(resources); } /** *

Make a Resource containing a collection of other resources

* @param resources multiple resources to combine as a single resource. Typically, they are directories. * @return A Resource of multiple resources. - * @see ResourceCollection + * @see CombinedResource */ - static ResourceCollection combine(Resource... resources) + static Resource combine(Resource... resources) { - if (resources == null || resources.length == 0) - throw new IllegalArgumentException("No resources"); - return new ResourceCollection(List.of(resources)); + return CombinedResource.combine(List.of(resources)); } /** @@ -203,12 +199,12 @@ public interface ResourceFactory } /** - * Construct a ResourceCollection from a list of URIs + * Construct a possible {@link CombinedResource} from a list of URIs * * @param uris the URIs * @return the Resource for the provided path */ - default ResourceCollection newResource(List uris) + default Resource newResource(List uris) { if ((uris == null) || (uris.isEmpty())) throw new IllegalArgumentException("List of URIs is invalid"); diff --git a/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-quickstart/src/test/java/org/eclipse/jetty/ee9/quickstart/AttributeNormalizerTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AttributeNormalizerTest.java similarity index 73% rename from jetty-ee9/jetty-ee9-tests/jetty-ee9-test-quickstart/src/test/java/org/eclipse/jetty/ee9/quickstart/AttributeNormalizerTest.java rename to jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AttributeNormalizerTest.java index 8141d834d9f..e55a3b517b4 100644 --- a/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-quickstart/src/test/java/org/eclipse/jetty/ee9/quickstart/AttributeNormalizerTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AttributeNormalizerTest.java @@ -11,8 +11,9 @@ // ======================================================================== // -package org.eclipse.jetty.ee9.quickstart; +package org.eclipse.jetty.util.resource; +import java.io.IOException; import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; @@ -26,11 +27,9 @@ import java.util.stream.Stream; import org.eclipse.jetty.toolchain.test.FS; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.IO; -import org.eclipse.jetty.util.resource.FileSystemPool; -import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceFactory; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -43,7 +42,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class AttributeNormalizerTest { - public static Stream scenarios() + public static Stream scenarios() throws IOException { final List data = new ArrayList<>(); final String arch = String.format("%s/%s", System.getProperty("os.name"), System.getProperty("os.arch")); @@ -55,18 +54,22 @@ public class AttributeNormalizerTest // ------ title = "Typical Setup"; - jettyHome = asTargetPath(title, "jetty-distro"); - jettyBase = asTargetPath(title, "jetty-distro/demo.base"); - war = asTargetPath(title, "jetty-distro/demo.base/webapps/FOO"); - data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, war))); + jettyHome = asTargetPath(title, "jetty-typical"); + jettyBase = asTargetPath(title, "jetty-typical/demo.base"); + war = asTargetPath(title, "jetty-typical/demo.base/webapps/FOO"); + data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, resourceFactory.newResource(war)))); // ------ title = "Old Setup"; - jettyHome = asTargetPath(title, "jetty-distro"); - jettyBase = asTargetPath(title, "jetty-distro"); - war = asTargetPath(title, "jetty-distro/webapps/FOO"); - - data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, war))); + jettyHome = asTargetPath(title, "jetty-old"); + jettyBase = asTargetPath(title, "jetty-old"); + war = asTargetPath(title, "jetty-old/webapps/FOO"); + if (!Files.exists(war.resolve("index.html"))) + { + Files.createFile(war.resolve("index.html")); + Files.createFile(war.resolve("favicon.ico")); + } + data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, resourceFactory.newResource(war)))); // ------ // This puts the jetty.home inside the jetty.base @@ -74,8 +77,7 @@ public class AttributeNormalizerTest jettyHome = asTargetPath(title, "app/dist"); jettyBase = asTargetPath(title, "app"); war = asTargetPath(title, "app/webapps/FOO"); - - data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, war))); + data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, resourceFactory.newResource(war)))); // ------ // This tests a path scenario often seen on various automatic deployments tooling @@ -84,8 +86,16 @@ public class AttributeNormalizerTest jettyHome = asTargetPath(title, "app%2Fnasty/dist"); jettyBase = asTargetPath(title, "app%2Fnasty/base"); war = asTargetPath(title, "app%2Fnasty/base/webapps/FOO"); + data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, resourceFactory.newResource(war)))); - data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, war))); + // ------ + title = "ResourceCollection Setup"; + jettyHome = asTargetPath(title, "jetty-collection"); + jettyBase = asTargetPath(title, "jetty-collection/demo.base"); + Path warA = asTargetPath(title, "jetty-collection/demo.base/webapps/WarA"); + Path warB = asTargetPath(title, "jetty-collection/demo.base/webapps/WarB"); + data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, + ResourceFactory.combine(resourceFactory.newResource(warA), resourceFactory.newResource(warB))))); return data.stream(); } @@ -166,7 +176,9 @@ public class AttributeNormalizerTest public void testNormalizeWarAsString(final Scenario scenario) { // Normalize WAR as String path - assertNormalize(scenario, scenario.war.toString(), scenario.war.toString()); + Path path = scenario.war.getPath(); + Assumptions.assumeTrue(path != null); + assertNormalize(scenario, path.toString(), path.toString()); } @ParameterizedTest @@ -259,12 +271,22 @@ public class AttributeNormalizerTest assertExpandPath(scenario, "${jetty.home}", scenario.jettyHome.toString()); } + @ParameterizedTest + @MethodSource("scenarios") + public void testExpandWebInfAsURI(final Scenario scenario) + { + // Expand + assertExpandURI(scenario, "${WAR.uri}/WEB-INF/web.xml", scenario.webXml.toUri()); + assertExpandURI(scenario, "${WAR.uri}/WEB-INF/test.tld", scenario.testTld.toUri()); + } + @ParameterizedTest @MethodSource("scenarios") public void testNormalizeWarAsURI(final Scenario scenario) { // Normalize WAR as URI - URI testWarURI = scenario.war.toUri(); + URI testWarURI = scenario.war.getURI(); + Assumptions.assumeTrue(testWarURI != null); assertNormalize(scenario, testWarURI, "${WAR.uri}"); } @@ -273,7 +295,7 @@ public class AttributeNormalizerTest public void testNormalizeWarDeepAsPath(final Scenario scenario) { // Normalize WAR deep path as File - Path testWarDeep = scenario.war.resolve("deep/ref"); + Path testWarDeep = scenario.war.resolve("deep/ref").getPath(); assertNormalize(scenario, testWarDeep, "${WAR.path}" + FS.separators("/deep/ref")); } @@ -282,7 +304,7 @@ public class AttributeNormalizerTest public void testNormalizeWarDeepAsString(final Scenario scenario) { // Normalize WAR deep path as String - Path testWarDeep = scenario.war.resolve("deep/ref"); + Path testWarDeep = scenario.war.resolve("deep/ref").getPath(); assertNormalize(scenario, testWarDeep.toString(), testWarDeep.toString()); } @@ -291,30 +313,22 @@ public class AttributeNormalizerTest public void testNormalizeWarDeepAsURI(final Scenario scenario) { // Normalize WAR deep path as URI - Path testWarDeep = scenario.war.resolve("deep/ref"); + Path testWarDeep = scenario.war.resolve("deep/ref").getPath(); assertNormalize(scenario, testWarDeep.toUri(), "${WAR.uri}/deep/ref"); } - @ParameterizedTest - @MethodSource("scenarios") - public void testExpandWarDeep(final Scenario scenario) - { - // Expand WAR deep path - Path testWarDeep = scenario.war.resolve("deep/ref"); - URI uri = URI.create("jar:" + testWarDeep.toUri().toASCIIString() + "!/other/file"); - assertExpandURI(scenario, "jar:${WAR.uri}/deep/ref!/other/file", uri); - } - public static class Scenario { private final Path jettyHome; private final Path jettyBase; - private final Path war; + private final Resource war; + private Path webXml; + private Path testTld; private final String arch; private final String title; private final AttributeNormalizer normalizer; - public Scenario(String arch, String title, Path jettyHome, Path jettyBase, Path war) + public Scenario(String arch, String title, Path jettyHome, Path jettyBase, Resource war) { this.arch = arch; this.title = title; @@ -326,15 +340,48 @@ public class AttributeNormalizerTest assertTrue(Files.exists(this.jettyHome)); assertTrue(Files.exists(this.jettyBase)); - assertTrue(Files.exists(this.war)); + assertTrue(war.exists()); // Set some System Properties that AttributeNormalizer expects System.setProperty("jetty.home", jettyHome.toString()); System.setProperty("jetty.base", jettyBase.toString()); + for (Resource w : war) + { + try + { + Path webinf = w.getPath().resolve("WEB-INF"); + if (!Files.exists(webinf)) + Files.createDirectory(webinf); + Path deep = w.getPath().resolve("deep"); + if (!Files.exists(deep)) + Files.createDirectory(deep); + Path ref = deep.resolve("ref"); + if (!Files.exists(ref)) + Files.createFile(ref); + + if (w.getFileName().equals("FOO") || w.getFileName().equals("WarA")) + { + webXml = webinf.resolve("web.xml"); + if (!Files.exists(webXml)) + Files.createFile(webXml); + } + + if (w.getFileName().equals("FOO") || w.getFileName().equals("WarB")) + { + testTld = webinf.resolve("test.tld"); + if (!Files.exists(testTld)) + Files.createFile(testTld); + } + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + // Setup normalizer - Resource webresource = resourceFactory.newResource(war); - this.normalizer = new AttributeNormalizer(webresource); + this.normalizer = new AttributeNormalizer(war); } @Override diff --git a/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-quickstart/src/test/java/org/eclipse/jetty/ee9/quickstart/AttributeNormalizerToCanonicalUriTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AttributeNormalizerToCanonicalUriTest.java similarity index 98% rename from jetty-ee9/jetty-ee9-tests/jetty-ee9-test-quickstart/src/test/java/org/eclipse/jetty/ee9/quickstart/AttributeNormalizerToCanonicalUriTest.java rename to jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AttributeNormalizerToCanonicalUriTest.java index 7bc22821469..b912a9382b1 100644 --- a/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-quickstart/src/test/java/org/eclipse/jetty/ee9/quickstart/AttributeNormalizerToCanonicalUriTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AttributeNormalizerToCanonicalUriTest.java @@ -11,7 +11,7 @@ // ======================================================================== // -package org.eclipse.jetty.ee9.quickstart; +package org.eclipse.jetty.util.resource; import java.net.URI; import java.util.ArrayList; diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceCollectionTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/CombinedResourceTest.java similarity index 94% rename from jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceCollectionTest.java rename to jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/CombinedResourceTest.java index b1f8db60a73..00317fcdb18 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceCollectionTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/CombinedResourceTest.java @@ -52,7 +52,7 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @ExtendWith(WorkDirExtension.class) -public class ResourceCollectionTest +public class CombinedResourceTest { private final ResourceFactory.Closeable resourceFactory = ResourceFactory.closeable(); public WorkDir workDir; @@ -78,7 +78,7 @@ public class ResourceCollectionTest Path two = MavenTestingUtils.getTestResourcePathDir("org/eclipse/jetty/util/resource/two"); Path three = MavenTestingUtils.getTestResourcePathDir("org/eclipse/jetty/util/resource/three"); - ResourceCollection rc = ResourceFactory.combine( + Resource rc = ResourceFactory.combine( resourceFactory.newResource(one), resourceFactory.newResource(two), resourceFactory.newResource(three) @@ -127,7 +127,7 @@ public class ResourceCollectionTest Path two = MavenTestingUtils.getTestResourcePathDir("org/eclipse/jetty/util/resource/two"); Path three = MavenTestingUtils.getTestResourcePathDir("org/eclipse/jetty/util/resource/three"); - ResourceCollection rc = ResourceFactory.combine( + Resource rc = ResourceFactory.combine( resourceFactory.newResource(one), resourceFactory.newResource(two), resourceFactory.newResource(three) @@ -135,8 +135,8 @@ public class ResourceCollectionTest // This should return a ResourceCollection with 3 `/dir/` sub-directories. Resource r = rc.resolve("dir"); - assertTrue(r instanceof ResourceCollection); - rc = (ResourceCollection)r; + assertTrue(r instanceof CombinedResource); + rc = (CombinedResource)r; assertEquals(getContent(rc, "1.txt"), "1 - one (in dir)"); assertEquals(getContent(rc, "2.txt"), "2 - two (in dir)"); assertEquals(getContent(rc, "3.txt"), "3 - three (in dir)"); @@ -149,7 +149,7 @@ public class ResourceCollectionTest Path two = MavenTestingUtils.getTestResourcePathDir("org/eclipse/jetty/util/resource/two"); Path three = MavenTestingUtils.getTestResourcePathDir("org/eclipse/jetty/util/resource/three"); - ResourceCollection rc = ResourceFactory.combine( + Resource rc = ResourceFactory.combine( resourceFactory.newResource(one), resourceFactory.newResource(two), resourceFactory.newResource(three) @@ -175,7 +175,7 @@ public class ResourceCollectionTest Path three = MavenTestingUtils.getTestResourcePathDir("org/eclipse/jetty/util/resource/three"); Path twoDir = MavenTestingUtils.getTestResourcePathDir("org/eclipse/jetty/util/resource/two/dir"); - ResourceCollection rc1 = ResourceFactory.combine( + Resource rc1 = ResourceFactory.combine( List.of( resourceFactory.newResource(one), resourceFactory.newResource(two), @@ -183,7 +183,7 @@ public class ResourceCollectionTest ) ); - ResourceCollection rc2 = ResourceFactory.combine( + Resource rc2 = ResourceFactory.combine( List.of( // the original ResourceCollection rc1, @@ -202,9 +202,11 @@ public class ResourceCollectionTest }; List actual = new ArrayList<>(); - for (Resource res: rc2.getResources()) + assertThat(rc2, instanceOf(CombinedResource.class)); + if (rc2 instanceof CombinedResource combinedResource) { - actual.add(res.getURI()); + for (Resource res : combinedResource.getResources()) + actual.add(res.getURI()); } assertThat(actual, contains(expected)); } @@ -307,7 +309,7 @@ public class ResourceCollectionTest // Since this is user space, we cannot know ahead of time what // this list contains, so we mount because we assume there // will be necessary things to mount - ResourceCollection rc = resourceFactory.newResource(uris); + Resource rc = resourceFactory.newResource(uris); assertThat(getContent(rc, "test.txt"), is("Test")); } @@ -333,7 +335,7 @@ public class ResourceCollectionTest // Since this is user space, we cannot know ahead of time what // this list contains, so we mount because we assume there // will be necessary things to mount - ResourceCollection rc = resourceFactory.newResource(uris); + Resource rc = resourceFactory.newResource(uris); assertThat(getContent(rc, "test.txt"), is("Test inside lib-foo.jar")); assertThat(getContent(rc, "testZed.txt"), is("TestZed inside lib-zed.jar")); } diff --git a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/MavenQuickStartConfiguration.java b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/MavenQuickStartConfiguration.java index aaa93f70a6f..cb9b915875b 100644 --- a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/MavenQuickStartConfiguration.java +++ b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/MavenQuickStartConfiguration.java @@ -17,8 +17,8 @@ import org.eclipse.jetty.ee10.quickstart.QuickStartConfiguration; import org.eclipse.jetty.ee10.webapp.Configuration; import org.eclipse.jetty.ee10.webapp.WebAppContext; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.resource.CombinedResource; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,9 +47,9 @@ public class MavenQuickStartConfiguration extends QuickStartConfiguration //Iterate over all of the resource bases and ignore any that were original bases, just //deleting the overlays Resource res = context.getBaseResource(); - if (res instanceof ResourceCollection) + if (res instanceof CombinedResource) { - for (Resource r : ((ResourceCollection)res).getResources()) + for (Resource r : ((CombinedResource)res).getResources()) { if (originalBaseStr.contains(r.toString())) continue; diff --git a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/MavenWebAppContext.java b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/MavenWebAppContext.java index b09cc2c3794..bcacad2afbd 100644 --- a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/MavenWebAppContext.java +++ b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/MavenWebAppContext.java @@ -39,8 +39,8 @@ import org.eclipse.jetty.ee10.webapp.WebAppContext; import org.eclipse.jetty.util.FileID; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.resource.CombinedResource; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.util.resource.Resources; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -218,7 +218,7 @@ public class MavenWebAppContext extends WebAppContext * configuration * * @param resourceBases Array of resources strings to set as a - * {@link ResourceCollection}. + * {@link CombinedResource}. */ public void setResourceBases(String[] resourceBases) { diff --git a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/WebAppPropertyConverter.java b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/WebAppPropertyConverter.java index 4da6dfdb23b..76befee379f 100644 --- a/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/WebAppPropertyConverter.java +++ b/jetty-ee10/jetty-ee10-maven-plugin/src/main/java/org/eclipse/jetty/ee10/maven/plugin/WebAppPropertyConverter.java @@ -30,8 +30,8 @@ import org.eclipse.jetty.ee10.quickstart.QuickStartConfiguration; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.resource.CombinedResource; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.xml.XmlConfiguration; /** @@ -106,8 +106,8 @@ public class WebAppPropertyConverter //send over the calculated resource bases that includes unpacked overlays Resource baseResource = webApp.getBaseResource(); - if (baseResource instanceof ResourceCollection) - props.put(BASE_DIRS, toCSV(((ResourceCollection)webApp.getBaseResource()).getResources())); + if (baseResource instanceof CombinedResource) + props.put(BASE_DIRS, toCSV(((CombinedResource)webApp.getBaseResource()).getResources())); else if (baseResource instanceof Resource) props.put(BASE_DIRS, webApp.getBaseResource().toString()); diff --git a/jetty-ee10/jetty-ee10-maven-plugin/src/test/java/org/eclipse/jetty/ee10/maven/plugin/TestWebAppPropertyConverter.java b/jetty-ee10/jetty-ee10-maven-plugin/src/test/java/org/eclipse/jetty/ee10/maven/plugin/TestWebAppPropertyConverter.java index e5f0c6016fd..6930cfc9ea7 100644 --- a/jetty-ee10/jetty-ee10-maven-plugin/src/test/java/org/eclipse/jetty/ee10/maven/plugin/TestWebAppPropertyConverter.java +++ b/jetty-ee10/jetty-ee10-maven-plugin/src/test/java/org/eclipse/jetty/ee10/maven/plugin/TestWebAppPropertyConverter.java @@ -16,17 +16,17 @@ package org.eclipse.jetty.ee10.maven.plugin; import java.io.File; import java.io.FileInputStream; import java.net.URI; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Objects; import java.util.Properties; import org.eclipse.jetty.ee10.webapp.WebAppContext; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.resource.CombinedResource; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.hamcrest.Matchers; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -152,10 +152,13 @@ public class TestWebAppPropertyConverter assertEquals(true, webApp.isPersistTempDirectory()); assertEquals(war.getAbsolutePath(), webApp.getWar()); assertEquals(webXml.getAbsolutePath(), webApp.getDescriptor()); - assertThat(webApp.getBaseResource(), instanceOf(ResourceCollection.class)); + assertThat(webApp.getBaseResource(), instanceOf(CombinedResource.class)); - ResourceCollection resourceCollection = (ResourceCollection)webApp.getBaseResource(); - List actual = resourceCollection.getResources().stream().filter(Objects::nonNull).map(Resource::getURI).toList(); + Resource combinedResource = webApp.getBaseResource(); + List actual = new ArrayList<>(); + for (Resource r : combinedResource) + if (r != null) + actual.add(r.getURI()); URI[] expected = new URI[]{base1.toURI(), base2.toURI()}; assertThat(actual, containsInAnyOrder(expected)); } diff --git a/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizer.java b/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizer.java deleted file mode 100644 index 05763019cec..00000000000 --- a/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizer.java +++ /dev/null @@ -1,469 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License v. 2.0 which is available at -// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// ======================================================================== -// - -package org.eclipse.jetty.ee10.quickstart; - -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Stack; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.util.resource.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Normalize Attribute to String. - *

- * Replaces and expands: - *

    - *
  • ${WAR}
  • - *
  • ${WAR.path}
  • - *
  • ${WAR.uri}
  • - *
  • ${jetty.base}
  • - *
  • ${jetty.base.uri}
  • - *
  • ${jetty.home}
  • - *
  • ${jetty.home.uri}
  • - *
  • ${user.home}
  • - *
  • ${user.home.uri}
  • - *
  • ${user.dir}
  • - *
  • ${user.dir.uri}
  • - *
- */ -public class AttributeNormalizer -{ - private static final Logger LOG = LoggerFactory.getLogger(AttributeNormalizer.class); - private static final Pattern __propertyPattern = Pattern.compile("(?<=[^$]|^)\\$\\{([^}]*)\\}"); - - private static class Attribute - { - final String key; - final String value; - final int weight; - - public Attribute(String key, String value, int weight) - { - this.key = key; - this.value = value; - this.weight = weight; - } - } - - public static URI toCanonicalURI(URI uri) - { - uri = uri.normalize(); - String path = uri.getPath(); - if (path != null && path.length() > 1 && path.endsWith("/")) - { - try - { - String ascii = uri.toASCIIString(); - uri = new URI(ascii.substring(0, ascii.length() - 1)); - } - catch (URISyntaxException e) - { - throw new IllegalArgumentException(e); - } - } - return uri; - } - - public static String toCanonicalURI(String uri) - { - if (uri != null && uri.length() > 1 && uri.endsWith("/")) - { - return uri.substring(0, uri.length() - 1); - } - return uri; - } - - public static Path toCanonicalPath(String path) - { - if (path == null) - return null; - if (path.length() > 1 && path.endsWith("/")) - path = path.substring(0, path.length() - 1); - return toCanonicalPath(FileSystems.getDefault().getPath(path)); - } - - private static Path toCanonicalPath(Path path) - { - if (path == null) - { - return null; - } - if (Files.exists(path)) - { - try - { - return path.toRealPath(); - } - catch (IOException e) - { - throw new IllegalArgumentException(e); - } - } - return path.toAbsolutePath(); - } - - private static class PathAttribute extends Attribute - { - public final Path path; - - public PathAttribute(String key, Path path, int weight) - { - super(key, path.toString(), weight); - this.path = path; - } - - @Override - public String toString() - { - return String.format("PathAttribute[%s=>%s]", key, path); - } - } - - private static class URIAttribute extends Attribute - { - public final URI uri; - - public URIAttribute(String key, URI uri, int weight) - { - super(key, toCanonicalURI(uri.toASCIIString()), weight); - this.uri = toCanonicalURI(uri); - } - - @Override - public String toString() - { - return String.format("URIAttribute[%s=>%s]", key, uri); - } - } - - private static Comparator attrComparator = new Comparator() - { - @Override - public int compare(Attribute o1, Attribute o2) - { - if ((o1.value == null) && (o2.value != null)) - { - return -1; - } - - if ((o1.value != null) && (o2.value == null)) - { - return 1; - } - - if ((o1.value == null) && (o2.value == null)) - { - return 0; - } - - // Different lengths? - int diff = o2.value.length() - o1.value.length(); - if (diff != 0) - { - return diff; - } - - // Different names? - diff = o2.value.compareTo(o1.value); - if (diff != 0) - { - return diff; - } - - // The paths are the same, base now on weight - return o2.weight - o1.weight; - } - }; - - private URI warURI; - private Map attributes = new HashMap<>(); - private List paths = new ArrayList<>(); - private List uris = new ArrayList<>(); - - public AttributeNormalizer(Resource baseResource) - { - if (baseResource == null) - throw new IllegalArgumentException("No base resource!"); - - warURI = toCanonicalURI(baseResource.getURI()); - if (!warURI.isAbsolute()) - throw new IllegalArgumentException("WAR URI is not absolute: " + warURI); - - addSystemProperty("jetty.base", 9); - addSystemProperty("jetty.home", 8); - addSystemProperty("user.home", 7); - addSystemProperty("user.dir", 6); - - if (warURI.getScheme().equalsIgnoreCase("file")) - paths.add(new PathAttribute("WAR.path", toCanonicalPath(new File(warURI).toString()), 10)); - uris.add(new URIAttribute("WAR.uri", warURI, 9)); // preferred encoding - uris.add(new URIAttribute("WAR", warURI, 8)); // legacy encoding - - Collections.sort(paths, attrComparator); - Collections.sort(uris, attrComparator); - - Stream.concat(paths.stream(), uris.stream()).forEach(a -> attributes.put(a.key, a)); - - if (LOG.isDebugEnabled()) - { - for (Attribute attr : attributes.values()) - { - LOG.debug(attr.toString()); - } - } - } - - private void addSystemProperty(String key, int weight) - { - String value = System.getProperty(key); - if (value != null) - { - Path path = toCanonicalPath(value); - paths.add(new PathAttribute(key, path, weight)); - uris.add(new URIAttribute(key + ".uri", path.toUri(), weight)); - } - } - - /** - * Normalize a URI, URL, or File reference by replacing known attributes with ${key} attributes. - * - * @param o the object to normalize into a string - * @return the string representation of the object, with expansion keys. - */ - public String normalize(Object o) - { - try - { - // Find a URI - URI uri = null; - Path path = null; - if (o instanceof URI) - uri = toCanonicalURI(((URI)o)); - else if (o instanceof Resource) - uri = toCanonicalURI(((Resource)o).getURI()); - else if (o instanceof URL) - uri = toCanonicalURI(((URL)o).toURI()); - else if (o instanceof File) - path = ((File)o).getAbsoluteFile().getCanonicalFile().toPath(); - else if (o instanceof Path) - path = (Path)o; - else - { - String s = o.toString(); - try - { - uri = new URI(s); - if (uri.getScheme() == null) - { - // Unknown scheme? not relevant to normalize - return s; - } - } - catch (URISyntaxException e) - { - // This path occurs for many reasons, but most common is when this - // is executed on MS Windows, on a string like "D:\jetty" - // and the new URI() fails for - // java.net.URISyntaxException: Illegal character in opaque part at index 2: D:\jetty - return s; - } - } - - if (uri != null) - { - if ("jar".equalsIgnoreCase(uri.getScheme())) - { - String raw = uri.getRawSchemeSpecificPart(); - int bang = raw.indexOf("!/"); - String normal = normalize(raw.substring(0, bang)); - String suffix = raw.substring(bang); - return "jar:" + normal + suffix; - } - else - { - if (uri.isAbsolute()) - { - return normalizeUri(uri); - } - } - } - else if (path != null) - return normalizePath(path); - } - catch (Exception e) - { - LOG.warn("Failed to normalize {}", o, e); - } - return String.valueOf(o); - } - - protected String normalizeUri(URI uri) - { - for (URIAttribute a : uris) - { - if (uri.compareTo(a.uri) == 0) - return String.format("${%s}", a.key); - - if (!a.uri.getScheme().equalsIgnoreCase(uri.getScheme())) - continue; - if (a.uri.getHost() == null && uri.getHost() != null) - continue; - if (a.uri.getHost() != null && !a.uri.getHost().equals(uri.getHost())) - continue; - - String aPath = a.uri.getPath(); - String uPath = uri.getPath(); - if (aPath.equals(uPath)) - return a.value; - - if (!uPath.startsWith(aPath)) - continue; - - if (uPath.length() == aPath.length()) - return String.format("${%s}", a.key); - - String s = uPath.substring(aPath.length()); - if (s.length() > 0 && s.charAt(0) != '/') - continue; - - return String.format("${%s}%s", a.key, s); - } - return uri.toASCIIString(); - } - - protected String normalizePath(Path path) - { - for (PathAttribute a : paths) - { - try - { - if (path.equals(a.path) || Files.isSameFile(path, a.path)) - return String.format("${%s}", a.key); - } - catch (IOException ignore) - { - LOG.trace("IGNORED", ignore); - } - - if (path.startsWith(a.path)) - return String.format("${%s}%c%s", a.key, File.separatorChar, a.path.relativize(path).toString()); - } - - return path.toString(); - } - - public String expand(String str) - { - return expand(str, new Stack()); - } - - public String expand(String str, Stack seenStack) - { - if (str == null) - { - return str; - } - - if (str.indexOf("${") < 0) - { - // Contains no potential expressions. - return str; - } - - Matcher mat = __propertyPattern.matcher(str); - StringBuilder expanded = new StringBuilder(); - int offset = 0; - String property; - String value; - - while (mat.find(offset)) - { - property = mat.group(1); - - // Loop detection - if (seenStack.contains(property)) - { - StringBuilder err = new StringBuilder(); - err.append("Property expansion loop detected: "); - int idx = seenStack.lastIndexOf(property); - for (int i = idx; i < seenStack.size(); i++) - { - err.append(seenStack.get(i)); - err.append(" -> "); - } - err.append(property); - throw new RuntimeException(err.toString()); - } - - seenStack.push(property); - - // find property name - expanded.append(str.subSequence(offset, mat.start())); - // get property value - value = getString(property); - if (value == null) - { - if (LOG.isDebugEnabled()) - LOG.debug("Unable to expand: {}", property); - expanded.append(mat.group()); - } - else - { - // recursively expand - value = expand(value, seenStack); - expanded.append(value); - } - // update offset - offset = mat.end(); - } - - // leftover - expanded.append(str.substring(offset)); - - return StringUtil.replace(expanded.toString(), "$$", "$"); - } - - private String getString(String property) - { - if (property == null) - { - return null; - } - - Attribute a = attributes.get(property); - if (a != null) - return a.value; - - // Use system properties next - return System.getProperty(property); - } -} diff --git a/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/QuickStartDescriptorProcessor.java b/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/QuickStartDescriptorProcessor.java index 8c372797778..8f562885461 100644 --- a/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/QuickStartDescriptorProcessor.java +++ b/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/QuickStartDescriptorProcessor.java @@ -33,6 +33,7 @@ import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.resource.AttributeNormalizer; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.ResourceFactory; import org.eclipse.jetty.util.resource.Resources; diff --git a/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/QuickStartGeneratorConfiguration.java b/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/QuickStartGeneratorConfiguration.java index 3363e35c6b1..67ece78fb29 100644 --- a/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/QuickStartGeneratorConfiguration.java +++ b/jetty-ee10/jetty-ee10-quickstart/src/main/java/org/eclipse/jetty/ee10/quickstart/QuickStartGeneratorConfiguration.java @@ -57,6 +57,7 @@ import org.eclipse.jetty.ee10.webapp.WebInfConfiguration; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.resource.AttributeNormalizer; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.xml.XmlAppendable; import org.slf4j.Logger; diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-quickstart/src/test/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizerTest.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-quickstart/src/test/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizerTest.java deleted file mode 100644 index 57df1579765..00000000000 --- a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-quickstart/src/test/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizerTest.java +++ /dev/null @@ -1,347 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License v. 2.0 which is available at -// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// ======================================================================== -// - -package org.eclipse.jetty.ee10.quickstart; - -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Stream; - -import org.eclipse.jetty.toolchain.test.FS; -import org.eclipse.jetty.toolchain.test.MavenTestingUtils; -import org.eclipse.jetty.util.IO; -import org.eclipse.jetty.util.resource.FileSystemPool; -import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceFactory; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.is; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class AttributeNormalizerTest -{ - public static Stream scenarios() - { - final List data = new ArrayList<>(); - final String arch = String.format("%s/%s", System.getProperty("os.name"), System.getProperty("os.arch")); - - String title; - Path jettyHome; - Path jettyBase; - Path war; - - // ------ - title = "Typical Setup"; - jettyHome = asTargetPath(title, "jetty-distro"); - jettyBase = asTargetPath(title, "jetty-distro/demo.base"); - war = asTargetPath(title, "jetty-distro/demo.base/webapps/FOO"); - data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, war))); - - // ------ - title = "Old Setup"; - jettyHome = asTargetPath(title, "jetty-distro"); - jettyBase = asTargetPath(title, "jetty-distro"); - war = asTargetPath(title, "jetty-distro/webapps/FOO"); - - data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, war))); - - // ------ - // This puts the jetty.home inside the jetty.base - title = "Overlap Setup"; - jettyHome = asTargetPath(title, "app/dist"); - jettyBase = asTargetPath(title, "app"); - war = asTargetPath(title, "app/webapps/FOO"); - - data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, war))); - - // ------ - // This tests a path scenario often seen on various automatic deployments tooling - // such as Kubernetes, CircleCI, TravisCI, and Jenkins. - title = "Nasty Path Setup"; - jettyHome = asTargetPath(title, "app%2Fnasty/dist"); - jettyBase = asTargetPath(title, "app%2Fnasty/base"); - war = asTargetPath(title, "app%2Fnasty/base/webapps/FOO"); - - data.add(Arguments.of(new Scenario(arch, title, jettyHome, jettyBase, war))); - - return data.stream(); - } - - private static Path asTargetPath(String title, String subpath) - { - Path rootPath = MavenTestingUtils.getTargetTestingPath(title); - FS.ensureDirExists(rootPath); - Path path = rootPath.resolve(FS.separators(subpath)); - FS.ensureDirExists(path); - - return path; - } - - private static final Map originalEnv = new HashMap<>(); - private static ResourceFactory.Closeable resourceFactory; - - @BeforeAll - public static void rememberOriginalEnv() - { - assertThat(FileSystemPool.INSTANCE.mounts(), empty()); - resourceFactory = ResourceFactory.closeable(); - System.getProperties().stringPropertyNames() - .forEach((name) -> originalEnv.put(name, System.getProperty(name))); - } - - @AfterAll - public static void afterAll() - { - IO.close(resourceFactory); - assertThat(FileSystemPool.INSTANCE.mounts(), empty()); - } - - @AfterEach - public void restoreOriginalEnv() - { - originalEnv.forEach(AttributeNormalizerTest::restoreSystemProperty); - } - - private static void restoreSystemProperty(String key, String value) - { - if (value == null) - { - System.clearProperty(key); - } - else - { - System.setProperty(key, value); - } - } - - private void assertNormalize(final Scenario scenario, Object o, String expected) - { - String result = scenario.normalizer.normalize(o); - assertThat("normalize((" + o.getClass().getSimpleName() + ") " + Objects.toString(o, "") + ")", - result, is(expected)); - } - - private void assertExpandPath(final Scenario scenario, String line, String expected) - { - String result = scenario.normalizer.expand(line); - - // Treat output as strings - assertThat("expand('" + line + "')", result, is(expected)); - } - - private void assertExpandURI(final Scenario scenario, String line, URI expected) - { - String result = scenario.normalizer.expand(line); - - URI resultURI = URI.create(result); - assertThat("expand('" + line + "')", resultURI.getScheme(), is(expected.getScheme())); - assertThat("expand('" + line + "')", resultURI.getPath(), is(expected.getPath())); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeWarAsString(final Scenario scenario) - { - // Normalize WAR as String path - assertNormalize(scenario, scenario.war.toString(), scenario.war.toString()); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeJettyBaseAsFile(final Scenario scenario) - { - // Normalize jetty.base as File path - assertNormalize(scenario, scenario.jettyBase.toFile(), "${jetty.base}"); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeJettyHomeAsFile(final Scenario scenario) - { - // Normalize jetty.home as File path - String expected = scenario.jettyBase.equals(scenario.jettyHome) ? "${jetty.base}" : "${jetty.home}"; - assertNormalize(scenario, scenario.jettyHome.toFile(), expected); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeJettyBaseAsPath(final Scenario scenario) - { - // Normalize jetty.base as File path - assertNormalize(scenario, scenario.jettyBase, "${jetty.base}"); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeJettyHomeAsPath(final Scenario scenario) - { - // Normalize jetty.home as File path - String expected = scenario.jettyBase.equals(scenario.jettyHome) ? "${jetty.base}" : "${jetty.home}"; - assertNormalize(scenario, scenario.jettyHome, expected); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeJettyBaseAsURIWithAuthority(final Scenario scenario) - { - // Normalize jetty.base as URI path - // Path.toUri() typically includes an URI authority - assertNormalize(scenario, scenario.jettyBase.toUri(), "${jetty.base.uri}"); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeJettyBaseAsURIWithoutAuthority(final Scenario scenario) - { - // Normalize jetty.base as URI path - // File.toURI() typically DOES NOT include an URI authority - assertNormalize(scenario, scenario.jettyBase.toFile().toURI(), "${jetty.base.uri}"); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeJettyHomeAsURIWithAuthority(final Scenario scenario) - { - // Normalize jetty.home as URI path - String expected = scenario.jettyBase.equals(scenario.jettyHome) ? "${jetty.base.uri}" : "${jetty.home.uri}"; - - // Path.toUri() typically includes an URI authority - assertNormalize(scenario, scenario.jettyHome.toUri(), expected); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeJettyHomeAsURIWithoutAuthority(final Scenario scenario) - { - // Normalize jetty.home as URI path - String expected = scenario.jettyBase.equals(scenario.jettyHome) ? "${jetty.base.uri}" : "${jetty.home.uri}"; - - // File.toURI() typically DOES NOT include an URI authority - assertNormalize(scenario, scenario.jettyHome.toFile().toURI(), expected); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testExpandJettyBase(final Scenario scenario) - { - // Expand jetty.base - assertExpandPath(scenario, "${jetty.base}", scenario.jettyBase.toString()); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testExpandJettyHome(final Scenario scenario) - { - // Expand jetty.home - assertExpandPath(scenario, "${jetty.home}", scenario.jettyHome.toString()); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeWarAsURI(final Scenario scenario) - { - // Normalize WAR as URI - URI testWarURI = scenario.war.toUri(); - assertNormalize(scenario, testWarURI, "${WAR.uri}"); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeWarDeepAsPath(final Scenario scenario) - { - // Normalize WAR deep path as File - Path testWarDeep = scenario.war.resolve("deep/ref"); - assertNormalize(scenario, testWarDeep, "${WAR.path}" + FS.separators("/deep/ref")); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeWarDeepAsString(final Scenario scenario) - { - // Normalize WAR deep path as String - Path testWarDeep = scenario.war.resolve("deep/ref"); - assertNormalize(scenario, testWarDeep.toString(), testWarDeep.toString()); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testNormalizeWarDeepAsURI(final Scenario scenario) - { - // Normalize WAR deep path as URI - Path testWarDeep = scenario.war.resolve("deep/ref"); - assertNormalize(scenario, testWarDeep.toUri(), "${WAR.uri}/deep/ref"); - } - - @ParameterizedTest - @MethodSource("scenarios") - public void testExpandWarDeep(final Scenario scenario) - { - // Expand WAR deep path - Path testWarDeep = scenario.war.resolve("deep/ref"); - URI uri = URI.create("jar:" + testWarDeep.toUri().toASCIIString() + "!/other/file"); - assertExpandURI(scenario, "jar:${WAR.uri}/deep/ref!/other/file", uri); - } - - public static class Scenario - { - private final Path jettyHome; - private final Path jettyBase; - private final Path war; - private final String arch; - private final String title; - private final AttributeNormalizer normalizer; - - public Scenario(String arch, String title, Path jettyHome, Path jettyBase, Path war) - { - this.arch = arch; - this.title = title; - - // Grab specific values of interest in general - this.jettyHome = jettyHome; - this.jettyBase = jettyBase; - this.war = war; - - assertTrue(Files.exists(this.jettyHome)); - assertTrue(Files.exists(this.jettyBase)); - assertTrue(Files.exists(this.war)); - - // Set some System Properties that AttributeNormalizer expects - System.setProperty("jetty.home", jettyHome.toString()); - System.setProperty("jetty.base", jettyBase.toString()); - - // Setup normalizer - Resource webresource = resourceFactory.newResource(war); - this.normalizer = new AttributeNormalizer(webresource); - } - - @Override - public String toString() - { - return String.format("%s [%s]", this.title, this.arch); - } - } -} - diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-quickstart/src/test/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizerToCanonicalUriTest.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-quickstart/src/test/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizerToCanonicalUriTest.java deleted file mode 100644 index 4d9662de7e4..00000000000 --- a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-quickstart/src/test/java/org/eclipse/jetty/ee10/quickstart/AttributeNormalizerToCanonicalUriTest.java +++ /dev/null @@ -1,64 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others. -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License v. 2.0 which is available at -// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// ======================================================================== -// - -package org.eclipse.jetty.ee10.quickstart; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Stream; - -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; - -public class AttributeNormalizerToCanonicalUriTest -{ - public static Stream sampleUris() - { - List data = new ArrayList<>(); - - // root without authority - data.add(new String[]{"file:/", "file:/"}); - data.add(new String[]{"file:/F:/", "file:/F:"}); - - // root with empty authority - data.add(new String[]{"file:///", "file:///"}); - data.add(new String[]{"file:///F:/", "file:///F:"}); - - // deep directory - no authority - data.add(new String[]{"file:/home/user/code/", "file:/home/user/code"}); - data.add(new String[]{"file:/C:/code/", "file:/C:/code"}); - - // deep directory - with authority - data.add(new String[]{"file:///home/user/code/", "file:///home/user/code"}); - data.add(new String[]{"file:///C:/code/", "file:///C:/code"}); - - // Some non-file tests - data.add(new String[]{"http://webtide.com/", "http://webtide.com/"}); - data.add(new String[]{"http://webtide.com/cometd/", "http://webtide.com/cometd"}); - - return data.stream(); - } - - @ParameterizedTest - @MethodSource("sampleUris") - public void testCanonicalURI(String input, String expected) - { - URI inputURI = URI.create(input); - URI actual = AttributeNormalizer.toCanonicalURI(inputURI); - assertThat(input, actual.toASCIIString(), is(expected)); - } -} diff --git a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/MetaInfConfiguration.java b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/MetaInfConfiguration.java index 5dc17949452..3033e09b211 100644 --- a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/MetaInfConfiguration.java +++ b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/MetaInfConfiguration.java @@ -723,16 +723,13 @@ public class MetaInfConfiguration extends AbstractConfiguration * * @param context the context to find extra classpath jars in * @return the list of Resources with the extra classpath, or null if not found - * @throws Exception if unable to resolve the extra classpath jars */ protected List findExtraClasspathJars(WebAppContext context) - throws Exception { if (context == null || context.getExtraClasspath() == null) return null; return context.getExtraClasspath() - .getResources() .stream() .filter(this::isFileSupported) .collect(Collectors.toList()); @@ -775,7 +772,6 @@ public class MetaInfConfiguration extends AbstractConfiguration return List.of(); return context.getExtraClasspath() - .getResources() .stream() .filter(Resource::isDirectory) .collect(Collectors.toList()); diff --git a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppClassLoader.java b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppClassLoader.java index 9246b6e2c4a..ea40569b140 100644 --- a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppClassLoader.java +++ b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppClassLoader.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.io.InputStream; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; +import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; @@ -43,7 +44,6 @@ import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.util.resource.ResourceFactory; import org.eclipse.jetty.util.resource.Resources; import org.slf4j.Logger; @@ -113,7 +113,7 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility */ boolean isParentLoaderPriority(); - ResourceCollection getExtraClasspath(); + List getExtraClasspath(); boolean isServerResource(String name, URL parentUrl); @@ -193,13 +193,8 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility } } - if (context.getExtraClasspath() != null) - { - for (Resource resource : context.getExtraClasspath().getResources()) - { - addClassPath(resource); - } - } + for (Resource extra : context.getExtraClasspath()) + addClassPath(extra); } /** @@ -224,16 +219,23 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility } /** - * @param resources The resources to add to the classpath - * @throws IOException if unable to add classpath from resource + * @param resource The resources to add to the classpath */ - public void addClassPath(Resource resources) - throws IOException + public void addClassPath(Resource resource) { - for (Resource resource: resources) + for (Resource r : resource) { - if (Resources.exists(resource)) - addURL(resource.getURI().toURL()); + if (resource.exists()) + { + try + { + addURL(r.getURI().toURL()); + } + catch (MalformedURLException e) + { + throw new IllegalArgumentException("File not resolvable or incompatible with URLClassloader: " + resource); + } + } else { if (LOG.isDebugEnabled()) diff --git a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppContext.java b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppContext.java index 6f9bf5b8221..7ac59b85dbc 100644 --- a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppContext.java +++ b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/WebAppContext.java @@ -30,6 +30,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletRegistration.Dynamic; @@ -59,7 +60,6 @@ import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.component.ClassLoaderDump; import org.eclipse.jetty.util.component.DumpableCollection; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.util.resource.ResourceFactory; import org.eclipse.jetty.util.resource.Resources; import org.slf4j.Logger; @@ -132,7 +132,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL private boolean _persistTmpDir = false; private String _war; - private ResourceCollection _extraClasspath; + private List _extraClasspath; private Throwable _unavailableException; private Map _resourceAliases; @@ -1235,29 +1235,29 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL */ @Override @ManagedAttribute(value = "extra classpath for context classloader", readonly = true) - public ResourceCollection getExtraClasspath() + public List getExtraClasspath() { - return _extraClasspath; + return _extraClasspath == null ? Collections.emptyList() : _extraClasspath; } /** * Set the Extra ClassPath via delimited String. *

- * This is a convenience method for {@link #setExtraClasspath(ResourceCollection)} + * This is a convenience method for {@link #setExtraClasspath(List)} *

* * @param extraClasspath Comma or semicolon separated path of filenames or URLs * pointing to directories or jar files. Directories should end * with '/'. - * @see #setExtraClasspath(ResourceCollection) + * @see #setExtraClasspath(List) */ public void setExtraClasspath(String extraClasspath) { List uris = URIUtil.split(extraClasspath); - setExtraClasspath(this.getResourceFactory().newResource(uris)); + setExtraClasspath(uris.stream().map(this.getResourceFactory()::newResource).collect(Collectors.toList())); } - public void setExtraClasspath(ResourceCollection extraClasspath) + public void setExtraClasspath(List extraClasspath) { _extraClasspath = extraClasspath; } diff --git a/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/MavenQuickStartConfiguration.java b/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/MavenQuickStartConfiguration.java index f68eb453e96..d4f69bed4d0 100644 --- a/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/MavenQuickStartConfiguration.java +++ b/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/MavenQuickStartConfiguration.java @@ -17,8 +17,8 @@ import org.eclipse.jetty.ee9.quickstart.QuickStartConfiguration; import org.eclipse.jetty.ee9.webapp.Configuration; import org.eclipse.jetty.ee9.webapp.WebAppContext; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.resource.CombinedResource; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,9 +47,9 @@ public class MavenQuickStartConfiguration extends QuickStartConfiguration //Iterate over all of the resource bases and ignore any that were original bases, just //deleting the overlays Resource res = context.getBaseResource(); - if (res instanceof ResourceCollection) + if (res instanceof CombinedResource) { - for (Resource r : ((ResourceCollection)res).getResources()) + for (Resource r : ((CombinedResource)res).getResources()) { if (originalBaseStr.contains(r.toString())) continue; diff --git a/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/MavenWebAppContext.java b/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/MavenWebAppContext.java index e82a6bdd13b..c7d160e344f 100644 --- a/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/MavenWebAppContext.java +++ b/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/MavenWebAppContext.java @@ -40,8 +40,8 @@ import org.eclipse.jetty.ee9.webapp.WebAppContext; import org.eclipse.jetty.util.FileID; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.resource.CombinedResource; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.util.resource.ResourceFactory; import org.eclipse.jetty.util.resource.Resources; import org.slf4j.Logger; @@ -220,7 +220,7 @@ public class MavenWebAppContext extends WebAppContext * configuration * * @param resourceBases Array of resources strings to set as a - * {@link ResourceCollection}. + * {@link CombinedResource}. */ public void setResourceBases(String[] resourceBases) { diff --git a/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/WebAppPropertyConverter.java b/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/WebAppPropertyConverter.java index 99fe68d5a7f..1a221398ae6 100644 --- a/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/WebAppPropertyConverter.java +++ b/jetty-ee9/jetty-ee9-maven-plugin/src/main/java/org/eclipse/jetty/ee9/maven/plugin/WebAppPropertyConverter.java @@ -29,8 +29,8 @@ import org.eclipse.jetty.ee9.quickstart.QuickStartConfiguration; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.resource.CombinedResource; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.xml.XmlConfiguration; /** @@ -105,8 +105,8 @@ public class WebAppPropertyConverter //send over the calculated resource bases that includes unpacked overlays Resource baseResource = webApp.getBaseResource(); - if (baseResource instanceof ResourceCollection) - props.put(BASE_DIRS, toCSV(((ResourceCollection)webApp.getBaseResource()).getResources())); + if (baseResource instanceof CombinedResource) + props.put(BASE_DIRS, toCSV(((CombinedResource)webApp.getBaseResource()).getResources())); else if (baseResource instanceof Resource) props.put(BASE_DIRS, webApp.getBaseResource().toString()); diff --git a/jetty-ee9/jetty-ee9-maven-plugin/src/test/java/org/eclipse/jetty/ee9/maven/plugin/TestWebAppPropertyConverter.java b/jetty-ee9/jetty-ee9-maven-plugin/src/test/java/org/eclipse/jetty/ee9/maven/plugin/TestWebAppPropertyConverter.java index 2f55a64e7ab..f1f32ced235 100644 --- a/jetty-ee9/jetty-ee9-maven-plugin/src/test/java/org/eclipse/jetty/ee9/maven/plugin/TestWebAppPropertyConverter.java +++ b/jetty-ee9/jetty-ee9-maven-plugin/src/test/java/org/eclipse/jetty/ee9/maven/plugin/TestWebAppPropertyConverter.java @@ -25,8 +25,8 @@ import org.eclipse.jetty.ee9.webapp.WebAppContext; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.resource.CombinedResource; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.hamcrest.Matchers; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -152,10 +152,10 @@ public class TestWebAppPropertyConverter assertEquals(true, webApp.isPersistTempDirectory()); assertEquals(war.getAbsolutePath(), webApp.getWar()); assertEquals(webXml.getAbsolutePath(), webApp.getDescriptor()); - assertThat(webApp.getBaseResource(), instanceOf(ResourceCollection.class)); + assertThat(webApp.getBaseResource(), instanceOf(CombinedResource.class)); - ResourceCollection resourceCollection = (ResourceCollection)webApp.getBaseResource(); - List actual = resourceCollection.getResources().stream().filter(Objects::nonNull).map(Resource::getURI).toList(); + CombinedResource combinedResource = (CombinedResource)webApp.getBaseResource(); + List actual = combinedResource.getResources().stream().filter(Objects::nonNull).map(Resource::getURI).toList(); URI[] expected = new URI[]{base1.toURI(), base2.toURI()}; assertThat(actual, containsInAnyOrder(expected)); } diff --git a/jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/QuickStartDescriptorProcessor.java b/jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/QuickStartDescriptorProcessor.java index 773e9d95c6c..e7bc7fa8a9a 100644 --- a/jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/QuickStartDescriptorProcessor.java +++ b/jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/QuickStartDescriptorProcessor.java @@ -33,6 +33,7 @@ import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.resource.AttributeNormalizer; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.ResourceFactory; import org.eclipse.jetty.util.resource.Resources; diff --git a/jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/QuickStartGeneratorConfiguration.java b/jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/QuickStartGeneratorConfiguration.java index 179afdae991..01ab7f2df5d 100644 --- a/jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/QuickStartGeneratorConfiguration.java +++ b/jetty-ee9/jetty-ee9-quickstart/src/main/java/org/eclipse/jetty/ee9/quickstart/QuickStartGeneratorConfiguration.java @@ -57,6 +57,7 @@ import org.eclipse.jetty.ee9.webapp.WebInfConfiguration; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.resource.AttributeNormalizer; import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.xml.XmlAppendable; import org.slf4j.Logger; diff --git a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/MetaInfConfiguration.java b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/MetaInfConfiguration.java index 005bcdb3764..c13ef4f81de 100644 --- a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/MetaInfConfiguration.java +++ b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/MetaInfConfiguration.java @@ -729,7 +729,6 @@ public class MetaInfConfiguration extends AbstractConfiguration return null; return context.getExtraClasspath() - .getResources() .stream() .filter(this::isFileSupported) .collect(Collectors.toList()); @@ -773,7 +772,6 @@ public class MetaInfConfiguration extends AbstractConfiguration return List.of(); return context.getExtraClasspath() - .getResources() .stream() .filter(Resource::isDirectory) .collect(Collectors.toList()); diff --git a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoader.java b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoader.java index 16fc197ab63..3d1856247ba 100644 --- a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoader.java +++ b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoader.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.io.InputStream; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; +import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; @@ -43,7 +44,6 @@ import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.util.resource.ResourceFactory; import org.eclipse.jetty.util.resource.Resources; import org.slf4j.Logger; @@ -113,7 +113,7 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility */ boolean isParentLoaderPriority(); - ResourceCollection getExtraClasspath(); + List getExtraClasspath(); boolean isServerResource(String name, URL parentUrl); @@ -193,13 +193,8 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility } } - if (context.getExtraClasspath() != null) - { - for (Resource resource : context.getExtraClasspath().getResources()) - { - addClassPath(resource); - } - } + for (Resource extra : context.getExtraClasspath()) + addClassPath(extra); } /** @@ -224,23 +219,30 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility } /** - * @param resources The resources to add to the classpath - * @throws IOException if unable to add classpath from resource + * @param resource The resources to add to the classpath */ - public void addClassPath(Resource resources) - throws IOException + public void addClassPath(Resource resource) { - for (Resource resource: resources) + for (Resource r : resource) { - if (Resources.exists(resource)) - addURL(resource.getURI().toURL()); + if (resource.exists()) + { + try + { + addURL(r.getURI().toURL()); + } + catch (MalformedURLException e) + { + throw new IllegalArgumentException("File not resolvable or incompatible with URLClassloader: " + resource); + } + } else { if (LOG.isDebugEnabled()) LOG.debug("Check resource exists and is not a nested jar: {}", resource); throw new IllegalArgumentException("File not resolvable or incompatible with URLClassloader: " + resource); } - } + }; } /** diff --git a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java index ff7fbc8ba82..06c5a80b501 100644 --- a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java +++ b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java @@ -30,6 +30,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletRegistration.Dynamic; @@ -63,7 +64,6 @@ import org.eclipse.jetty.util.component.ClassLoaderDump; import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.component.DumpableCollection; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.util.resource.ResourceFactory; import org.eclipse.jetty.util.resource.Resources; import org.slf4j.Logger; @@ -135,7 +135,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL private boolean _persistTmpDir = false; private String _war; - private ResourceCollection _extraClasspath; + private List _extraClasspath; private Throwable _unavailableException; private Map _resourceAliases; @@ -1233,30 +1233,30 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL */ @Override @ManagedAttribute(value = "extra classpath for context classloader", readonly = true) - public ResourceCollection getExtraClasspath() + public List getExtraClasspath() { - return _extraClasspath; + return _extraClasspath == null ? Collections.emptyList() : _extraClasspath; } /** * Set the Extra ClassPath via delimited String. *

- * This is a convenience method for {@link #setExtraClasspath(ResourceCollection)} + * This is a convenience method for {@link #setExtraClasspath(List)} )} *

* * @param extraClasspath Comma or semicolon separated path of filenames or URLs * pointing to directories or jar files. Directories should end * with '/'. * @throws IOException if unable to resolve the resources referenced - * @see #setExtraClasspath(ResourceCollection) + * @see #setExtraClasspath(List) */ public void setExtraClasspath(String extraClasspath) throws IOException { List uris = URIUtil.split(extraClasspath); - setExtraClasspath(this.getResourceFactory().newResource(uris)); + setExtraClasspath(uris.stream().map(this.getResourceFactory()::newResource).collect(Collectors.toList())); } - public void setExtraClasspath(ResourceCollection extraClasspath) + public void setExtraClasspath(List extraClasspath) { _extraClasspath = extraClasspath; } From 4e32557616d101651dc45e520ed43dee8742bc82 Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Tue, 1 Nov 2022 22:07:49 +1000 Subject: [PATCH 41/42] use default container (#8812) Signed-off-by: Olivier Lamy --- Jenkinsfile | 54 ++++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 37a13a4f407..b73e0d4ad01 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -14,34 +14,32 @@ pipeline { stage("Build / Test - JDK17") { agent { node { label 'linux' } } steps { - container('jetty-build') { - timeout( time: 180, unit: 'MINUTES' ) { - checkout scm - mavenBuild( "jdk17", "clean install javadoc:javadoc -Perrorprone", "maven3") - // Collect up the jacoco execution results (only on main build) - jacoco inclusionPattern: '**/org/eclipse/jetty/**/*.class', - exclusionPattern: '' + - // build tools - '**/org/eclipse/jetty/ant/**' + - ',*/org/eclipse/jetty/maven/its/**' + - ',**/org/eclipse/jetty/its/**' + - // example code / documentation - ',**/org/eclipse/jetty/embedded/**' + - ',**/org/eclipse/jetty/asyncrest/**' + - ',**/org/eclipse/jetty/demo/**' + - // special environments / late integrations - ',**/org/eclipse/jetty/gcloud/**' + - ',**/org/eclipse/jetty/infinispan/**' + - ',**/org/eclipse/jetty/osgi/**' + - ',**/org/eclipse/jetty/http/spi/**' + - // test classes - ',**/org/eclipse/jetty/tests/**' + - ',**/org/eclipse/jetty/test/**', - execPattern: '**/target/jacoco.exec', - classPattern: '**/target/classes', - sourcePattern: '**/src/main/java' - recordIssues id: "jdk17", name: "Static Analysis jdk17", aggregatingResults: true, enabledForFailure: true, tools: [mavenConsole(), java(), checkStyle(), errorProne(), spotBugs()] - } + timeout( time: 180, unit: 'MINUTES' ) { + checkout scm + mavenBuild( "jdk17", "clean install javadoc:javadoc -Perrorprone", "maven3") + // Collect up the jacoco execution results (only on main build) + jacoco inclusionPattern: '**/org/eclipse/jetty/**/*.class', + exclusionPattern: '' + + // build tools + '**/org/eclipse/jetty/ant/**' + + ',*/org/eclipse/jetty/maven/its/**' + + ',**/org/eclipse/jetty/its/**' + + // example code / documentation + ',**/org/eclipse/jetty/embedded/**' + + ',**/org/eclipse/jetty/asyncrest/**' + + ',**/org/eclipse/jetty/demo/**' + + // special environments / late integrations + ',**/org/eclipse/jetty/gcloud/**' + + ',**/org/eclipse/jetty/infinispan/**' + + ',**/org/eclipse/jetty/osgi/**' + + ',**/org/eclipse/jetty/http/spi/**' + + // test classes + ',**/org/eclipse/jetty/tests/**' + + ',**/org/eclipse/jetty/test/**', + execPattern: '**/target/jacoco.exec', + classPattern: '**/target/classes', + sourcePattern: '**/src/main/java' + recordIssues id: "jdk17", name: "Static Analysis jdk17", aggregatingResults: true, enabledForFailure: true, tools: [mavenConsole(), java(), checkStyle(), errorProne(), spotBugs()] } } } From 7e88b8234cd30552fe4f7cd6d6eaeef4d7459517 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 2 Nov 2022 08:16:24 +1100 Subject: [PATCH 42/42] Experiment with lock free AdaptiveExecutionStrategy (#8762) Removed the lock from the AdaptiveExecutionStrategy in favour of a BiInteger. --- .../strategy/AdaptiveExecutionStrategy.java | 186 ++++++++++++------ 1 file changed, 124 insertions(+), 62 deletions(-) diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/AdaptiveExecutionStrategy.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/AdaptiveExecutionStrategy.java index 7c216a2962e..712a2f84ed7 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/AdaptiveExecutionStrategy.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/AdaptiveExecutionStrategy.java @@ -20,13 +20,13 @@ import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.LongAdder; +import org.eclipse.jetty.util.AtomicBiInteger; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.VirtualThreads; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedOperation; import org.eclipse.jetty.util.component.ContainerLifeCycle; -import org.eclipse.jetty.util.thread.AutoLock; import org.eclipse.jetty.util.thread.ExecutionStrategy; import org.eclipse.jetty.util.thread.Invocable; import org.eclipse.jetty.util.thread.TryExecutor; @@ -98,12 +98,9 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe /** * The production state of the strategy. */ - private enum State - { - IDLE, // No tasks or producers. - PRODUCING, // There is an active producing thread. - REPRODUCING // There is an active producing thread and demand for more production. - } + static final int IDLE = 0; // No tasks or producers. + static final int PRODUCING = 1; // There is an active producing thread. + static final int REPRODUCING = 2; // There is an active producing thread and demand for more production. /** * The sub-strategies used by the strategy to consume tasks that are produced. @@ -128,7 +125,6 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe EXECUTE_PRODUCE_CONSUME } - private final AutoLock _lock = new AutoLock(); private final LongAdder _pcMode = new LongAdder(); private final LongAdder _picMode = new LongAdder(); private final LongAdder _pecMode = new LongAdder(); @@ -138,8 +134,7 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe private final TryExecutor _tryExecutor; private final Runnable _runPendingProducer = () -> tryProduce(true); private boolean _useVirtualThreads; - private State _state = State.IDLE; - private boolean _pending; + private final AtomicBiInteger _state = new AtomicBiInteger(); /** * @param producer The producer of tasks to be consumed. @@ -167,26 +162,33 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe public void dispatch() { boolean execute = false; - try (AutoLock l = _lock.lock()) + loop: while (true) { - switch (_state) + long biState = _state.get(); + int state = AtomicBiInteger.getLo(biState); + int pending = AtomicBiInteger.getHi(biState); + + switch (state) { case IDLE: - if (!_pending) + if (pending <= 0) { - _pending = true; + if (!_state.compareAndSet(biState, pending + 1, state)) + continue; execute = true; } - break; + break loop; case PRODUCING: - _state = State.REPRODUCING; - break; + if (!_state.compareAndSet(biState, pending, REPRODUCING)) + continue; + break loop; default: - break; + break loop; } } + if (LOG.isDebugEnabled()) LOG.debug("{} dispatch {}", this, execute); if (execute) @@ -209,39 +211,47 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe if (LOG.isDebugEnabled()) LOG.debug("{} tryProduce {}", this, wasPending); - // Takes the lock to atomically check if the thread can produce. - try (AutoLock l = _lock.lock()) + // check if the thread can produce. + loop: while (true) { + long biState = _state.get(); + int state = AtomicBiInteger.getLo(biState); + int pending = AtomicBiInteger.getHi(biState); + // If the calling thread was the pending producer, there is no longer one pending. if (wasPending) - _pending = false; + pending--; - switch (_state) + switch (state) { case IDLE: // The strategy was IDLE, so this thread can become the producer. - _state = State.PRODUCING; - break; + if (!_state.compareAndSet(biState, pending, PRODUCING)) + continue; + break loop; case PRODUCING: // The strategy is already producing, so another thread must be the producer. // However, it may be just about to stop being the producer so we set the // REPRODUCING state to force it to produce at least once more. - _state = State.REPRODUCING; + if (!_state.compareAndSet(biState, pending, REPRODUCING)) + continue; return; case REPRODUCING: // Another thread is already producing and will already try again to produce. + if (!_state.compareAndSet(biState, pending, state)) + continue; return; default: - throw new IllegalStateException(toStringLocked()); + throw new IllegalStateException(toString(biState)); } } // Determine the thread's invocation type once, outside of the production loop. boolean nonBlocking = Invocable.isNonBlockingInvocation(); - while (isRunning()) + running: while (isRunning()) { try { @@ -250,24 +260,30 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe // If we did not produce a task if (task == null) { - // take the lock to atomically determine if we should keep producing. - try (AutoLock l = _lock.lock()) + // determine if we should keep producing. + while (true) { - switch (_state) + long biState = _state.get(); + int state = AtomicBiInteger.getLo(biState); + int pending = AtomicBiInteger.getHi(biState); + + switch (state) { case PRODUCING: // The calling thread was the only producer, so it is now IDLE and we stop producing. - _state = State.IDLE; + if (!_state.compareAndSet(biState, pending, IDLE)) + continue; return; case REPRODUCING: // Another thread may have queued a task and tried to produce // so the calling thread should continue to produce. - _state = State.PRODUCING; - continue; + if (!_state.compareAndSet(biState, pending, PRODUCING)) + continue; + continue running; default: - throw new IllegalStateException(toStringLocked()); + throw new IllegalStateException(toString(biState)); } } } @@ -303,53 +319,90 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe return SubStrategy.PRODUCE_CONSUME; case EITHER: + { // The produced task may be run either as blocking or non blocking. // If the calling producing thread is already non-blocking, use PC. if (nonBlocking) return SubStrategy.PRODUCE_CONSUME; - // Take the lock to atomically check if a pending producer is available. - try (AutoLock l = _lock.lock()) + // check if a pending producer is available. + int executed = 0; + while (true) { + long biState = _state.get(); + int state = AtomicBiInteger.getLo(biState); + int pending = AtomicBiInteger.getHi(biState); + // If a pending producer is available or one can be started - if (_pending || _tryExecutor.tryExecute(_runPendingProducer)) + pending += executed; + if (pending <= 0 && _tryExecutor.tryExecute(_runPendingProducer)) + { + executed++; + pending++; + } + + if (pending > 0) { // Use EPC: the producer directly consumes the task, which may block // and then races with the pending producer to resume production. - _pending = true; - _state = State.IDLE; + if (!_state.compareAndSet(biState, pending, IDLE)) + continue; return SubStrategy.EXECUTE_PRODUCE_CONSUME; } + + if (!_state.compareAndSet(biState, pending, state)) + continue; + break; } // Otherwise use PIC: the producer consumes the task // in non-blocking mode and then resumes production. return SubStrategy.PRODUCE_INVOKE_CONSUME; + } case BLOCKING: + { // The produced task may block. // If the calling producing thread may also block if (!nonBlocking) { - // Take the lock to atomically check if a pending producer is available. - try (AutoLock l = _lock.lock()) + // check if a pending producer is available. + int executed = 0; + while (true) { + long biState = _state.get(); + int state = AtomicBiInteger.getLo(biState); + int pending = AtomicBiInteger.getHi(biState); + // If a pending producer is available or one can be started - if (_pending || _tryExecutor.tryExecute(_runPendingProducer)) + pending += executed; + if (pending <= 0 && _tryExecutor.tryExecute(_runPendingProducer)) + { + executed++; + pending++; + } + + // If a pending producer is available or one can be started + if (pending > 0) { // use EPC: The producer directly consumes the task, which may block // and then races with the pending producer to resume production. - _pending = true; - _state = State.IDLE; + if (!_state.compareAndSet(biState, pending, IDLE)) + continue; return SubStrategy.EXECUTE_PRODUCE_CONSUME; } + + if (!_state.compareAndSet(biState, pending, state)) + continue; + break; } } // Otherwise use PEC: the task is consumed by the executor and the producer continues to produce. return SubStrategy.PRODUCE_EXECUTE_CONSUME; + } default: throw new IllegalStateException(String.format("taskType=%s %s", taskType, this)); @@ -390,19 +443,25 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe runTask(task); // Race the pending producer to produce again. - try (AutoLock l = _lock.lock()) + while (true) { - if (_state == State.IDLE) + long biState = _state.get(); + int state = AtomicBiInteger.getLo(biState); + int pending = AtomicBiInteger.getHi(biState); + + if (state == IDLE) { // We beat the pending producer, so we will become the producer instead. // The pending produce will become a noop if it arrives whilst we are producing, // or it may take over if we subsequently do another EPC consumption. - _state = State.PRODUCING; + if (!_state.compareAndSet(biState, pending, PRODUCING)) + continue; return true; } + + // The pending producer is now producing, so this thread no longer produces. + return false; } - // The pending producer is now producing, so this thread no longer produces. - return false; default: throw new IllegalStateException(String.format("ss=%s %s", subStrategy, this)); @@ -521,10 +580,7 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe @ManagedAttribute(value = "whether this execution strategy is idle", readonly = true) public boolean isIdle() { - try (AutoLock l = _lock.lock()) - { - return _state == State.IDLE; - } + return _state.getLo() == IDLE; } @ManagedOperation(value = "resets the task counts", impact = "ACTION") @@ -539,17 +595,14 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe @Override public String toString() { - try (AutoLock l = _lock.lock()) - { - return toStringLocked(); - } + return toString(_state.get()); } - public String toStringLocked() + public String toString(long biState) { StringBuilder builder = new StringBuilder(); getString(builder); - getState(builder); + getState(builder, biState); return builder.toString(); } @@ -563,11 +616,20 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe builder.append('/'); } - private void getState(StringBuilder builder) + private void getState(StringBuilder builder, long biState) { - builder.append(_state); + int state = AtomicBiInteger.getLo(biState); + int pending = AtomicBiInteger.getHi(biState); + builder.append( + switch (state) + { + case IDLE -> "IDLE"; + case PRODUCING -> "PRODUCING"; + case REPRODUCING -> "REPRODUCING"; + default -> "UNKNOWN(%d)".formatted(state); + }); builder.append("/p="); - builder.append(_pending); + builder.append(pending); builder.append('/'); builder.append(_tryExecutor); builder.append("[pc=");