This is an automated email from the ASF dual-hosted git repository. reta pushed a commit to branch 3.3.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 5fdba769c8f7dff4f02c911403a56b81123de156 Author: Andriy Redko <[email protected]> AuthorDate: Thu Dec 2 08:37:25 2021 -0500 CXF-8620: AbstractHTTPServlet should support HTTP TRACE method dispatching if it is allowed by underlying container (#879) (cherry picked from commit ea7ea0c32683af9973f9897049f024c50ec6afa3) --- .../main/java/org/apache/cxf/jaxrs/ext/TRACE.java | 34 +++++---------- .../cxf/transport/servlet/AbstractHTTPServlet.java | 6 +++ .../cxf/systest/jaxrs/resources/Library.java | 5 +++ .../cxf/systest/jaxrs/resources/LibraryApi.java | 6 +++ .../systest/jaxrs/spring/boot/SpringJaxrsTest.java | 51 ++++++++++++++++++++++ 5 files changed, 78 insertions(+), 24 deletions(-) diff --git a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/LibraryApi.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/TRACE.java similarity index 54% copy from systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/LibraryApi.java copy to rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/TRACE.java index 911214d..fecb08b 100644 --- a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/LibraryApi.java +++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/TRACE.java @@ -17,31 +17,17 @@ * under the License. */ -package org.apache.cxf.systest.jaxrs.resources; +package org.apache.cxf.jaxrs.ext; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; -public interface LibraryApi { - @Produces({ MediaType.APPLICATION_JSON }) - @GET - Response getBooks(@QueryParam("page") @DefaultValue("1") int page); +import javax.ws.rs.HttpMethod; - @Produces({ MediaType.APPLICATION_JSON }) - @Path("{id}") - @GET - Response getBook(@PathParam("id") String id); - - @DELETE - void deleteBooks(); - - @Path("/catalog") - Catalog catalog(); +@HttpMethod("TRACE") +@Target(value = ElementType.METHOD) +@Retention(value = RetentionPolicy.RUNTIME) +public @interface TRACE { } diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/AbstractHTTPServlet.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/AbstractHTTPServlet.java index a6b5cbb..621a895 100644 --- a/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/AbstractHTTPServlet.java +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/servlet/AbstractHTTPServlet.java @@ -245,6 +245,12 @@ public abstract class AbstractHTTPServlet extends HttpServlet implements Filter throws ServletException, IOException { handleRequest(request, response); } + + @Override + protected void doTrace(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + handleRequest(request, response); + } /** * {@inheritDoc} diff --git a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/Library.java b/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/Library.java index 53fe0bd..37da1f7 100644 --- a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/Library.java +++ b/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/Library.java @@ -63,4 +63,9 @@ public class Library implements LibraryApi { public Catalog catalog() { return new Catalog(); } + + @Override + public Response traceBooks() { + return Response.status(Status.NOT_ACCEPTABLE).build(); + } } diff --git a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/LibraryApi.java b/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/LibraryApi.java index 911214d..01af5c7 100644 --- a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/LibraryApi.java +++ b/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/resources/LibraryApi.java @@ -29,6 +29,8 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import org.apache.cxf.jaxrs.ext.TRACE; + public interface LibraryApi { @Produces({ MediaType.APPLICATION_JSON }) @GET @@ -44,4 +46,8 @@ public interface LibraryApi { @Path("/catalog") Catalog catalog(); + + @TRACE + @Produces({ MediaType.APPLICATION_JSON }) + Response traceBooks(); } diff --git a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsTest.java b/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsTest.java index 3f77f8f..82769dc 100644 --- a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsTest.java +++ b/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsTest.java @@ -29,6 +29,7 @@ import javax.ws.rs.ProcessingException; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; @@ -45,7 +46,9 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.rule.OutputCapture; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -108,6 +111,13 @@ public class SpringJaxrsTest { public JacksonJsonProvider jacksonJsonProvider() { return new JacksonJsonProvider(); } + + @Bean + public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() { + return customizer -> customizer.addConnectorCustomizers(connector -> { + connector.setAllowTrace(true); + }); + } } @Before @@ -421,6 +431,47 @@ public class SpringJaxrsTest { entry("status", "UNKNOWN")); } + @Test + public void testJaxrsCustomHttpMethodMetric() { + final WebTarget target = createWebTarget(); + + try (Response r = target.request().trace()) { + assertThat(r.getStatus()).isEqualTo(Status.NOT_ACCEPTABLE.getStatusCode()); + } + + await() + .atMost(Duration.ofSeconds(1)) + .ignoreException(MeterNotFoundException.class) + .until(() -> registry.get("cxf.server.requests").timers(), not(empty())); + RequiredSearch serverRequestMetrics = registry.get("cxf.server.requests"); + + Map<Object, Object> serverTags = serverRequestMetrics.timer().getId().getTags().stream() + .collect(toMap(Tag::getKey, Tag::getValue)); + + assertThat(serverTags) + .containsOnly( + entry("exception", "None"), + entry("method", "TRACE"), + entry("operation", "traceBooks"), + entry("uri", "/api/library"), + entry("outcome", "CLIENT_ERROR"), + entry("status", "406")); + + RequiredSearch clientRequestMetrics = registry.get("cxf.client.requests"); + + Map<Object, Object> clientTags = clientRequestMetrics.timer().getId().getTags().stream() + .collect(toMap(Tag::getKey, Tag::getValue)); + + assertThat(clientTags) + .containsOnly( + entry("exception", "None"), + entry("method", "TRACE"), + entry("operation", "UNKNOWN"), + entry("uri", "http://localhost:" + port + "/api/library"), + entry("outcome", "CLIENT_ERROR"), + entry("status", "406")); + } + private LibraryApi createApi(int portToUse) { final JAXRSClientFactoryBean factory = new JAXRSClientFactoryBean(); factory.setAddress("http://localhost:" + portToUse + "/api/library");
