27
27
import jakarta .servlet .ServletException ;
28
28
import jakarta .servlet .http .HttpServletRequest ;
29
29
import jakarta .servlet .http .HttpServletResponse ;
30
+
31
+ import javax .annotation .Nullable ;
30
32
import java .io .IOException ;
31
33
32
34
public class Redirect extends URLRewrite {
33
35
36
+ private @ Nullable RedirectType redirectType ;
37
+
34
38
public Redirect (final Element config , final String uri ) throws ServletException {
35
39
super (config , uri );
40
+ this .redirectType = parseRedirectType (config .getAttribute ("type" ));
36
41
final String redirectTo = config .getAttribute ("url" );
37
- if (redirectTo .length () == 0 ) {
42
+ if (redirectTo .isEmpty () ) {
38
43
throw new ServletException ("<exist:redirect> needs an attribute 'url'." );
39
44
}
40
45
if (redirectTo .matches ("^\\ w+://.*" )) {
@@ -47,16 +52,66 @@ public Redirect(final Element config, final String uri) throws ServletException
47
52
48
53
public Redirect (final Redirect other ) {
49
54
super (other );
55
+ this .redirectType = other .redirectType ;
50
56
}
51
57
52
58
@ Override
53
59
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 ();
56
71
}
57
72
58
73
@ Override
59
74
protected URLRewrite copy () {
60
75
return new Redirect (this );
61
76
}
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
+ }
62
117
}
0 commit comments