Protect the DefaultServlet against Filters etc writing to the response which will...
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Wed, 30 Mar 2011 12:04:48 +0000 (12:04 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Wed, 30 Mar 2011 12:04:48 +0000 (12:04 +0000)
This also fixers some TCK failures since the TCK sometimes writes to the response with a filter.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1086918 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/connector/ResponseFacade.java
java/org/apache/catalina/servlets/DefaultServlet.java
webapps/docs/changelog.xml

index 989ebb3..0f5d794 100644 (file)
@@ -163,6 +163,16 @@ public class ResponseFacade
     }
 
 
+    public long getContentWritten() {
+
+        if (response == null) {
+            throw new IllegalStateException(
+                            sm.getString("responseFacade.nullResponse"));
+        }
+
+        return response.getContentWritten();
+    }
+
     // ------------------------------------------------ ServletResponse Methods
 
 
index 6086fb1..4fd5591 100644 (file)
@@ -47,6 +47,8 @@ import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletResponse;
+import javax.servlet.ServletResponseWrapper;
 import javax.servlet.UnavailableException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -60,6 +62,7 @@ import javax.xml.transform.stream.StreamSource;
 
 import org.apache.catalina.Globals;
 import org.apache.catalina.connector.RequestFacade;
+import org.apache.catalina.connector.ResponseFacade;
 import org.apache.catalina.util.RequestUtil;
 import org.apache.catalina.util.ServerInfo;
 import org.apache.catalina.util.URLEncoder;
@@ -885,6 +888,21 @@ public class DefaultServlet
 
         }
 
+        // Check to see if a Filter, Valve of wrapper has written some content.
+        // If it has, disable range requests and setting of a content length
+        // since neither can be done reliably.
+        ServletResponse r = response;
+        long contentWritten = 0;
+        while (r instanceof ServletResponseWrapper) {
+            r = ((ServletResponseWrapper) r).getResponse();
+        }
+        if (r instanceof ResponseFacade) {
+            contentWritten = ((ResponseFacade) r).getContentWritten();
+        }
+        if (contentWritten > 0) {
+            ranges = FULL;
+        }
+        
         if ( (cacheEntry.context != null)
                 || isError
                 || ( ((ranges == null) || (ranges.isEmpty()))
@@ -903,11 +921,17 @@ public class DefaultServlet
                 if (debug > 0)
                     log("DefaultServlet.serveFile:  contentLength=" +
                         contentLength);
-                if (contentLength < Integer.MAX_VALUE) {
-                    response.setContentLength((int) contentLength);
-                } else {
-                    // Set the content-length as String to be able to use a long
-                    response.setHeader("content-length", "" + contentLength);
+                // Don't set a content length if something else has already
+                // written to the response.
+                if (contentWritten > 0) {
+                    if (contentLength < Integer.MAX_VALUE) {
+                        response.setContentLength((int) contentLength);
+                    } else {
+                        // Set the content-length as String to be able to use a
+                        // long
+                        response.setHeader("content-length",
+                                "" + contentLength);
+                    }
                 }
             }
 
index 09e61a3..2df4ab1 100644 (file)
         HTTP range requests cannot be reliably served when a Writer is in use so
         prevent the DefaultServlet from attempting to do so. (kkolinko)
       </fix>
+      <fix>
+        Protect the DefaultServlet from Valves, Filters and Wrappers that write
+        content to the response. Prevent partial responses to partial GET
+        requests in this case since the range cannot be reliably determined.
+        Also prevent the DefaultServlet from setting a content length header
+        since this too cannot be reliably determined. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">