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

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


The following commit(s) were added to refs/heads/master by this push:
     new 2b694ff  SLING-13322 warnings on non-spec compliant behavior (#82)
2b694ff is described below

commit 2b694ff1558e4f4fd5f14c52e2156d6400e09215
Author: Jörg Hoh <[email protected]>
AuthorDate: Tue Sep 1 20:53:12 2026 +0200

    SLING-13322 warnings on non-spec compliant behavior (#82)
    
    log warnings when during an include a header-modifying operation is tried, 
which is not
    allowed by the Servlet spec.
---
 .../impl/SlingJakartaHttpServletResponseImpl.java  | 33 ++++++++++++++++++++++
 .../impl/SlingHttpServletResponseImplTest.java     |  2 ++
 2 files changed, 35 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 4c197d4..406d39e 100644
--- 
a/src/main/java/org/apache/sling/engine/impl/SlingJakartaHttpServletResponseImpl.java
+++ 
b/src/main/java/org/apache/sling/engine/impl/SlingJakartaHttpServletResponseImpl.java
@@ -210,6 +210,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
                         explanation);
             }
         } else { // response is not yet committed, so the statuscode can be 
changed
+            logHeaderModificationCallOnIncludeForMethod("setStatus");
             super.setStatus(sc);
         }
     }
@@ -217,6 +218,9 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void reset() {
         if (!this.isProtectHeadersOnInclude() || isError()) {
+            if (!this.isProtectHeadersOnInclude()) {
+                logHeaderModificationCallOnIncludeForMethod("reset");
+            }
             super.reset();
         } else {
             // ignore if not committed: because we want the exception to be 
thrown when the
@@ -231,6 +235,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void setContentLength(final int len) {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("setContentLength()");
             super.setContentLength(len);
         }
     }
@@ -238,6 +243,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void setContentLengthLong(final long len) {
         if (!this.isProtectHeadersOnInclude()) {
+            
logHeaderModificationCallOnIncludeForMethod("setContentLengthLong()");
             super.setContentLengthLong(len);
         }
     }
@@ -245,6 +251,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void setLocale(final Locale loc) {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("setLocale()");
             super.setLocale(loc);
         }
     }
@@ -252,6 +259,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void addCookie(final Cookie cookie) {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("addCookie()");
             super.addCookie(cookie);
         }
     }
@@ -259,6 +267,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void addDateHeader(final String name, final long value) {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("addDateHeader()");
             super.addDateHeader(name, value);
         }
     }
@@ -266,6 +275,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void addHeader(final String name, final String value) {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("addHeader()");
             super.addHeader(name, value);
         }
     }
@@ -273,6 +283,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void addIntHeader(final String name, final int value) {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("addIntHeader()");
             super.addIntHeader(name, value);
         }
     }
@@ -280,6 +291,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void sendRedirect(final String location) throws IOException {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("sendRedirect");
             this.committedReason = CommitReason.SEND_REDIRECT;
             super.sendRedirect(location);
         }
@@ -288,6 +300,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void setDateHeader(final String name, final long value) {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("setDateHeader()");
             super.setDateHeader(name, value);
         }
     }
@@ -295,6 +308,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void setHeader(final String name, final String value) {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("setHeader()");
             super.setHeader(name, value);
         }
     }
@@ -302,6 +316,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void setIntHeader(final String name, final int value) {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("setIntHeader()");
             super.setIntHeader(name, value);
         }
     }
@@ -492,6 +507,23 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
                 allMessages);
     }
 
+    /**
+     * log a message for calling a header-modifying API when called as part of 
an include
+     * @param method the name of the method
+     */
+    private void logHeaderModificationCallOnIncludeForMethod(String method) {
+        if (isInclude()) {
+            String msg = String.format(
+                    "Calling '%s' within an include is not compliant to the 
Servlet spec (see SLING-13222)", method);
+            requestData.getRequestProgressTracker().log("WARN:" + msg);
+            if (!LOG.isDebugEnabled()) {
+                LOG.warn("{}; enable DEBUG logging to get the full 
stacktrace", msg);
+            } else {
+                LOG.warn("{}; call trace: {} ", msg, getCurrentStackTrace());
+            }
+        }
+    }
+
     private static class ContentTypeChangeException extends SlingException {
         protected ContentTypeChangeException(String text) {
             super(text);
@@ -510,6 +542,7 @@ public class SlingJakartaHttpServletResponseImpl extends 
HttpServletResponseWrap
     @Override
     public void sendError(int status, String message) throws IOException {
         if (!this.isProtectHeadersOnInclude()) {
+            logHeaderModificationCallOnIncludeForMethod("setError()");
             checkCommitted();
 
             this.committedReason = CommitReason.SEND_ERROR;
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 88845c7..b14bc5b 100644
--- 
a/src/test/java/org/apache/sling/engine/impl/SlingHttpServletResponseImplTest.java
+++ 
b/src/test/java/org/apache/sling/engine/impl/SlingHttpServletResponseImplTest.java
@@ -94,6 +94,7 @@ public class SlingHttpServletResponseImplTest {
         final RequestData requestData = mock(RequestData.class);
         final DispatchingInfo info = new 
DispatchingInfo(DispatcherType.INCLUDE);
         when(requestData.getDispatchingInfo()).thenReturn(info);
+        
when(requestData.getRequestProgressTracker()).thenReturn(mock(RequestProgressTracker.class));
 
         final SlingJakartaHttpServletResponseImpl include = new 
SlingJakartaHttpServletResponseImpl(requestData, orig);
         SlingJakartaHttpServletResponseImpl spyInclude = Mockito.spy(include);
@@ -113,6 +114,7 @@ public class SlingHttpServletResponseImplTest {
         final DispatchingInfo info = new 
DispatchingInfo(DispatcherType.INCLUDE);
         when(requestData.getDispatchingInfo()).thenReturn(info);
         
when(requestData.getSlingRequestProcessor()).thenReturn(mock(SlingRequestProcessorImpl.class));
+        
when(requestData.getRequestProgressTracker()).thenReturn(mock(RequestProgressTracker.class));
 
         final SlingJakartaHttpServletResponseImpl include = new 
SlingJakartaHttpServletResponseImpl(requestData, orig);
         SlingJakartaHttpServletResponseImpl spyInclude = Mockito.spy(include);

Reply via email to