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

cziegeler pushed a commit to branch sling-13421-header-only-media-ranges
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-api.git

commit d7609ee823f86e4589c9a108904093e48ea23c5c
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Wed Nov 11 13:08:03 2026 +0100

    SLING-13421 Add header-only Jakarta media range parsing
    
    Co-authored-by: Copilot <[email protected]>
---
 .../api/request/header/JakartaMediaRangeList.java  | 40 ++++++++++++++++++++++
 .../sling/api/request/header/package-info.java     |  2 +-
 .../request/header/JakartaMediaRangeListTest.java  | 31 +++++++++++++++++
 3 files changed, 72 insertions(+), 1 deletion(-)

diff --git 
a/src/main/java/org/apache/sling/api/request/header/JakartaMediaRangeList.java 
b/src/main/java/org/apache/sling/api/request/header/JakartaMediaRangeList.java
index bc7bf5d..3b6dbe6 100644
--- 
a/src/main/java/org/apache/sling/api/request/header/JakartaMediaRangeList.java
+++ 
b/src/main/java/org/apache/sling/api/request/header/JakartaMediaRangeList.java
@@ -25,6 +25,7 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import jakarta.servlet.http.HttpServletRequest;
+import org.jetbrains.annotations.NotNull;
 import org.osgi.annotation.versioning.ConsumerType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -37,13 +38,40 @@ import org.slf4j.LoggerFactory;
 @ConsumerType
 public class JakartaMediaRangeList extends 
