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

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new 48df571e7f Implement the new sendRedirect() methods in Servlet 6.1
48df571e7f is described below

commit 48df571e7f8b0f4afe0353b559b6844d637c7c56
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Mar 14 14:15:54 2023 +0000

    Implement the new sendRedirect() methods in Servlet 6.1
---
 java/jakarta/servlet/http/HttpServletResponse.java | 97 +++++++++++++++++++---
 .../servlet/http/HttpServletResponseWrapper.java   | 30 ++++++-
 java/org/apache/catalina/connector/Response.java   | 30 ++-----
 .../apache/catalina/connector/ResponseFacade.java  |  4 +-
 .../catalina/core/ApplicationHttpResponse.java     | 12 +--
 .../filters/TesterHttpServletResponse.java         |  2 +-
 webapps/docs/changelog.xml                         |  4 +
 7 files changed, 132 insertions(+), 47 deletions(-)

diff --git a/java/jakarta/servlet/http/HttpServletResponse.java 
b/java/jakarta/servlet/http/HttpServletResponse.java
index daacbc212b..a1757dbc71 100644
--- a/java/jakarta/servlet/http/HttpServletResponse.java
+++ b/java/jakarta/servlet/http/HttpServletResponse.java
@@ -112,22 +112,99 @@ public interface HttpServletResponse extends 
ServletResponse {
     void sendError(int sc) throws IOException;
 
     /**
-     * Sends a temporary redirect response to the client using the specified 
redirect location URL. This method can
-     * accept relative URLs; the servlet container must convert the relative 
URL to an absolute URL before sending the
-     * response to the client. If the location is relative without a leading 
'/' the container interprets it as relative
-     * to the current request URI. If the location is relative with a leading 
'/' the container interprets it as
-     * relative to the servlet container root.
+     * Sends a redirect response to the client using the specified redirect 
location URL with the status code
+     * {@link #SC_FOUND} 302 (Found), clears the response buffer and commits 
the response. The response buffer will be
+     * replaced with a short hypertext note as per RFC 9110.
+     * <p>
+     * This method has no effect if called from an include.
+     *
+     * @param location the redirect location URL (may be absolute or relative)
+     *
+     * @exception IOException              If an input or output exception 
occurs
+     * @exception IllegalArgumentException If a relative URL is given and 
cannot be converted into an absolute URL
+     * @exception IllegalStateException    If the response was already 
committed when this method was called
+     *
+     * @see #sendRedirect(String, int, boolean)
+     */
+    default void sendRedirect(String location) throws IOException {
+        sendRedirect(location, SC_FOUND, true);
+    }
+
+    /**
+     * Sends a redirect response to the client using the specified redirect 
location URL with the status code
+     * {@link #SC_FOUND} 302 (Found), optionally clears the response buffer 
and commits the response. If the response
+     * buffer is cleared, it will be replaced with a short hypertext note as 
per RFC 9110.
+     * <p>
+     * This method has no effect if called from an include.
+     *
+     * @param location    the redirect location URL (may be absolute or 
relative)
+     * @param clearBuffer if {@code true}, clear the buffer and replace it 
with the data set by this method otherwise
+     *                        retain the existing buffer
+     *
+     * @exception IOException              If an input or output exception 
occurs
+     * @exception IllegalArgumentException If a relative URL is given and 
cannot be converted into an absolute URL
+     * @exception IllegalStateException    If the response was already 
committed when this method was called
+     *
+     * @see #sendRedirect(String, int, boolean)
+     */
+    default void sendRedirect(String location, boolean clearBuffer) throws 
IOException {
+        sendRedirect(location, SC_FOUND, clearBuffer);
+    }
+
+    /**
+     * Sends a redirect response to the client using the specified redirect 
location URL and status code, clears the
+     * response buffer and commits the response. The response buffer will be 
replaced with a short hypertext note as per
+     * RFC 9110.
+     * <p>
+     * This method has no effect if called from an include.
+     *
+     * @param location the redirect location URL (may be absolute or relative)
+     * @param sc       the status code to use for the redirect
+     *
+     * @exception IOException              If an input or output exception 
occurs
+     * @exception IllegalArgumentException If a relative URL is given and 
cannot be converted into an absolute URL
+     * @exception IllegalStateException    If the response was already 
committed when this method was called
+     *
+     * @see #sendRedirect(String, int, boolean)
+     */
+    default void sendRedirect(String location, int sc) throws IOException {
+        sendRedirect(location, sc, true);
+    }
+
+    /**
+     * Sends a redirect response to the client using the specified redirect 
location URL and status code, optionally
+     * clears the response buffer and commits the response. If the response 
buffer is cleared, it will be replaced with
+     * a short hypertext note as per RFC 9110.
+     * <p>
+     * This method has no effect if called from an include.
+     * <p>
+     * This method accepts both relative and absolute URLs. Absolute URLs 
passed to this method are used as provided as
+     * the redirect location URL. Relative URLs are converted to absolute URLs 
unless a container specific
+     * feature/option is provided that controls whether relative URLs passed 
to this method are converted to absolute
+     * URLs or used as provided for the redirect location URL. If converting a 
relative URL to an absolute URL then:
+     * <ul>
+     * <li>If the location is relative without a leading '/' the container 
interprets it as relative to the current
+     * request URI.</li>
+     * <li>If the location is relative with a leading '/' the container 
interprets it as relative to the servlet
+     * container root.</li>
+     * <li>If the location is relative with two leading '/' the container 
interprets it as a network-path reference (see
+     * <a href="http://www.ietf.org/rfc/rfc3986.txt";> RFC 3986: Uniform 
Resource Identifier (URI): Generic Syntax</a>,
+     * section 4.2 &quot;Relative Reference&quot;).</li>
+     * </ul>
      * <p>
      * If the response has already been committed, this method throws an 
IllegalStateException. After using this method,
      * the response should be considered to be committed and should not be 
written to.
      *
-     * @param location the redirect location URL
+     * @param location    the redirect location URL (may be absolute or 
relative)
+     * @param sc          the status code to use for the redirect
+     * @param clearBuffer if {@code true}, clear the buffer and replace it 
with the data set by this method otherwise
+     *                        retain the existing buffer
      *
-     * @exception IOException           If an input or output exception occurs
-     * @exception IllegalStateException If the response was committed or if a 
partial URL is given and cannot be
-     *                                      converted into a valid URL
+     * @exception IOException              If an input or output exception 
occurs
+     * @exception IllegalArgumentException If a relative URL is given and 
cannot be converted into an absolute URL
+     * @exception IllegalStateException    If the response was already 
committed when this method was called
      */
-    void sendRedirect(String location) throws IOException;
+    void sendRedirect(String location, int sc, boolean clearBuffer) throws 
IOException;
 
     /**
      * Sets a response header with the given name and date-value. The date is 
specified in terms of milliseconds since
diff --git a/java/jakarta/servlet/http/HttpServletResponseWrapper.java 
b/java/jakarta/servlet/http/HttpServletResponseWrapper.java
index e6c491e55b..2804d4795a 100644
--- a/java/jakarta/servlet/http/HttpServletResponseWrapper.java
+++ b/java/jakarta/servlet/http/HttpServletResponseWrapper.java
@@ -98,13 +98,41 @@ public class HttpServletResponseWrapper extends 
ServletResponseWrapper implement
     }
 
     /**
-     * The default behavior of this method is to return sendRedirect(String 
location) on the wrapped response object.
+     * The default behavior of this method is to call sendRedirect(String 
location) on the wrapped response object.
      */
     @Override
     public void sendRedirect(String location) throws IOException {
         this._getHttpServletResponse().sendRedirect(location);
     }
 
+    /**
+     * The default behavior of this method is to call sendRedirect(String 
location, int sc) on the wrapped response
+     * object.
+     */
+    @Override
+    public void sendRedirect(String location, int sc) throws IOException {
+        this._getHttpServletResponse().sendRedirect(location, sc);
+    }
+
+    /**
+     * The default behavior of this method is to call sendRedirect(String 
location, boolean clearBuffer) on the wrapped
+     * response object.
+     */
+    @Override
+    public void sendRedirect(String location, boolean clearBuffer) throws 
IOException {
+        this._getHttpServletResponse().sendRedirect(location, clearBuffer);
+    }
+
+    /**
+     * The default behavior of this method is to call sendRedirect(String 
location, int sc, boolean clearBuffer) on the
+     * wrapped response object.
+     */
+    @Override
+    public void sendRedirect(String location, int sc, boolean clearBuffer) 
throws IOException {
+        this._getHttpServletResponse().sendRedirect(location, sc, clearBuffer);
+    }
+
+
     /**
      * The default behavior of this method is to call setDateHeader(String 
name, long date) on the wrapped response
      * object.
diff --git a/java/org/apache/catalina/connector/Response.java 
b/java/org/apache/catalina/connector/Response.java
index 9ba8a399c6..e96cd9298c 100644
--- a/java/org/apache/catalina/connector/Response.java
+++ b/java/org/apache/catalina/connector/Response.java
@@ -1222,30 +1222,8 @@ public class Response implements HttpServletResponse {
     }
 
 
-    /**
-     * Send a temporary redirect to the specified redirect location URL.
-     *
-     * @param location Location URL to redirect to
-     *
-     * @exception IllegalStateException if this response has already been 
committed
-     * @exception IOException           if an input/output error occurs
-     */
     @Override
-    public void sendRedirect(String location) throws IOException {
-        sendRedirect(location, SC_FOUND);
-    }
-
-
-    /**
-     * Internal method that allows a redirect to be sent with a status other 
than {@link HttpServletResponse#SC_FOUND}
-     * (302). No attempt is made to validate the status code.
-     *
-     * @param location Location URL to redirect to
-     * @param status   HTTP status code that will be sent
-     *
-     * @throws IOException an IO exception occurred
-     */
-    public void sendRedirect(String location, int status) throws IOException {
+    public void sendRedirect(String location, int status, boolean clearBuffer) 
throws IOException {
         if (isCommitted()) {
             throw new 
IllegalStateException(sm.getString("coyoteResponse.sendRedirect.ise"));
         }
@@ -1256,7 +1234,9 @@ public class Response implements HttpServletResponse {
         }
 
         // Clear any data content that has been buffered
-        resetBuffer(true);
+        if (clearBuffer) {
+            resetBuffer(true);
+        }
 
         // Generate a temporary redirect to the specified location
         try {
@@ -1274,7 +1254,7 @@ public class Response implements HttpServletResponse {
             }
             setStatus(status);
             setHeader("Location", locationUri);
-            if (context != null && context.getSendRedirectBody()) {
+            if (clearBuffer && context != null && 
context.getSendRedirectBody()) {
                 PrintWriter writer = getWriter();
                 writer.print(sm.getString("coyoteResponse.sendRedirect.note", 
Escape.htmlElementContent(locationUri)));
                 flushBuffer();
diff --git a/java/org/apache/catalina/connector/ResponseFacade.java 
b/java/org/apache/catalina/connector/ResponseFacade.java
index 1ffcdf593e..accfbbd00b 100644
--- a/java/org/apache/catalina/connector/ResponseFacade.java
+++ b/java/org/apache/catalina/connector/ResponseFacade.java
@@ -272,10 +272,10 @@ public class ResponseFacade implements 
HttpServletResponse {
 
 
     @Override
-    public void sendRedirect(String location) throws IOException {
+    public void sendRedirect(String location, int sc, boolean clearBuffer) 
throws IOException {
         checkCommitted("coyoteResponse.sendRedirect.ise");
         response.setAppCommitted(true);
-        response.sendRedirect(location);
+        response.sendRedirect(location, sc, clearBuffer);
     }
 
 
diff --git a/java/org/apache/catalina/core/ApplicationHttpResponse.java 
b/java/org/apache/catalina/core/ApplicationHttpResponse.java
index 73ae1eddf6..75f882fff2 100644
--- a/java/org/apache/catalina/core/ApplicationHttpResponse.java
+++ b/java/org/apache/catalina/core/ApplicationHttpResponse.java
@@ -257,19 +257,15 @@ class ApplicationHttpResponse extends 
HttpServletResponseWrapper {
 
 
     /**
+     * {@inheritDoc}
+     * <p>
      * Disallow <code>sendRedirect()</code> calls on an included response.
-     *
-     * @param location The new location
-     *
-     * @exception IOException if an input/output error occurs
      */
     @Override
-    public void sendRedirect(String location) throws IOException {
-
+    public void sendRedirect(String location, int sc, boolean clearBuffer) 
throws IOException {
         if (!included) {
-            ((HttpServletResponse) getResponse()).sendRedirect(location);
+            ((HttpServletResponse) getResponse()).sendRedirect(location, sc, 
clearBuffer);
         }
-
     }
 
 
diff --git a/test/org/apache/catalina/filters/TesterHttpServletResponse.java 
b/test/org/apache/catalina/filters/TesterHttpServletResponse.java
index a440da7837..aa9b00a28c 100644
--- a/test/org/apache/catalina/filters/TesterHttpServletResponse.java
+++ b/test/org/apache/catalina/filters/TesterHttpServletResponse.java
@@ -349,7 +349,7 @@ public class TesterHttpServletResponse implements 
HttpServletResponse {
     }
 
     @Override
-    public void sendRedirect(String location) throws IOException {
+    public void sendRedirect(String location, int sc, boolean clearBuffer) 
throws IOException {
         /* NOOP */}
 
     @Override
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 1204011225..fdaab5447c 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -133,6 +133,10 @@
         <code>authenticationSessionTimeout</code> attribute of the FORM
         authenticator. (markt)
       </add>
+      <add>
+        Implement the new Servlet API methods that provide additional control
+        when sending a redirect to the client. (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Coyote">


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to