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

joerghoh pushed a commit to branch SLING-13351
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-engine.git

commit 50d2118b8de151960bd44ec1ace0aee32ff7b17d
Author: Joerg Hoh <[email protected]>
AuthorDate: Wed Sep 16 10:37:02 2026 +0200

    SLING-13351 make content-type handling consistent
    
    the content-type can be set also via setHeader/addHeader, so in these cases 
the logic of
    setContenType should be applied.
---
 .../impl/SlingJakartaHttpServletResponseImpl.java  | 14 ++++++
 .../impl/SlingHttpServletResponseImplTest.java     | 57 ++++++++++++++++++++++
 2 files changed, 71 insertions(+)

diff --git 
a/src/main/java/org/apache/sling/engine/impl/SlingJakartaHttpServletResponseImpl.java
 
b/src/main/java/org/apache/sling/engine/impl/SlingJakartaHttpServletResponseImpl.java
index 5ed609b..2a4a19d 100644
--- 
a/src/main/java/org/apache/sling/engine/impl/SlingJakartaHttpServletResponseImpl.java
+++ 
b/src/main/java/org/apache/sling/engine/impl/SlingJakartaHttpServletResponseImpl.java
@@ -59,6 +59,8 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
 
     private static final String CALL_STACK_MESSAGE = "Call stack causing the 
content type override violation: ";
 
+    private static final String HEADER_CONTENT_TYPE = "Content-Type";
+
     private static final Logger LOG = 
LoggerFactory.getLogger(SlingJakartaHttpServletResponseImpl.class);
 
     // this regex matches TIMER_START{ followed by any characters except }, 
and then
@@ -274,6 +276,12 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
 
     @Override
     public void addHeader(final String name, final String value) {
+        if (this.isInclude() && HEADER_CONTENT_TYPE.equalsIgnoreCase(name)) {
+            // changing the Content-Type header during an include must be 
subject
+            // to the same enforcement as setContentType (see setHeader)
+            this.setContentType(value);
+            return;
+        }
         if (!this.isProtectHeadersOnInclude()) {
             logHeaderModificationCallOnIncludeForMethod("addHeader()");
             super.addHeader(name, value);
@@ -307,6 +315,12 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
 
     @Override
     public void setHeader(final String name, final String value) {
+        if (this.isInclude() && HEADER_CONTENT_TYPE.equalsIgnoreCase(name)) {
+            // changing the Content-Type header during an include must be 
subject
+            // to the same enforcement as setContentType (see setHeader)
+            this.setContentType(value);
+            return;
+        }
         if (!this.isProtectHeadersOnInclude()) {
             logHeaderModificationCallOnIncludeForMethod("setHeader()");
             super.setHeader(name, value);
diff --git 
a/src/test/java/org/apache/sling/engine/impl/SlingHttpServletResponseImplTest.java
 
b/src/test/java/org/apache/sling/engine/impl/SlingHttpServletResponseImplTest.java
index fd658f5..b2e84b3 100644
--- 
a/src/test/java/org/apache/sling/engine/impl/SlingHttpServletResponseImplTest.java
+++ 
b/src/test/java/org/apache/sling/engine/impl/SlingHttpServletResponseImplTest.java
@@ -374,6 +374,63 @@ public class SlingHttpServletResponseImplTest {
                                 
.collect(Collectors.joining(System.lineSeparator())))));
     }
 
+    @Test
+    public void testContentTypeOverrideEnforcedForSetHeader() {
+        final SlingJakartaHttpServletResponse orig = 
Mockito.mock(SlingJakartaHttpServletResponse.class);
+        final RequestData requestData = mock(RequestData.class);
+        final DispatchingInfo info = new 
DispatchingInfo(DispatcherType.INCLUDE);
+        final RequestProgressTracker requestProgressTracker = 
mock(RequestProgressTracker.class);
+        when(requestData.getDispatchingInfo()).thenReturn(info);
+        when(orig.getContentType()).thenReturn("text/plain");
+        
when(requestData.getRequestProgressTracker()).thenReturn(requestProgressTracker);
+        ArrayList<String> logMessagesList = new 
ArrayList<>(Arrays.asList(logMessages));
+        when(requestProgressTracker.getMessages()).thenAnswer(invocation -> 
logMessagesList.iterator());
+        info.setCheckContentTypeOnInclude(true);
+
+        final SlingRequestProcessorImpl requestProcessor = 
mock(SlingRequestProcessorImpl.class);
+        
when(requestData.getSlingRequestProcessor()).thenReturn(requestProcessor);
+        
when(requestData.getActiveServletName()).thenReturn(ACTIVE_SERVLET_NAME);
+
+        final HttpServletResponse include = new 
SlingJakartaHttpServletResponseImpl(requestData, orig);
+
+        Throwable setHeaderThrowable = null;
+        try {
+            include.setHeader("Content-Type", "text/html");
+        } catch (RuntimeException e) {
+            setHeaderThrowable = e;
+        }
+        assertNotNull("Expected setHeader(\"Content-Type\", ...) to be 
blocked.", setHeaderThrowable);
+
+        Throwable addHeaderThrowable = null;
+        try {
+            include.addHeader("content-type", "text/html");
+        } catch (RuntimeException e) {
+            addHeaderThrowable = e;
+        }
+        assertNotNull("Expected addHeader(\"content-type\", ...) to be 
blocked.", addHeaderThrowable);
+
+        Mockito.verify(orig, never()).setHeader(Mockito.anyString(), 
Mockito.anyString());
+        Mockito.verify(orig, never()).addHeader(Mockito.anyString(), 
Mockito.anyString());
+        Mockito.verify(orig, never()).setContentType(Mockito.anyString());
+    }
+
+    @Test
+    public void testUnrelatedHeadersNotRoutedThroughContentTypeCheck() {
+        final SlingJakartaHttpServletResponse orig = 
Mockito.mock(SlingJakartaHttpServletResponse.class);
+        final RequestData requestData = mock(RequestData.class);
+        final DispatchingInfo info = new 
DispatchingInfo(DispatcherType.INCLUDE);
+        when(requestData.getDispatchingInfo()).thenReturn(info);
+        info.setCheckContentTypeOnInclude(true);
+
+        final HttpServletResponse include = new 
SlingJakartaHttpServletResponseImpl(requestData, orig);
+
+        include.setHeader("X-Custom", "value");
+        include.addHeader("X-Custom", "another");
+
+        Mockito.verify(orig, times(1)).setHeader("X-Custom", "value");
+        Mockito.verify(orig, times(1)).addHeader("X-Custom", "another");
+    }
+
     @Test
     public void testContentTypeOverrideDisabled() {
         final SlingJakartaHttpServletResponse orig = 
Mockito.mock(SlingJakartaHttpServletResponse.class);

Reply via email to