|
|
|
@ -45,8 +45,9 @@ import org.springframework.web.util.UriUtils; |
|
|
|
* available in the model. |
|
|
|
* available in the model. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>A URL for this view is supposed to be a HTTP redirect which does the redirect via |
|
|
|
* <p>A URL for this view is supposed to be a HTTP redirect which does the redirect via |
|
|
|
* sending an {@link HttpStatus#SEE_OTHER} code. If HTTP 1.0 compatibility is needed, |
|
|
|
* sending a {@literal 3xx} status code. By default {@link HttpStatus#SEE_OTHER} is used. |
|
|
|
* {@link HttpStatus#FOUND} code can be set via {@link #setStatusCode(HttpStatus)}. |
|
|
|
* If HTTP 1.0 compatibility is needed, {@link HttpStatus#FOUND} code can be set via |
|
|
|
|
|
|
|
* {@link #setStatusCode(HttpStatus)}. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>Note that the default value for the "contextRelative" flag is true. |
|
|
|
* <p>Note that the default value for the "contextRelative" flag is true. |
|
|
|
* With the flag on, URLs starting with "/" are considered relative to the web application |
|
|
|
* With the flag on, URLs starting with "/" are considered relative to the web application |
|
|
|
@ -54,7 +55,6 @@ import org.springframework.web.util.UriUtils; |
|
|
|
* root. |
|
|
|
* root. |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Sebastien Deleuze |
|
|
|
* @author Sebastien Deleuze |
|
|
|
* @see #setContextRelative |
|
|
|
|
|
|
|
* @since 5.0 |
|
|
|
* @since 5.0 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class RedirectView extends AbstractUrlBasedView { |
|
|
|
public class RedirectView extends AbstractUrlBasedView { |
|
|
|
@ -66,49 +66,70 @@ public class RedirectView extends AbstractUrlBasedView { |
|
|
|
|
|
|
|
|
|
|
|
private HttpStatus statusCode = HttpStatus.SEE_OTHER; |
|
|
|
private HttpStatus statusCode = HttpStatus.SEE_OTHER; |
|
|
|
|
|
|
|
|
|
|
|
private boolean propagateQueryParams = false; |
|
|
|
private boolean propagateQuery = false; |
|
|
|
|
|
|
|
|
|
|
|
private String[] hosts; |
|
|
|
private String[] hosts; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Create a new {@code RedirectView} with the given redirect URL. |
|
|
|
* Constructor for use as a bean. |
|
|
|
* |
|
|
|
*/ |
|
|
|
* @see #builder(String) |
|
|
|
public RedirectView() { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Create a new {@code RedirectView} with the given URL and the {@link HttpStatus#SEE_OTHER} |
|
|
|
|
|
|
|
* status code which is the correct code for HTTP 1.1 clients. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public RedirectView(String redirectUrl) { |
|
|
|
public RedirectView(String redirectUrl) { |
|
|
|
super(redirectUrl); |
|
|
|
super(redirectUrl); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Return a builder for a {@code RedirectView}. |
|
|
|
* Create a new {@code RedirectView} with the given redirect URL ans status code. Most |
|
|
|
|
|
|
|
* frequently used ones are: |
|
|
|
|
|
|
|
* <ul> |
|
|
|
|
|
|
|
* <li>{@link HttpStatus#SEE_OTHER} : temporary redirect for HTTP 1.1 compatible clients</li> |
|
|
|
|
|
|
|
* <li>{@link HttpStatus#FOUND} : temporary redirect for HTTP 1.0 compatible clients</li> |
|
|
|
|
|
|
|
* <li>{@link HttpStatus#MOVED_PERMANENTLY} : permanent redirect</li> |
|
|
|
|
|
|
|
* </ul> |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static Builder builder(String redirectUrl) { |
|
|
|
public RedirectView(String redirectUrl, HttpStatus statusCode) { |
|
|
|
return new BuilderImpl(redirectUrl); |
|
|
|
super(redirectUrl); |
|
|
|
|
|
|
|
setStatusCode(statusCode); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Set whether to interpret a given URL that starts with a slash ("/") |
|
|
|
* Set whether to interpret a given URL that starts with a slash ("/") |
|
|
|
* as relative to the current context path. |
|
|
|
* as relative to the current context path ({@code true}, the default) or to |
|
|
|
* <p>Default is "true": the context path will be |
|
|
|
* the web server root ({@code false}). |
|
|
|
* prepended to the URL in such a case. If "false", an URL that starts |
|
|
|
|
|
|
|
* with a slash will be interpreted as absolute, i.e. taken as-is. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void setContextRelative(boolean contextRelative) { |
|
|
|
public void setContextRelative(boolean contextRelative) { |
|
|
|
this.contextRelative = contextRelative; |
|
|
|
this.contextRelative = contextRelative; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Set a customized redirect status code to be used for a redirect. Default is |
|
|
|
* Return whether to interpret a given URL that starts with a slash ("/") |
|
|
|
* {@link HttpStatus#SEE_OTHER} which is the correct code for HTTP 1.1 |
|
|
|
* as relative to the current context path ("true") or to the web server |
|
|
|
* clients. This setter can be used to configure {@link HttpStatus#FOUND} |
|
|
|
* root ("false"). |
|
|
|
* if HTTP 1.0 clients need to be supported, or any other {@literal 3xx} |
|
|
|
* @return |
|
|
|
* status code. |
|
|
|
*/ |
|
|
|
|
|
|
|
public boolean isContextRelative() { |
|
|
|
|
|
|
|
return contextRelative; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Set the redirect status code. Most frequently used ones are: |
|
|
|
|
|
|
|
* <ul> |
|
|
|
|
|
|
|
* <li>{@link HttpStatus#SEE_OTHER} : temporary redirect for HTTP 1.1 compatible clients</li> |
|
|
|
|
|
|
|
* <li>{@link HttpStatus#FOUND} : temporary redirect for HTTP 1.0 compatible clients</li> |
|
|
|
|
|
|
|
* <li>{@link HttpStatus#MOVED_PERMANENTLY} : permanent redirect</li> |
|
|
|
|
|
|
|
* </ul> |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void setStatusCode(HttpStatus statusCode) { |
|
|
|
public void setStatusCode(HttpStatus statusCode) { |
|
|
|
Assert.notNull(statusCode); |
|
|
|
Assert.notNull(statusCode, "HttpStatus must not be null"); |
|
|
|
|
|
|
|
Assert.isTrue(statusCode.is3xxRedirection(), "HttpStatus must be a redirection (3xx status code)"); |
|
|
|
this.statusCode = statusCode; |
|
|
|
this.statusCode = statusCode; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -120,12 +141,19 @@ public class RedirectView extends AbstractUrlBasedView { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* When set to {@code true} the query string of the current URL is appended |
|
|
|
* Set whether to append the query string of the current URL to the redirected URL |
|
|
|
* and thus propagated through to the redirected URL. |
|
|
|
* ({@code true}) or not ({@code false}, the default). |
|
|
|
* <p>Defaults to {@code false}. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void setPropagateQueryParams(boolean propagateQueryParams) { |
|
|
|
public void setPropagateQuery(boolean propagateQuery) { |
|
|
|
this.propagateQueryParams = propagateQueryParams; |
|
|
|
this.propagateQuery = propagateQuery; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Return whether the query string of the current URL is appended to the redirected URL |
|
|
|
|
|
|
|
* ({@code true}) or not ({@code false}). |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public boolean isPropagateQuery() { |
|
|
|
|
|
|
|
return propagateQuery; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -141,6 +169,13 @@ public class RedirectView extends AbstractUrlBasedView { |
|
|
|
this.hosts = hosts; |
|
|
|
this.hosts = hosts; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Return the configured application hosts. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public String[] getHosts() { |
|
|
|
|
|
|
|
return this.hosts; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Convert model to request parameters and redirect to the given URL. |
|
|
|
* Convert model to request parameters and redirect to the given URL. |
|
|
|
* @see #sendRedirect |
|
|
|
* @see #sendRedirect |
|
|
|
@ -173,7 +208,7 @@ public class RedirectView extends AbstractUrlBasedView { |
|
|
|
Map<String, String> variables = getCurrentRequestUriVariables(exchange); |
|
|
|
Map<String, String> variables = getCurrentRequestUriVariables(exchange); |
|
|
|
targetUrl = replaceUriTemplateVariables(targetUrl.toString(), model, variables, charset); |
|
|
|
targetUrl = replaceUriTemplateVariables(targetUrl.toString(), model, variables, charset); |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.propagateQueryParams) { |
|
|
|
if (this.propagateQuery) { |
|
|
|
appendCurrentQueryParams(targetUrl, request); |
|
|
|
appendCurrentQueryParams(targetUrl, request); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -292,74 +327,12 @@ public class RedirectView extends AbstractUrlBasedView { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public interface Builder { |
|
|
|
@Override |
|
|
|
|
|
|
|
public void afterPropertiesSet() throws Exception { |
|
|
|
/** |
|
|
|
super.afterPropertiesSet(); |
|
|
|
* @see RedirectView#setContextRelative(boolean) |
|
|
|
if (getStatusCode() == null) { |
|
|
|
*/ |
|
|
|
throw new IllegalArgumentException("Property 'statusCode' is required"); |
|
|
|
Builder contextRelative(boolean contextRelative); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see RedirectView#setStatusCode(HttpStatus) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Builder statusCode(HttpStatus statusCode); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see RedirectView#setPropagateQueryParams(boolean) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Builder propagateQueryParams(boolean propagateQueryParams); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* @see RedirectView#setHosts(String...) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Builder hosts(String... hosts); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Build the redirect view. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
RedirectView build(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class BuilderImpl implements Builder { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final RedirectView view; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public BuilderImpl(String redirectUrl) { |
|
|
|
|
|
|
|
this.view = new RedirectView(redirectUrl); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public Builder contextRelative(boolean contextRelative) { |
|
|
|
|
|
|
|
this.view.setContextRelative(contextRelative); |
|
|
|
|
|
|
|
return this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public Builder statusCode(HttpStatus statusCode) { |
|
|
|
|
|
|
|
this.view.setStatusCode(statusCode); |
|
|
|
|
|
|
|
return this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public Builder propagateQueryParams(boolean propagateQueryParams) { |
|
|
|
|
|
|
|
this.view.setPropagateQueryParams(propagateQueryParams); |
|
|
|
|
|
|
|
return this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public Builder hosts(String... hosts) { |
|
|
|
|
|
|
|
this.view.setHosts(hosts); |
|
|
|
|
|
|
|
return this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public RedirectView build() { |
|
|
|
|
|
|
|
return this.view; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|