diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java index 93e3b4e288b..b4e99347ccc 100644 --- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java +++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java @@ -249,7 +249,10 @@ public String getMatchedResourceTemplate() { final List templates = new LinkedList<>(); for (MethodInvocationInfo invocation : stack) { OperationResourceInfo ori = invocation.getMethodInfo(); - templates.add(ori.getClassResourceInfo().getURITemplate()); + final URITemplate classUriTemplate = ori.getClassResourceInfo().getURITemplate(); + if (classUriTemplate != null) { + templates.add(classUriTemplate); + } templates.add(ori.getURITemplate()); } @@ -258,7 +261,7 @@ public String getMatchedResourceTemplate() { for (int i = 1; i < templates.size(); ++i) { builder = builder.path(templates.get(i).getValue()); } - return builder.build().toString(); + return builder.toTemplate(); } } LOG.fine("No resource stack information, returning empty template"); diff --git a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java index ae6c97105b2..bfc5c8ba871 100644 --- a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java +++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java @@ -430,6 +430,12 @@ public Response get() { return null; } + @GET + @Path("one/{name:[a-zA-Z][a-zA-Z_0-9]*}") + public Response getTemplate() { + return null; + } + @GET @Path("bar") public Response getSubMethod() { @@ -563,6 +569,58 @@ public void testGetMatchedURIsSubResourceLocatorSubPath() throws Exception { assertEquals("foo", matchedUris.get(2)); } + @Test + public void testGetMatchedResourceTemplateIncludesApplicationPathAndTemplateVariables() throws Exception { + Message m = mockMessage("http://localhost:8080/app", "/foo/one/abc"); + OperationResourceInfoStack oriStack = new OperationResourceInfoStack(); + ClassResourceInfo cri = getCri(RootResource.class, true); + OperationResourceInfo ori = getOri(cri, "getTemplate"); + + MethodInvocationInfo miInfo = new MethodInvocationInfo(ori, RootResource.class, new ArrayList()); + oriStack.push(miInfo); + m.put(OperationResourceInfoStack.class, oriStack); + + UriInfoImpl u = new UriInfoImpl(m); + assertEquals("/foo/one/{name:[a-zA-Z][a-zA-Z_0-9]*}", u.getMatchedResourceTemplate()); + } + + @Test + public void testGetMatchedResourceTemplateIgnoresPathBeforeApplicationPath() throws Exception { + Message m = mockMessage("http://localhost:8080/context/service", "/foo/bar"); + + OperationResourceInfoStack oriStack = new OperationResourceInfoStack(); + ClassResourceInfo cri = getCri(RootResource.class, true); + OperationResourceInfo ori = getOri(cri, "getSubMethod"); + + MethodInvocationInfo miInfo = new MethodInvocationInfo(ori, RootResource.class, new ArrayList()); + oriStack.push(miInfo); + m.put(OperationResourceInfoStack.class, oriStack); + + UriInfoImpl u = new UriInfoImpl(m); + assertEquals("/foo/bar", u.getMatchedResourceTemplate()); + } + + @Test + public void testGetMatchedResourceTemplateSubResourceWithoutClassPath() throws Exception { + Message m = mockMessage("http://localhost:8080/app", "/foo/sub"); + OperationResourceInfoStack oriStack = new OperationResourceInfoStack(); + ClassResourceInfo rootCri = getCri(RootResource.class, true); + OperationResourceInfo rootOri = getOri(rootCri, "getSubResourceLocator"); + + MethodInvocationInfo miInfo = new MethodInvocationInfo(rootOri, RootResource.class, new ArrayList()); + oriStack.push(miInfo); + + ClassResourceInfo subCri = getCri(SubResource.class, false); + OperationResourceInfo subOri = getOri(subCri, "getFromSub"); + + miInfo = new MethodInvocationInfo(subOri, SubResource.class, new ArrayList()); + oriStack.push(miInfo); + m.put(OperationResourceInfoStack.class, oriStack); + + UriInfoImpl u = new UriInfoImpl(m); + assertEquals("/foo/sub/", u.getMatchedResourceTemplate()); + } + private Message mockMessage(String baseAddress, String pathInfo) { return mockMessage(baseAddress, pathInfo, null, null); } diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStorePerRequest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStorePerRequest.java index 4ed0cd0ede0..e9ab093329b 100644 --- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStorePerRequest.java +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStorePerRequest.java @@ -31,6 +31,7 @@ import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriInfo; @Path("/bookstore2") public class BookStorePerRequest { @@ -86,6 +87,12 @@ public void setHttpHeaders(HttpHeaders headers) { public Book getBookByHeader2() throws Exception { return getBookByHeader(); } + + @GET + @Path("/book%20template/{name:[a-zA-Z][a-zA-Z_0-9]*}") + public String getBookTemplate(@Context final UriInfo info) throws Exception { + return info.getMatchedResourceTemplate(); + } @GET @Path("/bookheaders/") diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java index 3278e4d7d2e..cd19a68b979 100644 --- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java @@ -44,6 +44,8 @@ import org.junit.BeforeClass; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; @@ -202,6 +204,14 @@ public void testGetBook123TwoApplications() throws Exception { doTestPerRequest("http://localhost:" + PORT + "/application6/thebooks/bookstore2/bookheaders"); doTestPerRequest("http://localhost:" + PORT + "/application6/the%20books2/bookstore2/book%20headers"); } + + @Test + public void testGetMatchedResourceTemplate() throws Exception { + WebClient wc = WebClient.create("http://localhost:" + PORT + + "/application6/the%20books2/bookstore2/book%20template/abc"); + assertThat(wc.accept("*/*").get(String.class), + equalTo("/bookstore2/book%20template/{name:[a-zA-Z][a-zA-Z_0-9]*}")); + } @SafeVarargs private final Response doTestPerRequest(String address, Map.Entry ... params) throws Exception {