diff --git a/core/src/main/java/org/apache/struts2/dispatcher/ServletRedirectResult.java b/core/src/main/java/org/apache/struts2/dispatcher/ServletRedirectResult.java index 635514747..9ed2a3887 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/ServletRedirectResult.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/ServletRedirectResult.java @@ -22,6 +22,7 @@ package org.apache.struts2.dispatcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import static javax.servlet.http.HttpServletResponse.*; import org.apache.struts2.ServletActionContext; import org.apache.struts2.dispatcher.mapper.ActionMapper; @@ -33,6 +34,8 @@ import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.util.logging.Logger; import com.opensymphony.xwork2.util.logging.LoggerFactory; +import java.io.IOException; + /** * @@ -87,6 +90,8 @@ public class ServletRedirectResult extends StrutsResultSupport { protected ActionMapper actionMapper; + protected int statusCode = SC_FOUND; + public ServletRedirectResult() { super(); } @@ -100,6 +105,10 @@ public class ServletRedirectResult extends StrutsResultSupport { this.actionMapper = mapper; } + public void setStatusCode(int code) { + this.statusCode = code; + } + /** * Sets whether or not to prepend the servlet context path to the redirected URL. * @@ -150,7 +159,27 @@ public class ServletRedirectResult extends StrutsResultSupport { LOG.debug("Redirecting to finalLocation " + finalLocation); } - response.sendRedirect(finalLocation); + sendRedirect(response, finalLocation); + } + + /** + * Sends the redirection. Can be overridden to customize how the redirect is handled (i.e. to use a different + * status code) + * + * @param response The response + * @param finalLocation The location URI + * @throws IOException + */ + protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException { + if (SC_FOUND == statusCode) { + response.sendRedirect(finalLocation); + } else { + response.setStatus(statusCode); + response.setHeader("Location", finalLocation); + response.getWriter().write(finalLocation); + response.getWriter().close(); + } + } private static boolean isPathUrl(String url) { diff --git a/core/src/test/java/org/apache/struts2/dispatcher/ServletRedirectResultTest.java b/core/src/test/java/org/apache/struts2/dispatcher/ServletRedirectResultTest.java index f9a7cbcb0..87ee73eed 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/ServletRedirectResultTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/ServletRedirectResultTest.java @@ -21,9 +21,12 @@ package org.apache.struts2.dispatcher; import java.util.HashMap; +import java.io.StringWriter; +import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import static javax.servlet.http.HttpServletResponse.*; import ognl.Ognl; @@ -68,6 +71,26 @@ public class ServletRedirectResultTest extends StrutsTestCase implements StrutsS } } + public void testAbsoluteRedirect303() { + view.setLocation("/bar/foo.jsp"); + view.setStatusCode(303); + responseMock.expectAndReturn("encodeRedirectURL", "/context/bar/foo.jsp", "/context/bar/foo.jsp"); + responseMock.expect("setStatus", C.args(C.eq(SC_SEE_OTHER))); + responseMock.expect("setHeader", C.args(C.eq("Location"), C.eq("/context/bar/foo.jsp"))); + StringWriter writer = new StringWriter(); + responseMock.matchAndReturn("getWriter", new PrintWriter(writer)); + + try { + view.execute(ai); + requestMock.verify(); + responseMock.verify(); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + assertEquals("/context/bar/foo.jsp", writer.toString()); + } + public void testPrependServletContextFalse() { view.setLocation("/bar/foo.jsp"); view.setPrependServletContext(false);