Skip to content

Commit 613e65f

Browse files
eiichesrstoyanchev
authored andcommitted
Fix URL decoding issue in reactive @RequestParam
%-encoded strings were injected undecoded into @RequestParam variables, which does not coincide with spring-webmvc behaviour. This commit fixes AbstractServerHttpRequest.getQueryParams() to correctly return decoded name-value pairs. Issue: SPR-15140
1 parent 88c5f59 commit 613e65f

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616

1717
package org.springframework.http.server.reactive;
1818

19+
import java.io.UnsupportedEncodingException;
1920
import java.net.URI;
21+
import java.net.URLDecoder;
22+
import java.nio.charset.StandardCharsets;
2023
import java.util.regex.Matcher;
2124
import java.util.regex.Pattern;
2225

@@ -76,6 +79,22 @@ public MultiValueMap<String, String> getQueryParams() {
7679
return this.queryParams;
7780
}
7881

82+
/**
83+
* A method for decoding name and value string in a name-value pair.
84+
* <p>Note that the plus sign "+" is converted into a space character " ".</p>
85+
* @param encodedString the string to be decoded
86+
* @return the decoded string
87+
* @see java.net.URLDecoder#decode(String, String)
88+
*/
89+
private static String decodeQueryParam(final String encodedString) {
90+
try {
91+
return URLDecoder.decode(encodedString, StandardCharsets.UTF_8.name());
92+
} catch (UnsupportedEncodingException e) {
93+
// StandardCharsets are guaranteed to be available on every implementation of the Java platform, so this should never happen.
94+
throw new IllegalStateException(e);
95+
}
96+
}
97+
7998
/**
8099
* A method for parsing of the query into name-value pairs. The return
81100
* value is turned into an immutable map and cached.
@@ -94,7 +113,8 @@ protected MultiValueMap<String, String> initQueryParams() {
94113
String eq = matcher.group(2);
95114
String value = matcher.group(3);
96115
value = (value != null ? value : (StringUtils.hasLength(eq) ? "" : null));
97-
queryParams.add(name, value);
116+
queryParams.add(decodeQueryParam(name),
117+
value != null ? decodeQueryParam(value) : null);
98118
}
99119
}
100120
return queryParams;

spring-web/src/test/java/org/springframework/http/server/reactive/ServerHttpRequestTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ public void queryParamsWithMulitpleValues() throws Exception {
6464
assertEquals(Arrays.asList("1", "2"), params.get("a"));
6565
}
6666

67+
@Test
68+
public void queryParamsWithUrlEncodedValue() throws Exception {
69+
MultiValueMap<String, String> params = createHttpRequest("/path?a=%20%2B+%C3%A0").getQueryParams();
70+
assertEquals(1, params.size());
71+
assertEquals(Collections.singletonList(" + \u00e0"), params.get("a"));
72+
}
73+
6774
@Test
6875
public void queryParamsWithEmptyValue() throws Exception {
6976
MultiValueMap<String, String> params = createHttpRequest("/path?a=").getQueryParams();

0 commit comments

Comments
 (0)