Skip to content

Commit 0bbb770

Browse files
committed
Add propagateQueryParams property to RedirectView
This change makes it possible to configure RedirectView such that the query string of the current request is added to the target URL. This change is preparation for SPR-11543.
1 parent 0e2c5ee commit 0bbb770

File tree

2 files changed

+73
-4
lines changed

2 files changed

+73
-4
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/view/RedirectView.java

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@
5353
import org.springframework.web.util.WebUtils;
5454

5555
/**
56-
* <p>View that redirects to an absolute, context relative, or current request
56+
* View that redirects to an absolute, context relative, or current request
5757
* relative URL. The URL may be a URI template in which case the URI template
5858
* variables will be replaced with values available in the model. By default
5959
* all primitive model attributes (or collections thereof) are exposed as HTTP
@@ -105,6 +105,8 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
105105

106106
private boolean expandUriTemplateVariables = true;
107107

108+
private boolean propagateQueryParams = false;
109+
108110

109111
/**
110112
* Constructor for use as a bean.
@@ -235,6 +237,24 @@ public void setExpandUriTemplateVariables(boolean expandUriTemplateVariables) {
235237
this.expandUriTemplateVariables = expandUriTemplateVariables;
236238
}
237239

240+
/**
241+
* When set to {@code true} the query string of the current URL is appended
242+
* and thus propagated through to the redirected URL.
243+
* <p>Defaults to {@code false}.
244+
* @since 4.1
245+
*/
246+
public void setPropagateQueryParams(boolean propagateQueryParams) {
247+
this.propagateQueryParams = propagateQueryParams;
248+
}
249+
250+
/**
251+
* Whether to propagate the query params of the current URL.
252+
* @since 4.1
253+
*/
254+
public boolean isPropagateQueryProperties() {
255+
return this.propagateQueryParams;
256+
}
257+
238258
/**
239259
* Returns "true" indicating this view performs a redirect.
240260
*/
@@ -307,6 +327,9 @@ protected final String createTargetUrl(Map<String, Object> model, HttpServletReq
307327
Map<String, String> variables = getCurrentRequestUriVariables(request);
308328
targetUrl = replaceUriTemplateVariables(targetUrl.toString(), model, variables, enc);
309329
}
330+
if (isPropagateQueryProperties()) {
331+
appendCurrentQueryParams(targetUrl, request);
332+
}
310333
if (this.exposeModelAttributes) {
311334
appendQueryProperties(targetUrl, model, enc);
312335
}
@@ -347,11 +370,44 @@ protected StringBuilder replaceUriTemplateVariables(
347370

348371
@SuppressWarnings("unchecked")
349372
private Map<String, String> getCurrentRequestUriVariables(HttpServletRequest request) {
350-
Map<String, String> uriVars =
351-
(Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
373+
String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
374+
Map<String, String> uriVars = (Map<String, String>) request.getAttribute(name);
352375
return (uriVars != null) ? uriVars : Collections.<String, String> emptyMap();
353376
}
354377

378+
/**
379+
* Append the query string of the current request to the target redirect URL.
380+
* @param targetUrl the StringBuilder to append the properties to
381+
* @param request the current request
382+
* @since 4.1
383+
*/
384+
protected void appendCurrentQueryParams(StringBuilder targetUrl, HttpServletRequest request) {
385+
386+
String query = request.getQueryString();
387+
if (StringUtils.hasText(query)) {
388+
389+
// Extract anchor fragment, if any.
390+
String fragment = null;
391+
int anchorIndex = targetUrl.indexOf("#");
392+
if (anchorIndex > -1) {
393+
fragment = targetUrl.substring(anchorIndex);
394+
targetUrl.delete(anchorIndex, targetUrl.length());
395+
}
396+
397+
if (targetUrl.toString().indexOf('?') < 0) {
398+
targetUrl.append('?').append(query);
399+
}
400+
else {
401+
targetUrl.append('&').append(query);
402+
}
403+
404+
// Append anchor fragment, if any, to end of URL.
405+
if (fragment != null) {
406+
targetUrl.append(fragment);
407+
}
408+
}
409+
}
410+
355411
/**
356412
* Append query properties to the redirect URL.
357413
* Stringifies, URL-encodes and formats model attributes as query properties.

spring-webmvc/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,19 @@ public void objectConversion() throws Exception {
325325
doTest(model, url, false, expectedUrlForEncoding);
326326
}
327327

328+
@Test
329+
public void propagateQueryParams() throws Exception {
330+
RedirectView rv = new RedirectView();
331+
rv.setPropagateQueryParams(true);
332+
rv.setUrl("http://url.somewhere.com?foo=bar#bazz");
333+
MockHttpServletRequest request = createRequest();
334+
MockHttpServletResponse response = new MockHttpServletResponse();
335+
request.setQueryString("a=b&c=d");
336+
rv.render(new HashMap<String, Object>(), request, response);
337+
assertEquals(302, response.getStatus());
338+
assertEquals("http://url.somewhere.com?foo=bar&a=b&c=d#bazz", response.getHeader("Location"));
339+
}
340+
328341
private void doTest(Map<String, ?> map, String url, boolean contextRelative, String expectedUrlForEncoding)
329342
throws Exception {
330343
doTest(map, url, contextRelative, true, expectedUrlForEncoding);

0 commit comments

Comments
 (0)