This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new ea7ea0c  CXF-8620: AbstractHTTPServlet should support HTTP TRACE 
method dispatching if it is allowed by underlying container (#879)
ea7ea0c is described below

commit ea7ea0c32683af9973f9897049f024c50ec6afa3
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)
---
 .../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 ++++++++++++++++++++++
 .../netty/AbstractNettyClientServerHttp2Test.java  | 38 +++++++++++++---
 .../apache/cxf/systest/http2/netty/BookStore.java  | 12 +++++
 .../cxf/systest/http2/netty/Http2TestClient.java   |  4 ++
 8 files changed, 127 insertions(+), 29 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 32e1797..e32f6bc 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;
 
@@ -44,7 +45,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 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.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.test.context.ActiveProfiles;
@@ -94,6 +97,13 @@ public class SpringJaxrsTest {
         public JacksonJsonProvider jacksonJsonProvider() {
             return new JacksonJsonProvider();
         }
+        
+        @Bean
+        public WebServerFactoryCustomizer<TomcatServletWebServerFactory> 
tomcatCustomizer() {
+            return customizer -> customizer.addConnectorCustomizers(connector 
-> {
+                connector.setAllowTrace(true);
+            });
+        }
     }
 
     @Autowired
@@ -413,6 +423,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");
diff --git 
a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractNettyClientServerHttp2Test.java
 
b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractNettyClientServerHttp2Test.java
index 1263377..5945b1f 100644
--- 
a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractNettyClientServerHttp2Test.java
+++ 
b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/AbstractNettyClientServerHttp2Test.java
@@ -51,6 +51,21 @@ abstract class AbstractNettyClientServerHttp2Test extends 
AbstractBusClientServe
     }
     
     @Test
+    public void testBookTraceWithHttp2() throws Exception {
+        final Http2TestClient client = new Http2TestClient(isSecure());
+        
+        final ClientResponse response = client
+            .request(getAddress())
+            .accept("text/plain")
+            .path(getContext() + "/web/bookstore/trace")
+            .http2()
+            .trace();
+        
+        assertThat(response.getResponseCode(), equalTo(406));
+        assertThat(response.getProtocol(), equalTo("HTTP/2.0"));
+    }
+    
+    @Test
     public void testBookWithHttp2() throws Exception {
         final Http2TestClient client = new Http2TestClient(isSecure());
         
@@ -85,8 +100,24 @@ abstract class AbstractNettyClientServerHttp2Test extends 
AbstractBusClientServe
 
     @Test
     public void testBookWithHttp() throws Exception {
+        final WebClient wc = createWebClient("/web/bookstore/booknames");
+        try (Response resp = wc.get()) {
+            assertThat(resp.getStatus(), equalTo(200));
+            assertEquals("CXF in Action", resp.readEntity(String.class));
+        }
+    }
+
+    @Test
+    public void testBookTraceWithHttp() throws Exception {
+        final WebClient wc = createWebClient("/web/bookstore/trace");
+        try (Response response = wc.invoke("TRACE", null)) {
+            assertThat(response.getStatus(), equalTo(406));
+        }        
+    }
+
+    private WebClient createWebClient(final String path) {
         final WebClient wc = WebClient
-            .create(getAddress() + getContext() + "/web/bookstore/booknames")
+            .create(getAddress() + getContext() + path)
             .accept("text/plain");
         
         if (isSecure()) {
@@ -103,10 +134,7 @@ abstract class AbstractNettyClientServerHttp2Test extends 
AbstractBusClientServe
             params.setDisableCNCheck(true);
         }
         
-        try (Response resp = wc.get()) {
-            assertThat(resp.getStatus(), equalTo(200));
-            assertEquals("CXF in Action", resp.readEntity(String.class));
-        }
+        return wc;
     }
 
     protected abstract String getAddress();
diff --git 
a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookStore.java
 
b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookStore.java
index 4b4e1ca..4715c02 100644
--- 
a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookStore.java
+++ 
b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/BookStore.java
@@ -23,11 +23,15 @@ import java.io.IOException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
+import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
 
 import org.apache.cxf.jaxrs.ext.StreamingResponse;
+import org.apache.cxf.jaxrs.ext.TRACE;
 
 @Path("/web/bookstore")
 public class BookStore {
@@ -63,6 +67,14 @@ public class BookStore {
             }
         };
     }
+    
+    @TRACE
+    @Produces("application/xml")
+    @Consumes("application/xml")
+    @Path("/trace")
+    public Response traceBook() {
+        return Response.status(Status.NOT_ACCEPTABLE).build();
+    }
 }
 
 
diff --git 
a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Http2TestClient.java
 
b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Http2TestClient.java
index 32e4e64..b88e610 100644
--- 
a/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Http2TestClient.java
+++ 
b/systests/transport-netty/src/test/java/org/apache/cxf/systest/http2/netty/Http2TestClient.java
@@ -163,6 +163,10 @@ public class Http2TestClient implements AutoCloseable {
         public ClientResponse get() throws Exception {
             return request(address, path, version, HttpMethod.GET, accept);
         }
+        
+        public ClientResponse trace() throws Exception {
+            return request(address, path, version, HttpMethod.TRACE, accept);
+        }
     }
     
     public RequestBuilder request(final String address) throws IOException {

Reply via email to