2727import jakarta .servlet .ServletException ;
2828import jakarta .servlet .http .HttpServletRequest ;
2929import jakarta .servlet .http .HttpServletResponse ;
30+
31+ import javax .annotation .Nullable ;
3032import java .io .IOException ;
3133
3234public class Redirect extends URLRewrite {
3335
36+ private @ Nullable RedirectType redirectType ;
37+
3438 public Redirect (final Element config , final String uri ) throws ServletException {
3539 super (config , uri );
40+ this .redirectType = parseRedirectType (config .getAttribute ("type" ));
3641 final String redirectTo = config .getAttribute ("url" );
37- if (redirectTo .length () == 0 ) {
42+ if (redirectTo .isEmpty () ) {
3843 throw new ServletException ("<exist:redirect> needs an attribute 'url'." );
3944 }
4045 if (redirectTo .matches ("^\\ w+://.*" )) {
@@ -47,16 +52,66 @@ public Redirect(final Element config, final String uri) throws ServletException
4752
4853 public Redirect (final Redirect other ) {
4954 super (other );
55+ this .redirectType = other .redirectType ;
5056 }
5157
5258 @ Override
5359 public void doRewrite (final HttpServletRequest request , final HttpServletResponse response ) throws IOException {
54- setHeaders (new HttpResponseWrapper (response ));
55- response .sendRedirect (target );
60+ if (redirectType == null ) {
61+ redirectType = "GET" .equals (request .getMethod ()) ? RedirectType .Found : RedirectType .SeeOther ;
62+ }
63+
64+ final HttpResponseWrapper responseWrapper = new HttpResponseWrapper (response );
65+ setHeaders (responseWrapper );
66+ responseWrapper .setStatusCode (redirectType .httpStatusCode );
67+ responseWrapper .setHeader ("Location" , target );
68+
69+ // commit the response
70+ responseWrapper .flushBuffer ();
5671 }
5772
5873 @ Override
5974 protected URLRewrite copy () {
6075 return new Redirect (this );
6176 }
77+
78+ private static @ Nullable RedirectType parseRedirectType (@ Nullable final String strRedirectType ) throws ServletException {
79+ // first, if no value use the default
80+ if (strRedirectType == null || strRedirectType .isEmpty ()) {
81+ return null ;
82+ }
83+
84+ // second, try to parse by number
85+ try {
86+ final int intRedirectType = Integer .valueOf (strRedirectType );
87+ for (final RedirectType redirectType : RedirectType .values ()) {
88+ if (redirectType .httpStatusCode == intRedirectType ) {
89+ return redirectType ;
90+ }
91+ }
92+ } catch (final NumberFormatException e ) {
93+ // ignore - no op
94+ }
95+
96+ // third, try to parse by name
97+ try {
98+ return RedirectType .valueOf (strRedirectType );
99+ } catch (final IllegalArgumentException e ) {
100+ throw new ServletException ("<exist:redirect type=\" " + strRedirectType + "\" is unsupported." );
101+ }
102+ }
103+
104+ private enum RedirectType {
105+ MovedPermanently (301 ),
106+ Found (302 ),
107+ SeeOther (303 ),
108+ TemporaryRedirect (307 ),
109+ PermanentRedirect (308 );
110+
111+ public final int httpStatusCode ;
112+
113+ RedirectType (final int httpStatusCode ) {
114+ this .httpStatusCode = httpStatusCode ;
115+ }
116+ }
62117}
0 commit comments