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 {