TreeSet<JakartaMediaRangeList.MediaRange> {
 
+    /**
+     * The HTTP header name for the Accept header.
+     */
     public static final String HEADER_ACCEPT = "Accept";
+
+    /**
+     * The request parameter name for the Accept header override.
+     * @deprecated Use {@link #HEADER_ACCEPT} instead.
+     */
+    @Deprecated
     public static final String PARAM_ACCEPT = ":http-equiv-accept";
+
+    /**
+     * The wildcard character for media ranges.
+     */
     public static final String WILDCARD = "*";
+
     boolean matchesAll = false;
 
     private static final Logger log = 
LoggerFactory.getLogger(JakartaMediaRangeList.class);
 
+    /**
+     * Creates a <code>MediaRangeList</code> from the {@link #HEADER_ACCEPT} 
header of the supplied request.
+     * Request parameters, including {@link #PARAM_ACCEPT}, are ignored.
+     * If the header is missing or empty, the client is assumed to accept all 
media types.
+     *
+     * @param request The request to read the Accept header from
+     * @return The media ranges accepted by the client
+     * @since 1.2.0
+     */
+    public static @NotNull JakartaMediaRangeList fromRequest(@NotNull 
HttpServletRequest request) {
+        return new JakartaMediaRangeList(request.getHeader(HEADER_ACCEPT));
+    }
+
     /**
      * Constructs a <code>MediaRangeList</code> using information from the 
supplied <code>HttpServletRequest</code>.
      * if the request contains a {@link #PARAM_ACCEPT} query parameter, the 
query parameter value overrides any
@@ -52,7 +80,10 @@ public class JakartaMediaRangeList extends 
TreeSet<JakartaMediaRangeList.MediaRa
      * {@link #HEADER_ACCEPT} is used. If both values are missing, it is 
assumed that the client accepts all media types,
      * as per the RFC. See also {@link 
#JakartaMediaRangeList(java.lang.String)}
      * @param request The <code>HttpServletRequest</code> to extract a 
<code>MediaRangeList</code> from
+     * @deprecated Use {@link #fromRequest(HttpServletRequest)} to read only 
the Accept header without
+     * allowing request parameters to override it.
      */
+    @Deprecated
     public JakartaMediaRangeList(HttpServletRequest request) {
         String queryParam = request.getParameter(PARAM_ACCEPT);
         if (queryParam != null && queryParam.trim().length() != 0) {
@@ -106,6 +137,15 @@ public class JakartaMediaRangeList extends 
TreeSet<JakartaMediaRangeList.MediaRa
         }
     }
 
+    /**
+     * Whether this <code>MediaRangeList</code> matches all media types.
+     * @return <code>true</code> if this <code>MediaRangeList</code> matches 
all media types, <code>false</code> otherwise
+     * @since 1.2.0
+     */
+    public boolean matchesAll() {
+        return this.matchesAll;
+    }
+
     /**
      * Determines if this MediaRangeList contains a given media type.
      * @param mediaType A string on the form <code>type/subtype</code>. 
Neither <code>type</code>
diff --git 
a/src/main/java/org/apache/sling/api/request/header/package-info.java 
b/src/main/java/org/apache/sling/api/request/header/package-info.java
index a7085e2..09b8624 100644
--- a/src/main/java/org/apache/sling/api/request/header/package-info.java
+++ b/src/main/java/org/apache/sling/api/request/header/package-info.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-@Version("1.1.0")
+@Version("1.2.0")
 package org.apache.sling.api.request.header;
 
 import org.osgi.annotation.versioning.Version;
diff --git 
a/src/test/java/org/apache/sling/api/request/header/JakartaMediaRangeListTest.java
 
b/src/test/java/org/apache/sling/api/request/header/JakartaMediaRangeListTest.java
index c30034f..954d67d 100644
--- 
a/src/test/java/org/apache/sling/api/request/header/JakartaMediaRangeListTest.java
+++ 
b/src/test/java/org/apache/sling/api/request/header/JakartaMediaRangeListTest.java
@@ -22,6 +22,7 @@ import junit.framework.TestCase;
 import org.apache.sling.api.SlingJakartaHttpServletRequest;
 import org.mockito.Mockito;
 
+@SuppressWarnings("deprecation")
 public class JakartaMediaRangeListTest extends TestCase {
     protected JakartaMediaRangeList rangeList;
 
@@ -55,6 +56,36 @@ public class JakartaMediaRangeListTest extends TestCase {
         assertFalse("Contained media type from overridden Accept header", 
rangeList.contains("text/plain"));
     }
 
+    public void testFromRequestIgnoresHttpEquivParam() {
+        SlingJakartaHttpServletRequest req = 
Mockito.mock(SlingJakartaHttpServletRequest.class);
+        Mockito.when(req.getHeader(JakartaMediaRangeList.HEADER_ACCEPT))
+                .thenReturn("text/plain;q=0.8, application/json");
+        
Mockito.when(req.getParameter(JakartaMediaRangeList.PARAM_ACCEPT)).thenReturn("text/html");
+
+        JakartaMediaRangeList rangeList = 
JakartaMediaRangeList.fromRequest(req);
+
+        assertEquals("text/plain", rangeList.prefer("text/plain"));
+        assertTrue(rangeList.contains("application/json"));
+        assertFalse(rangeList.contains("text/html"));
+        assertEquals("application/json", rangeList.prefer("text/plain", 
"application/json"));
+        Mockito.verify(req, Mockito.never()).getParameter(Mockito.anyString());
+    }
+
+    public void testFromRequestWithoutAcceptHeader() {
+        for (String header : new String[] {null, "", "  "}) {
+            SlingJakartaHttpServletRequest req = 
Mockito.mock(SlingJakartaHttpServletRequest.class);
+            
Mockito.when(req.getHeader(JakartaMediaRangeList.HEADER_ACCEPT)).thenReturn(header);
+            
Mockito.when(req.getParameter(JakartaMediaRangeList.PARAM_ACCEPT)).thenReturn("text/html");
+
+            JakartaMediaRangeList rangeList = 
JakartaMediaRangeList.fromRequest(req);
+
+            assertEquals(1, rangeList.size());
+            assertTrue(rangeList.contains("text/plain"));
+            assertTrue(rangeList.contains("application/json"));
+            Mockito.verify(req, 
Mockito.never()).getParameter(Mockito.anyString());
+        }
+    }
+
     public void testInvalidJdkAcceptHeader() {
         // This header is sent by Java client which make use of URLConnection 
on Oracle JDK
         // See acceptHeader at

Reply via email to