diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java index 1db7aafb831..8a74f778afc 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,7 +53,7 @@ import org.springframework.web.util.UriUtils; import org.springframework.web.util.WebUtils; /** - *

View that redirects to an absolute, context relative, or current request + * View that redirects to an absolute, context relative, or current request * relative URL. The URL may be a URI template in which case the URI template * variables will be replaced with values available in the model. By default * all primitive model attributes (or collections thereof) are exposed as HTTP @@ -105,6 +105,8 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { private boolean expandUriTemplateVariables = true; + private boolean propagateQueryParams = false; + /** * Constructor for use as a bean. @@ -235,6 +237,24 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { this.expandUriTemplateVariables = expandUriTemplateVariables; } + /** + * When set to {@code true} the query string of the current URL is appended + * and thus propagated through to the redirected URL. + *

Defaults to {@code false}. + * @since 4.1 + */ + public void setPropagateQueryParams(boolean propagateQueryParams) { + this.propagateQueryParams = propagateQueryParams; + } + + /** + * Whether to propagate the query params of the current URL. + * @since 4.1 + */ + public boolean isPropagateQueryProperties() { + return this.propagateQueryParams; + } + /** * Returns "true" indicating this view performs a redirect. */ @@ -307,6 +327,9 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { Map variables = getCurrentRequestUriVariables(request); targetUrl = replaceUriTemplateVariables(targetUrl.toString(), model, variables, enc); } + if (isPropagateQueryProperties()) { + appendCurrentQueryParams(targetUrl, request); + } if (this.exposeModelAttributes) { appendQueryProperties(targetUrl, model, enc); } @@ -347,11 +370,44 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView { @SuppressWarnings("unchecked") private Map getCurrentRequestUriVariables(HttpServletRequest request) { - Map uriVars = - (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; + Map uriVars = (Map) request.getAttribute(name); return (uriVars != null) ? uriVars : Collections. emptyMap(); } + /** + * Append the query string of the current request to the target redirect URL. + * @param targetUrl the StringBuilder to append the properties to + * @param request the current request + * @since 4.1 + */ + protected void appendCurrentQueryParams(StringBuilder targetUrl, HttpServletRequest request) { + + String query = request.getQueryString(); + if (StringUtils.hasText(query)) { + + // Extract anchor fragment, if any. + String fragment = null; + int anchorIndex = targetUrl.indexOf("#"); + if (anchorIndex > -1) { + fragment = targetUrl.substring(anchorIndex); + targetUrl.delete(anchorIndex, targetUrl.length()); + } + + if (targetUrl.toString().indexOf('?') < 0) { + targetUrl.append('?').append(query); + } + else { + targetUrl.append('&').append(query); + } + + // Append anchor fragment, if any, to end of URL. + if (fragment != null) { + targetUrl.append(fragment); + } + } + } + /** * Append query properties to the redirect URL. * Stringifies, URL-encodes and formats model attributes as query properties. diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java index 2e800c9d5b8..3b142aca481 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java @@ -325,6 +325,19 @@ public class RedirectViewTests { doTest(model, url, false, expectedUrlForEncoding); } + @Test + public void propagateQueryParams() throws Exception { + RedirectView rv = new RedirectView(); + rv.setPropagateQueryParams(true); + rv.setUrl("http://url.somewhere.com?foo=bar#bazz"); + MockHttpServletRequest request = createRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + request.setQueryString("a=b&c=d"); + rv.render(new HashMap(), request, response); + assertEquals(302, response.getStatus()); + assertEquals("http://url.somewhere.com?foo=bar&a=b&c=d#bazz", response.getHeader("Location")); + } + private void doTest(Map map, String url, boolean contextRelative, String expectedUrlForEncoding) throws Exception { doTest(map, url, contextRelative, true, expectedUrlForEncoding);