This is an automated email from the ASF dual-hosted git repository. ffang pushed a commit to branch 3.6.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 84fd1310b728f7423ca5c51d74afca677ee65d1d Author: Freeman Fang <[email protected]> AuthorDate: Thu Nov 14 15:40:45 2024 -0500 [CXF-9052]LoadDistributorFeature not comaptible with JAX-RS subresources (cherry picked from commit 49a6ed5aa831629396cca3c90db4fb5974e63195) (cherry picked from commit b7d2dfcc960e6bb816692b96c63cec4b1ca1151a) --- .../clustering/LoadDistributorTargetSelector.java | 40 +++++++++++ .../cxf/systest/jaxrs/failover/CXF9052Test.java | 79 ++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/rt/features/clustering/src/main/java/org/apache/cxf/clustering/LoadDistributorTargetSelector.java b/rt/features/clustering/src/main/java/org/apache/cxf/clustering/LoadDistributorTargetSelector.java index 467e3e735c..2ae2b04cdf 100644 --- a/rt/features/clustering/src/main/java/org/apache/cxf/clustering/LoadDistributorTargetSelector.java +++ b/rt/features/clustering/src/main/java/org/apache/cxf/clustering/LoadDistributorTargetSelector.java @@ -21,6 +21,7 @@ package org.apache.cxf.clustering; import java.util.List; import java.util.logging.Logger; +import org.apache.cxf.clustering.FailoverTargetSelector.InvocationContext; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.message.Exchange; @@ -169,6 +170,45 @@ public class LoadDistributorTargetSelector extends FailoverTargetSelector { } return failoverTarget; } + + // Some conduits may replace the endpoint address after it has already been prepared + // but before the invocation has been done (ex, org.apache.cxf.clustering.LoadDistributorTargetSelector) + // which may affect JAX-RS clients where actual endpoint address property may include additional path + // segments. + protected boolean replaceEndpointAddressPropertyIfNeeded(Message message, + String endpointAddress, + Conduit cond) { + String requestURI = (String)message.get(Message.REQUEST_URI); + if (requestURI != null && endpointAddress != null && !requestURI.equals(endpointAddress)) { + String basePath = (String)message.get(Message.BASE_PATH); + if (basePath.startsWith(endpointAddress)) { + endpointAddress = basePath; + } + if (basePath != null && requestURI.startsWith(basePath)) { + String pathInfo = requestURI.substring(basePath.length()); + message.put(Message.BASE_PATH, endpointAddress); + final String slash = "/"; + boolean startsWithSlash = pathInfo.startsWith(slash); + if (endpointAddress.endsWith(slash)) { + endpointAddress = endpointAddress + (startsWithSlash ? pathInfo.substring(1) : pathInfo); + } else { + endpointAddress = endpointAddress + (startsWithSlash ? pathInfo : (slash + pathInfo)); + } + message.put(Message.ENDPOINT_ADDRESS, endpointAddress); + message.put(Message.REQUEST_URI, endpointAddress); + + Exchange exchange = message.getExchange(); + String key = String.valueOf(System.identityHashCode(exchange)); + InvocationContext invocation = getInvocationContext(key); + if (invocation != null) { + overrideAddressProperty(invocation.getContext(), + cond.getTarget().getAddress().getValue()); + } + return true; + } + } + return false; + } /** * Get the distribution target endpoint, if a suitable one is available. diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/failover/CXF9052Test.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/failover/CXF9052Test.java new file mode 100644 index 0000000000..fd4891bc4f --- /dev/null +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/failover/CXF9052Test.java @@ -0,0 +1,79 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.systest.jaxrs.failover; + +import java.util.List; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import org.apache.cxf.clustering.FailoverFeature; +import org.apache.cxf.clustering.LoadDistributorFeature; +import org.apache.cxf.clustering.SequentialStrategy; +import org.apache.cxf.feature.Feature; +import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean; + +import org.junit.Assert; +import org.junit.Test; +public class CXF9052Test { + @Test + public void noClustering() { + makeRequest(List.of()); + } + + @Test + public void failover() { + var failover = new FailoverFeature(); + failover.setStrategy(makeStrategy()); + makeRequest(List.of(failover)); + } + + @Test + public void loadDistributor() { + var distro = new LoadDistributorFeature(); + distro.setStrategy(makeStrategy()); + makeRequest(List.of(distro)); + } + + private static SequentialStrategy makeStrategy() { + var s = new SequentialStrategy(); + s.setAlternateAddresses(List.of("http://localhost:1234/test")); + return s; + } + + private static void makeRequest(List<Feature> features) { + var fct = new JAXRSClientFactoryBean(); + fct.setFeatures(features); + fct.setServiceClass(Root.class); + fct.setAddress("http://localhost:1234/test"); + try { + fct.create(Root.class).sub().name(); + } catch (Exception e) { + Assert.assertTrue(e.getMessage(), e.getMessage().contains("/sub/name")); + } + } + + interface Root { + @Path("/sub") Sub sub(); + } + + interface Sub { + @GET @Path("/name") String name(); + } +}
