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

reta pushed a commit to branch 3.6.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 95195443cba6571adda2093f7200e97159044ec4
Author: Andriy Redko <drr...@gmail.com>
AuthorDate: Thu Jan 18 19:47:13 2024 -0500

    CXF-8812: Content-Type header created with collection containing 'null' 
value (#1653)
---
 .../org/apache/cxf/jaxrs/impl/HttpHeadersImpl.java | 44 ++++++++++++++++++++--
 .../apache/cxf/jaxrs/impl/HttpHeadersImplTest.java | 31 +++++++++++++++
 .../org/apache/cxf/systest/jaxrs/BookStore.java    |  7 ++++
 .../systest/jaxrs/JAXRS20ClientServerBookTest.java | 19 ++++++++++
 4 files changed, 98 insertions(+), 3 deletions(-)

diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpHeadersImpl.java
 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpHeadersImpl.java
index 67fb41bb67..e3a2a57f41 100644
--- 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpHeadersImpl.java
+++ 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpHeadersImpl.java
@@ -34,6 +34,7 @@ import java.util.Set;
 import java.util.TreeMap;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 import javax.ws.rs.core.Cookie;
 import javax.ws.rs.core.HttpHeaders;
@@ -87,9 +88,46 @@ public class HttpHeadersImpl implements HttpHeaders {
     private Map<String, List<String>> headers;
     public HttpHeadersImpl(Message message) {
         this.message = message;
-        this.headers = CastUtils.cast((Map<?, 
?>)message.get(Message.PROTOCOL_HEADERS));
-        if (headers == null) {
-            headers = Collections.emptyMap();
+        this.headers = filter(CastUtils.cast((Map<?, 
?>)message.get(Message.PROTOCOL_HEADERS)));
+    }
+
+    /**
+     * Filters the protocol headers by excluding the headers that have {@code 
null} values.
+     * @param protocolHeaders protocol headers to filter
+     * @return filtered headers
+     */
+    private static Map<String, List<String>> filter(Map<String, List<String>> 
protocolHeaders) {
+        if (protocolHeaders == null) {
+            return Collections.emptyMap();
+        } else if (protocolHeaders.isEmpty()) { 
+            return protocolHeaders;
+        }
+
+        final Set<String> nullableHeader = protocolHeaders
+            .entrySet()
+            .stream()
+            .filter(e -> {
+                if (e.getValue() == null) {
+                    return true;
+                } else if (e.getValue().size() == 1) {
+                    return e.getValue().get(0) == null;
+                } else {
+                    return false;
+                }
+            })
+            .map(e -> e.getKey())
+            .collect(Collectors.toSet());
+
+        if (nullableHeader.isEmpty()) {
+            return protocolHeaders;
+        } else {
+            final Map<String, List<String>> headers = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+            for (final Map.Entry<String, List<String>> entry: 
protocolHeaders.entrySet()) {
+                if (!nullableHeader.contains(entry.getKey())) {
+                    headers.put(entry.getKey(), entry.getValue());
+                }
+            }
+            return headers;
         }
     }
 
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/HttpHeadersImplTest.java
 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/HttpHeadersImplTest.java
index c0903057fe..423cb072a8 100644
--- 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/HttpHeadersImplTest.java
+++ 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/HttpHeadersImplTest.java
@@ -41,9 +41,12 @@ import org.apache.cxf.message.MessageImpl;
 
 import org.junit.Test;
 
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
 public class HttpHeadersImplTest {
@@ -199,6 +202,34 @@ public class HttpHeadersImplTest {
         assertTrue(values.isEmpty());
     }
 
+    @Test
+    public void testGetNullHeaderValue() throws Exception {
+
+        Message m = new MessageImpl();
+        // this is what happens at runtime and is tested in the system tests
+        Map<String, List<String>> headers =
+            new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        headers.put("A", Collections.<String>singletonList(null));
+        m.put(Message.PROTOCOL_HEADERS, headers);
+        HttpHeaders h = new HttpHeadersImpl(m);
+        List<String> values = h.getRequestHeader("A");
+        assertThat(values, is(nullValue()));
+    }
+
+    @Test
+    public void testGetNullHeader() throws Exception {
+
+        Message m = new MessageImpl();
+        // this is what happens at runtime and is tested in the system tests
+        Map<String, List<String>> headers =
+            new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        headers.put("A", null);
+        m.put(Message.PROTOCOL_HEADERS, headers);
+        HttpHeaders h = new HttpHeadersImpl(m);
+        List<String> values = h.getRequestHeader("A");
+        assertThat(values, is(nullValue()));
+    }
+
     @Test
     public void testGetDate() throws Exception {
 
diff --git 
a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java 
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
index 545f362b6e..bdbbeed451 100644
--- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
@@ -1837,6 +1837,13 @@ public class BookStore {
             AnnotatedClass.class.getAnnotations()).build();
     }
     
+    @GET
+    @Path("/headers")
+    @Produces("application/json")
+    public Map<String, List<String>> getHeaders() {
+        return httpHeaders.getRequestHeaders();
+    }
+    
     public final String init() {
         books.clear();
         cds.clear();
diff --git 
a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java
 
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java
index 2f4bb40996..c66cfbe968 100644
--- 
a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java
+++ 
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java
@@ -29,6 +29,7 @@ import java.net.UnknownHostException;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
@@ -81,7 +82,9 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasKey;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -967,6 +970,22 @@ public class JAXRS20ClientServerBookTest extends 
AbstractBusClientServerTestBase
         }
     }
 
+    @Test
+    public void testGetHeaders() throws Exception {
+        final WebTarget target = ClientBuilder
+            .newClient()
+            .register(JacksonJaxbJsonProvider.class)
+            .target("http://localhost:"; + PORT + "/bookstore/headers");
+
+        @SuppressWarnings("unchecked")
+        final Map<String, Object> headers = target
+            .request().accept("application/json")
+            .get(Map.class);
+
+        assertThat(headers, hasKey("Accept"));
+        assertThat(headers, not(hasKey("Content-Type")));
+    }
+
     @Test
     public void testGetBookDateAnnotated() throws Exception {
         final String response = ClientBuilder

Reply via email to