Support for "request parameters"
ServerWebExchange now provides access to "requestParams" as a MulitValueMap with query parameters and form data combined. The combined map is then used for the params condition of @RequestMapping purposes () and also for @RequestParam arguments. Issue: SPR-15000
This commit is contained in:
parent
36da299f96
commit
6119415427
|
@ -21,6 +21,8 @@ import java.util.Collections;
|
|||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
|
@ -141,12 +143,18 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
|
|||
|
||||
@Override
|
||||
protected boolean matchName(ServerWebExchange exchange) {
|
||||
return exchange.getRequest().getQueryParams().containsKey(this.name);
|
||||
return getRequestParams(exchange).containsKey(this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchValue(ServerWebExchange exchange) {
|
||||
return this.value.equals(exchange.getRequest().getQueryParams().getFirst(this.name));
|
||||
return this.value.equals(getRequestParams(exchange).getFirst(this.name));
|
||||
}
|
||||
|
||||
private MultiValueMap<String, String> getRequestParams(ServerWebExchange exchange) {
|
||||
MultiValueMap<String, String> params = exchange.getRequestParams().subscribe().peek();
|
||||
Assert.notNull(params, "Expected form data (if any) to be parsed.");
|
||||
return params;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -260,26 +260,31 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
|||
logger.debug("Looking up handler method for path " + lookupPath);
|
||||
}
|
||||
this.mappingRegistry.acquireReadLock();
|
||||
|
||||
try {
|
||||
HandlerMethod handlerMethod = null;
|
||||
try {
|
||||
handlerMethod = lookupHandlerMethod(lookupPath, exchange);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return Mono.error(ex);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (handlerMethod != null) {
|
||||
logger.debug("Returning handler method [" + handlerMethod + "]");
|
||||
}
|
||||
else {
|
||||
logger.debug("Did not find handler method for [" + lookupPath + "]");
|
||||
}
|
||||
}
|
||||
if (handlerMethod != null) {
|
||||
handlerMethod = handlerMethod.createWithResolvedBean();
|
||||
}
|
||||
return Mono.justOrEmpty(handlerMethod);
|
||||
// Ensure form data is parsed for "params" conditions...
|
||||
return exchange.getRequestParams()
|
||||
.then(() -> {
|
||||
HandlerMethod handlerMethod = null;
|
||||
try {
|
||||
handlerMethod = lookupHandlerMethod(lookupPath, exchange);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return Mono.error(ex);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (handlerMethod != null) {
|
||||
logger.debug("Returning handler method [" + handlerMethod + "]");
|
||||
}
|
||||
else {
|
||||
logger.debug("Did not find handler method for [" + lookupPath + "]");
|
||||
}
|
||||
}
|
||||
if (handlerMethod != null) {
|
||||
handlerMethod = handlerMethod.createWithResolvedBean();
|
||||
}
|
||||
return Mono.justOrEmpty(handlerMethod);
|
||||
});
|
||||
}
|
||||
finally {
|
||||
this.mappingRegistry.releaseReadLock();
|
||||
|
|
|
@ -20,6 +20,8 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
@ -59,11 +61,17 @@ public class RequestParamMapMethodArgumentResolver implements SyncHandlerMethodA
|
|||
public Optional<Object> resolveArgumentValue(MethodParameter parameter, BindingContext context,
|
||||
ServerWebExchange exchange) {
|
||||
|
||||
MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
|
||||
Object value = (isMultiValueMap(parameter) ? queryParams : queryParams.toSingleValueMap());
|
||||
MultiValueMap<String, String> requestParams = getRequestParams(exchange);
|
||||
Object value = (isMultiValueMap(parameter) ? requestParams : requestParams.toSingleValueMap());
|
||||
return Optional.of(value);
|
||||
}
|
||||
|
||||
private MultiValueMap<String, String> getRequestParams(ServerWebExchange exchange) {
|
||||
MultiValueMap<String, String> params = exchange.getRequestParams().subscribe().peek();
|
||||
Assert.notNull(params, "Expected form data (if any) to be parsed.");
|
||||
return params;
|
||||
}
|
||||
|
||||
private boolean isMultiValueMap(MethodParameter parameter) {
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
return MultiValueMap.class.isAssignableFrom(paramType);
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.springframework.beans.BeanUtils;
|
|||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
|
@ -106,7 +108,7 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueSyncAr
|
|||
protected Optional<Object> resolveNamedValue(String name, MethodParameter parameter,
|
||||
ServerWebExchange exchange) {
|
||||
|
||||
List<String> paramValues = exchange.getRequest().getQueryParams().get(name);
|
||||
List<String> paramValues = getRequestParams(exchange).get(name);
|
||||
Object result = null;
|
||||
if (paramValues != null) {
|
||||
result = (paramValues.size() == 1 ? paramValues.get(0) : paramValues);
|
||||
|
@ -114,6 +116,12 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueSyncAr
|
|||
return Optional.ofNullable(result);
|
||||
}
|
||||
|
||||
private MultiValueMap<String, String> getRequestParams(ServerWebExchange exchange) {
|
||||
MultiValueMap<String, String> params = exchange.getRequestParams().subscribe().peek();
|
||||
Assert.notNull(params, "Expected form data (if any) to be parsed.");
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter, ServerWebExchange exchange) {
|
||||
String type = parameter.getNestedParameterType().getSimpleName();
|
||||
|
|
|
@ -22,9 +22,11 @@ import java.util.Collection;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.MockWebSessionManager;
|
||||
|
@ -35,9 +37,11 @@ import static org.junit.Assert.assertFalse;
|
|||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.web.util.UriComponentsBuilder.fromPath;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
* Unit tests for {@link ParamsRequestCondition}.
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ParamsRequestConditionTests {
|
||||
|
||||
|
@ -52,47 +56,45 @@ public class ParamsRequestConditionTests {
|
|||
|
||||
@Test
|
||||
public void paramPresent() throws Exception {
|
||||
ServerWebExchange exchange = createExchange("foo", "");
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo");
|
||||
|
||||
assertNotNull(condition.getMatchingCondition(exchange));
|
||||
assertNotNull(condition.getMatchingCondition(exchangeWithQuery("foo=")));
|
||||
assertNotNull(condition.getMatchingCondition(exchangeWithFormData("foo=")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramPresentNoMatch() throws Exception {
|
||||
ServerWebExchange exchange = createExchange("bar", "");
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo");
|
||||
|
||||
assertNull(condition.getMatchingCondition(exchange));
|
||||
assertNull(condition.getMatchingCondition(exchangeWithQuery("bar=")));
|
||||
assertNull(condition.getMatchingCondition(exchangeWithFormData("bar=")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramNotPresent() throws Exception {
|
||||
ServerWebExchange exchange = createExchange();
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("!foo");
|
||||
|
||||
assertNotNull(condition.getMatchingCondition(exchange));
|
||||
ServerWebExchange exchange = exchange();
|
||||
assertNotNull(new ParamsRequestCondition("!foo").getMatchingCondition(exchange));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramValueMatch() throws Exception {
|
||||
ServerWebExchange exchange = createExchange("foo", "bar");
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo=bar");
|
||||
|
||||
assertNotNull(condition.getMatchingCondition(exchange));
|
||||
assertNotNull(condition.getMatchingCondition(exchangeWithQuery("foo=bar")));
|
||||
assertNotNull(condition.getMatchingCondition(exchangeWithFormData("foo=bar")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramValueNoMatch() throws Exception {
|
||||
ServerWebExchange exchange = createExchange("foo", "bazz");
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo=bar");
|
||||
|
||||
assertNull(condition.getMatchingCondition(exchange));
|
||||
assertNull(condition.getMatchingCondition(exchangeWithQuery("foo=bazz")));
|
||||
assertNull(condition.getMatchingCondition(exchangeWithFormData("foo=bazz")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo() throws Exception {
|
||||
ServerWebExchange exchange = createExchange();
|
||||
ServerWebExchange exchange = exchange(new MockServerHttpRequest(HttpMethod.GET, "/"));
|
||||
|
||||
ParamsRequestCondition condition1 = new ParamsRequestCondition("foo", "bar", "baz");
|
||||
ParamsRequestCondition condition2 = new ParamsRequestCondition("foo", "bar");
|
||||
|
@ -114,31 +116,29 @@ public class ParamsRequestConditionTests {
|
|||
assertEquals(2, conditions.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMatchingCondition() throws Exception {
|
||||
ServerWebExchange exchange = createExchange("foo", "bar");
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo");
|
||||
|
||||
ParamsRequestCondition result = condition.getMatchingCondition(exchange);
|
||||
assertEquals(condition, result);
|
||||
|
||||
condition = new ParamsRequestCondition("bar");
|
||||
|
||||
result = condition.getMatchingCondition(exchange);
|
||||
assertNull(result);
|
||||
private ServerWebExchange exchangeWithQuery(String query) throws URISyntaxException {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/");
|
||||
MultiValueMap<String, String> params = fromPath("/").query(query).build().getQueryParams();
|
||||
request.getQueryParams().putAll(params);
|
||||
return exchange(request);
|
||||
}
|
||||
|
||||
private ServerWebExchange createExchange() throws URISyntaxException {
|
||||
return createExchange(null, null);
|
||||
private ServerWebExchange exchangeWithFormData(String formData) throws URISyntaxException {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/");
|
||||
request.getHeaders().setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
request.setBody(formData);
|
||||
return exchange(request);
|
||||
}
|
||||
|
||||
private ServerWebExchange createExchange(String paramName, String paramValue) throws URISyntaxException {
|
||||
ServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/");
|
||||
if (paramName != null) {
|
||||
request.getQueryParams().add(paramName, paramValue);
|
||||
}
|
||||
WebSessionManager sessionManager = new MockWebSessionManager();
|
||||
return new DefaultServerWebExchange(request, new MockServerHttpResponse(), sessionManager);
|
||||
private ServerWebExchange exchange() {
|
||||
return exchange(new MockServerHttpRequest(HttpMethod.GET, "/"));
|
||||
}
|
||||
|
||||
private ServerWebExchange exchange(ServerHttpRequest request) {
|
||||
MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
WebSessionManager manager = new MockWebSessionManager();
|
||||
return new DefaultServerWebExchange(request, response, manager);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,21 +17,21 @@
|
|||
package org.springframework.web.reactive.result.method.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
@ -42,18 +42,16 @@ import org.springframework.web.server.session.WebSessionManager;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.web.util.UriComponentsBuilder.fromPath;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link RequestParamMapMethodArgumentResolver}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class RequestParamMapMethodArgumentResolverTests {
|
||||
|
||||
private RequestParamMapMethodArgumentResolver resolver;
|
||||
|
||||
private ServerWebExchange exchange;
|
||||
|
||||
private MethodParameter paramMap;
|
||||
private MethodParameter paramMultiValueMap;
|
||||
private MethodParameter paramNamedMap;
|
||||
|
@ -65,10 +63,6 @@ public class RequestParamMapMethodArgumentResolverTests {
|
|||
public void setUp() throws Exception {
|
||||
this.resolver = new RequestParamMapMethodArgumentResolver();
|
||||
|
||||
ServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/");
|
||||
WebSessionManager sessionManager = new MockWebSessionManager();
|
||||
this.exchange = new DefaultServerWebExchange(request, new MockServerHttpResponse(), sessionManager);
|
||||
|
||||
Method method = getClass().getMethod("params", Map.class, MultiValueMap.class, Map.class, Map.class);
|
||||
this.paramMap = new SynthesizingMethodParameter(method, 0);
|
||||
this.paramMultiValueMap = new SynthesizingMethodParameter(method, 1);
|
||||
|
@ -86,35 +80,51 @@ public class RequestParamMapMethodArgumentResolverTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void resolveMapArgument() throws Exception {
|
||||
String name = "foo";
|
||||
String value = "bar";
|
||||
this.exchange.getRequest().getQueryParams().set(name, value);
|
||||
Map<String, String> expected = Collections.singletonMap(name, value);
|
||||
|
||||
Mono<Object> mono = resolver.resolveArgument(paramMap, null, exchange);
|
||||
Object result = mono.block();
|
||||
|
||||
public void resolveMapArgumentWithQueryString() throws Exception {
|
||||
Object result= resolve(this.paramMap, exchangeWithQuery("foo=bar"));
|
||||
assertTrue(result instanceof Map);
|
||||
assertEquals(expected, result);
|
||||
assertEquals(Collections.singletonMap("foo", "bar"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveMapArgumentWithFormData() throws Exception {
|
||||
Object result= resolve(this.paramMap, exchangeWithFormData("foo=bar"));
|
||||
assertTrue(result instanceof Map);
|
||||
assertEquals(Collections.singletonMap("foo", "bar"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveMultiValueMapArgument() throws Exception {
|
||||
String name = "foo";
|
||||
String value1 = "bar";
|
||||
String value2 = "baz";
|
||||
this.exchange.getRequest().getQueryParams().put(name, Arrays.asList(value1, value2));
|
||||
|
||||
MultiValueMap<String, String> expected = new LinkedMultiValueMap<>(1);
|
||||
expected.add(name, value1);
|
||||
expected.add(name, value2);
|
||||
|
||||
Mono<Object> mono = this.resolver.resolveArgument(this.paramMultiValueMap, null, this.exchange);
|
||||
Object result = mono.block();
|
||||
ServerWebExchange exchange = exchangeWithQuery("foo=bar&foo=baz");
|
||||
Object result= resolve(this.paramMultiValueMap, exchange);
|
||||
|
||||
assertTrue(result instanceof MultiValueMap);
|
||||
assertEquals(expected, result);
|
||||
assertEquals(Collections.singletonMap("foo", Arrays.asList("bar", "baz")), result);
|
||||
}
|
||||
|
||||
|
||||
private ServerWebExchange exchangeWithQuery(String query) throws URISyntaxException {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/");
|
||||
MultiValueMap<String, String> params = fromPath("/").query(query).build().getQueryParams();
|
||||
request.getQueryParams().putAll(params);
|
||||
return exchange(request);
|
||||
}
|
||||
|
||||
private ServerWebExchange exchangeWithFormData(String formData) throws URISyntaxException {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/");
|
||||
request.getHeaders().setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
request.setBody(formData);
|
||||
return exchange(request);
|
||||
}
|
||||
|
||||
private ServerWebExchange exchange(ServerHttpRequest request) {
|
||||
MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
WebSessionManager manager = new MockWebSessionManager();
|
||||
return new DefaultServerWebExchange(request, response, manager);
|
||||
}
|
||||
|
||||
private Object resolve(MethodParameter parameter, ServerWebExchange exchange) {
|
||||
return this.resolver.resolveArgument(parameter, null, exchange).blockMillis(0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.springframework.web.reactive.result.method.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
|
@ -32,9 +32,11 @@ import org.springframework.core.ParameterNameDiscoverer;
|
|||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
|
@ -45,7 +47,12 @@ import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
|||
import org.springframework.web.server.session.MockWebSessionManager;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.web.util.UriComponentsBuilder.fromPath;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link RequestParamMethodArgumentResolver}.
|
||||
|
@ -56,8 +63,6 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
|
||||
private RequestParamMethodArgumentResolver resolver;
|
||||
|
||||
private ServerWebExchange exchange;
|
||||
|
||||
private MethodParameter paramNamedDefaultValueString;
|
||||
private MethodParameter paramNamedStringArray;
|
||||
private MethodParameter paramNamedMap;
|
||||
|
@ -67,7 +72,7 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
private MethodParameter paramNotRequired;
|
||||
private MethodParameter paramOptional;
|
||||
|
||||
private BindingContext bindingContext;
|
||||
private BindingContext bindContext;
|
||||
|
||||
|
||||
@Before @SuppressWarnings("ConfusingArgumentToVarargsMethod")
|
||||
|
@ -77,10 +82,6 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||
Method method = ReflectionUtils.findMethod(getClass(), "handle", (Class<?>[]) null);
|
||||
|
||||
ServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/");
|
||||
WebSessionManager sessionManager = new MockWebSessionManager();
|
||||
this.exchange = new DefaultServerWebExchange(request, new MockServerHttpResponse(), sessionManager);
|
||||
|
||||
this.paramNamedDefaultValueString = new SynthesizingMethodParameter(method, 0);
|
||||
this.paramNamedStringArray = new SynthesizingMethodParameter(method, 1);
|
||||
this.paramNamedMap = new SynthesizingMethodParameter(method, 2);
|
||||
|
@ -94,7 +95,7 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
|
||||
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
|
||||
initializer.setConversionService(new DefaultFormattingConversionService());
|
||||
this.bindingContext = new BindingContext(initializer);
|
||||
this.bindContext = new BindingContext(initializer);
|
||||
}
|
||||
|
||||
|
||||
|
@ -115,45 +116,33 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void resolveString() throws Exception {
|
||||
String expected = "foo";
|
||||
this.exchange.getRequest().getQueryParams().set("name", expected);
|
||||
public void resolveWithQueryString() throws Exception {
|
||||
assertEquals("foo", resolve(this.paramNamedDefaultValueString, exchangeWithQuery("name=foo")));
|
||||
}
|
||||
|
||||
Mono<Object> mono = this.resolver.resolveArgument(
|
||||
this.paramNamedDefaultValueString, this.bindingContext, this.exchange);
|
||||
|
||||
Object result = mono.block();
|
||||
assertTrue(result instanceof String);
|
||||
assertEquals("Invalid result", expected, result);
|
||||
@Test
|
||||
public void resolveWithFormData() throws Exception {
|
||||
assertEquals("foo", resolve(this.paramNamedDefaultValueString, exchangeWithFormData("name=foo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveStringArray() throws Exception {
|
||||
String[] expected = {"foo", "bar"};
|
||||
this.exchange.getRequest().getQueryParams().put("name", Arrays.asList(expected));
|
||||
|
||||
Mono<Object> mono = this.resolver.resolveArgument(
|
||||
this.paramNamedStringArray, this.bindingContext, this.exchange);
|
||||
|
||||
Object result = mono.block();
|
||||
Object result = resolve(this.paramNamedStringArray, exchangeWithQuery("name=foo&name=bar"));
|
||||
assertTrue(result instanceof String[]);
|
||||
assertArrayEquals(expected, (String[]) result);
|
||||
assertArrayEquals(new String[] {"foo", "bar"}, (String[]) result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveDefaultValue() throws Exception {
|
||||
Mono<Object> mono = this.resolver.resolveArgument(
|
||||
this.paramNamedDefaultValueString, this.bindingContext, this.exchange);
|
||||
|
||||
Object result = mono.block();
|
||||
assertTrue(result instanceof String);
|
||||
assertEquals("Invalid result", "bar", result);
|
||||
Object result = resolve(this.paramNamedDefaultValueString, exchange());
|
||||
assertEquals("bar", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingRequestParam() throws Exception {
|
||||
|
||||
Mono<Object> mono = this.resolver.resolveArgument(
|
||||
this.paramNamedStringArray, this.bindingContext, this.exchange);
|
||||
this.paramNamedStringArray, this.bindContext, exchange());
|
||||
|
||||
StepVerifier.create(mono)
|
||||
.expectNextCount(0)
|
||||
|
@ -163,65 +152,41 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
|
||||
@Test
|
||||
public void resolveSimpleTypeParam() throws Exception {
|
||||
this.exchange.getRequest().getQueryParams().set("stringNotAnnot", "plainValue");
|
||||
Mono<Object> mono = this.resolver.resolveArgument(
|
||||
this.paramStringNotAnnot, this.bindingContext, this.exchange);
|
||||
|
||||
Object result = mono.block();
|
||||
assertTrue(result instanceof String);
|
||||
ServerWebExchange exchange = exchangeWithQuery("stringNotAnnot=plainValue");
|
||||
Object result = resolve(this.paramStringNotAnnot, exchange);
|
||||
assertEquals("plainValue", result);
|
||||
}
|
||||
|
||||
@Test // SPR-8561
|
||||
public void resolveSimpleTypeParamToNull() throws Exception {
|
||||
Mono<Object> mono = this.resolver.resolveArgument(
|
||||
this.paramStringNotAnnot, this.bindingContext, this.exchange);
|
||||
|
||||
Object result = mono.block();
|
||||
assertNull(result);
|
||||
assertNull(resolve(this.paramStringNotAnnot, exchange()));
|
||||
}
|
||||
|
||||
@Test // SPR-10180
|
||||
public void resolveEmptyValueToDefault() throws Exception {
|
||||
this.exchange.getRequest().getQueryParams().set("name", "");
|
||||
Mono<Object> mono = this.resolver.resolveArgument(
|
||||
this.paramNamedDefaultValueString, this.bindingContext, this.exchange);
|
||||
|
||||
Object result = mono.block();
|
||||
ServerWebExchange exchange = exchangeWithQuery("name=");
|
||||
Object result = resolve(this.paramNamedDefaultValueString, exchange);
|
||||
assertEquals("bar", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveEmptyValueWithoutDefault() throws Exception {
|
||||
this.exchange.getRequest().getQueryParams().set("stringNotAnnot", "");
|
||||
Mono<Object> mono = this.resolver.resolveArgument(
|
||||
this.paramStringNotAnnot, this.bindingContext, this.exchange);
|
||||
|
||||
Object result = mono.block();
|
||||
assertEquals("", result);
|
||||
assertEquals("", resolve(this.paramStringNotAnnot, exchangeWithQuery("stringNotAnnot=")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveEmptyValueRequiredWithoutDefault() throws Exception {
|
||||
this.exchange.getRequest().getQueryParams().set("name", "");
|
||||
Mono<Object> mono = this.resolver.resolveArgument(
|
||||
this.paramRequired, this.bindingContext, this.exchange);
|
||||
|
||||
Object result = mono.block();
|
||||
assertEquals("", result);
|
||||
assertEquals("", resolve(this.paramRequired, exchangeWithQuery("name=")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalParamValue() throws Exception {
|
||||
Mono<Object> mono = this.resolver.resolveArgument(
|
||||
this.paramOptional, this.bindingContext, this.exchange);
|
||||
|
||||
Object result = mono.block();
|
||||
ServerWebExchange exchange = exchange();
|
||||
Object result = resolve(this.paramOptional, exchange);
|
||||
assertEquals(Optional.empty(), result);
|
||||
|
||||
this.exchange.getRequest().getQueryParams().set("name", "123");
|
||||
mono = this.resolver.resolveArgument(this.paramOptional, this.bindingContext, this.exchange);
|
||||
result = mono.block();
|
||||
exchange = exchangeWithQuery("name=123");
|
||||
result = resolve(this.paramOptional, exchange);
|
||||
|
||||
assertEquals(Optional.class, result.getClass());
|
||||
Optional<?> value = (Optional<?>) result;
|
||||
|
@ -230,6 +195,35 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
}
|
||||
|
||||
|
||||
private ServerWebExchange exchangeWithQuery(String query) throws URISyntaxException {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/");
|
||||
MultiValueMap<String, String> params = fromPath("/").query(query).build().getQueryParams();
|
||||
request.getQueryParams().putAll(params);
|
||||
return exchange(request);
|
||||
}
|
||||
|
||||
private ServerWebExchange exchangeWithFormData(String formData) throws URISyntaxException {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/");
|
||||
request.getHeaders().setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
request.setBody(formData);
|
||||
return exchange(request);
|
||||
}
|
||||
|
||||
private ServerWebExchange exchange() {
|
||||
return exchange(new MockServerHttpRequest(HttpMethod.GET, "/"));
|
||||
}
|
||||
|
||||
private ServerWebExchange exchange(ServerHttpRequest request) {
|
||||
MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
WebSessionManager manager = new MockWebSessionManager();
|
||||
return new DefaultServerWebExchange(request, response, manager);
|
||||
}
|
||||
|
||||
private Object resolve(MethodParameter parameter, ServerWebExchange exchange) {
|
||||
return this.resolver.resolveArgument(parameter, this.bindContext, exchange).blockMillis(0);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"unused", "OptionalUsedAsFieldOrParameterType"})
|
||||
public void handle(
|
||||
@RequestParam(name = "name", defaultValue = "bar") String param1,
|
||||
|
|
|
@ -76,11 +76,18 @@ public interface ServerWebExchange {
|
|||
<T extends Principal> Mono<T> getPrincipal();
|
||||
|
||||
/**
|
||||
* Return the form data from the body of the request or an empty {@code Mono}
|
||||
* if the Content-Type is not "application/x-www-form-urlencoded".
|
||||
* Return the form data from the body of the request if the Content-Type is
|
||||
* {@code "application/x-www-form-urlencoded"} or an empty map.
|
||||
*/
|
||||
Mono<MultiValueMap<String, String>> getFormData();
|
||||
|
||||
/**
|
||||
* Return a combined map that represents both
|
||||
* {@link ServerHttpRequest#getQueryParams()} and {@link #getFormData()}
|
||||
* or an empty map.
|
||||
*/
|
||||
Mono<MultiValueMap<String, String>> getRequestParams();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the one of the {@code checkNotModified} methods
|
||||
* in this contract were used and they returned true.
|
||||
|
|
|
@ -93,6 +93,11 @@ public class ServerWebExchangeDecorator implements ServerWebExchange {
|
|||
return getDelegate().getFormData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<MultiValueMap<String, String>> getRequestParams() {
|
||||
return getDelegate().getRequestParams();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotModified() {
|
||||
return getDelegate().isNotModified();
|
||||
|
|
|
@ -38,6 +38,8 @@ import org.springframework.http.codec.FormHttpMessageReader;
|
|||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
@ -56,9 +58,13 @@ public class DefaultServerWebExchange implements ServerWebExchange {
|
|||
|
||||
private static final FormHttpMessageReader FORM_READER = new FormHttpMessageReader();
|
||||
|
||||
private static final ResolvableType MULTIVALUE_TYPE =
|
||||
private static final ResolvableType FORM_DATA_VALUE_TYPE =
|
||||
ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class);
|
||||
|
||||
private static final Mono<MultiValueMap<String, String>> EMPTY_FORM_DATA =
|
||||
Mono.just(CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<String, String>(0)))
|
||||
.cache();
|
||||
|
||||
|
||||
private final ServerHttpRequest request;
|
||||
|
||||
|
@ -70,6 +76,8 @@ public class DefaultServerWebExchange implements ServerWebExchange {
|
|||
|
||||
private final Mono<MultiValueMap<String, String>> formDataMono;
|
||||
|
||||
private final Mono<MultiValueMap<String, String>> requestParamsMono;
|
||||
|
||||
private volatile boolean notModified;
|
||||
|
||||
|
||||
|
@ -80,10 +88,12 @@ public class DefaultServerWebExchange implements ServerWebExchange {
|
|||
Assert.notNull(response, "'response' is required");
|
||||
Assert.notNull(response, "'sessionManager' is required");
|
||||
Assert.notNull(response, "'formReader' is required");
|
||||
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.sessionMono = sessionManager.getSession(this).cache();
|
||||
this.formDataMono = initFormData(request);
|
||||
this.requestParamsMono = initRequestParams(request, this.formDataMono);
|
||||
}
|
||||
|
||||
private static Mono<MultiValueMap<String, String>> initFormData(ServerHttpRequest request) {
|
||||
|
@ -91,13 +101,28 @@ public class DefaultServerWebExchange implements ServerWebExchange {
|
|||
try {
|
||||
contentType = request.getHeaders().getContentType();
|
||||
if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) {
|
||||
return FORM_READER.readMono(MULTIVALUE_TYPE, request, Collections.emptyMap()).cache();
|
||||
Map<String, Object> hints = Collections.emptyMap();
|
||||
return FORM_READER.readMono(FORM_DATA_VALUE_TYPE, request, hints).cache();
|
||||
}
|
||||
}
|
||||
catch (InvalidMediaTypeException ex) {
|
||||
// Ignore
|
||||
}
|
||||
return Mono.empty();
|
||||
return EMPTY_FORM_DATA;
|
||||
}
|
||||
|
||||
private static Mono<MultiValueMap<String, String>> initRequestParams(
|
||||
ServerHttpRequest request, Mono<MultiValueMap<String, String>> formDataMono) {
|
||||
|
||||
return formDataMono
|
||||
.map(formData -> {
|
||||
MultiValueMap<String, String> result = new LinkedMultiValueMap<>();
|
||||
result.putAll(request.getQueryParams());
|
||||
result.putAll(formData);
|
||||
return CollectionUtils.unmodifiableMultiValueMap(result);
|
||||
})
|
||||
.defaultIfEmpty(request.getQueryParams())
|
||||
.cache();
|
||||
}
|
||||
|
||||
|
||||
|
@ -144,6 +169,11 @@ public class DefaultServerWebExchange implements ServerWebExchange {
|
|||
return this.formDataMono;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<MultiValueMap<String, String>> getRequestParams() {
|
||||
return this.requestParamsMono;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotModified() {
|
||||
return this.notModified;
|
||||
|
|
|
@ -43,7 +43,8 @@ import static org.junit.Assert.assertNull;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Parameterized tests for ServletWebRequest
|
||||
* "checkNotModified" unit tests for {@link DefaultServerWebExchange}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -26,6 +26,7 @@ import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition.Para
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ParamsRequestCondition}.
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class ParamsRequestConditionTests {
|
||||
|
@ -36,34 +37,28 @@ public class ParamsRequestConditionTests {
|
|||
assertFalse(new ParamsRequestCondition("foo").equals(new ParamsRequestCondition("bar")));
|
||||
assertFalse(new ParamsRequestCondition("foo").equals(new ParamsRequestCondition("FOO")));
|
||||
assertEquals(new ParamsRequestCondition("foo=bar"), new ParamsRequestCondition("foo=bar"));
|
||||
assertFalse(
|
||||
new ParamsRequestCondition("foo=bar").equals(new ParamsRequestCondition("FOO=bar")));
|
||||
assertFalse(new ParamsRequestCondition("foo=bar").equals(new ParamsRequestCondition("FOO=bar")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramPresent() {
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("foo", "");
|
||||
|
||||
assertNotNull(condition.getMatchingCondition(request));
|
||||
assertNotNull(new ParamsRequestCondition("foo").getMatchingCondition(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramPresentNoMatch() {
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("bar", "");
|
||||
|
||||
assertNull(condition.getMatchingCondition(request));
|
||||
assertNull(new ParamsRequestCondition("foo").getMatchingCondition(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramNotPresent() {
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("!foo");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
assertNotNull(condition.getMatchingCondition(request));
|
||||
|
@ -71,22 +66,18 @@ public class ParamsRequestConditionTests {
|
|||
|
||||
@Test
|
||||
public void paramValueMatch() {
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo=bar");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("foo", "bar");
|
||||
|
||||
assertNotNull(condition.getMatchingCondition(request));
|
||||
assertNotNull(new ParamsRequestCondition("foo=bar").getMatchingCondition(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramValueNoMatch() {
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo=bar");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("foo", "bazz");
|
||||
|
||||
assertNull(condition.getMatchingCondition(request));
|
||||
assertNull(new ParamsRequestCondition("foo=bar").getMatchingCondition(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -113,20 +104,4 @@ public class ParamsRequestConditionTests {
|
|||
assertEquals(2, conditions.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMatchingCondition() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("foo", "bar");
|
||||
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo");
|
||||
|
||||
ParamsRequestCondition result = condition.getMatchingCondition(request);
|
||||
assertEquals(condition, result);
|
||||
|
||||
condition = new ParamsRequestCondition("bar");
|
||||
|
||||
result = condition.getMatchingCondition(request);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue