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 <[email protected]>
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 "Relative Reference").</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: [email protected]
For additional commands, e-mail: [email protected]