mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-10-10 00:59:01 +00:00
Data binding from pathvars and headers in fn handlers
Closes gh-35800
This commit is contained in:
@@ -296,7 +296,8 @@ allPartsEvents.windowUntil(PartEvent::isLast)
|
||||
|
||||
NOTE: The body contents of the `PartEvent` objects must be completely consumed, relayed, or released to avoid memory leaks.
|
||||
|
||||
The following shows how to bind request parameters, including an optional `DataBinder` customization:
|
||||
The following shows how to bind request parameters, URI variables, or headers via `DataBinder`,
|
||||
and also shows how to customize the `DataBinder`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
||||
@@ -184,7 +184,8 @@ val map = request.params()
|
||||
----
|
||||
======
|
||||
|
||||
The following shows how to bind request parameters, including an optional `DataBinder` customization:
|
||||
The following shows how to bind request parameters, URI variables, or headers via `DataBinder`,
|
||||
and also shows how to customize the `DataBinder`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
||||
+2
-1
@@ -61,6 +61,7 @@ import org.springframework.web.reactive.accept.ApiVersionStrategy;
|
||||
import org.springframework.web.reactive.function.BodyExtractor;
|
||||
import org.springframework.web.reactive.function.BodyExtractors;
|
||||
import org.springframework.web.reactive.function.UnsupportedMediaTypeException;
|
||||
import org.springframework.web.reactive.result.method.annotation.ExtendedWebExchangeDataBinder;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||
@@ -244,7 +245,7 @@ class DefaultServerRequest implements ServerRequest {
|
||||
Assert.notNull(dataBinderCustomizer, "DataBinderCustomizer must not be null");
|
||||
|
||||
return Mono.defer(() -> {
|
||||
WebExchangeDataBinder dataBinder = new WebExchangeDataBinder(null);
|
||||
WebExchangeDataBinder dataBinder = new ExtendedWebExchangeDataBinder(null);
|
||||
dataBinder.setTargetType(ResolvableType.forClass(bindType));
|
||||
dataBinderCustomizer.accept(dataBinder);
|
||||
|
||||
|
||||
+11
@@ -51,6 +51,17 @@ public class ExtendedWebExchangeDataBinder extends WebExchangeDataBinder {
|
||||
private Predicate<String> headerPredicate = name -> !FILTERED_HEADER_NAMES.contains(name.toLowerCase(Locale.ROOT));
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance, with default object name.
|
||||
* @param target the target object to bind onto (or {@code null} if the
|
||||
* binder is just used to convert a plain parameter value)
|
||||
* @since 7.0.2
|
||||
* @see #DEFAULT_OBJECT_NAME
|
||||
*/
|
||||
public ExtendedWebExchangeDataBinder(@Nullable Object target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
public ExtendedWebExchangeDataBinder(@Nullable Object target, String objectName) {
|
||||
super(target, objectName);
|
||||
}
|
||||
|
||||
+7
-3
@@ -30,6 +30,7 @@ import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpSe
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
|
||||
|
||||
/**
|
||||
* Integration tests with data binding in fn handlers.
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
class BindingFunctionIntegrationTests extends AbstractRouterFunctionIntegrationTests {
|
||||
@@ -65,7 +66,8 @@ class BindingFunctionIntegrationTests extends AbstractRouterFunctionIntegrationT
|
||||
startServer(httpServer);
|
||||
|
||||
Mono<String> result = this.webClient.get()
|
||||
.uri("/constructor?foo=FOO&bar=BAR")
|
||||
.uri("/constructor?foo=FOO")
|
||||
.header("bar", "BAR")
|
||||
.retrieve()
|
||||
.bodyToMono(String.class);
|
||||
|
||||
@@ -80,7 +82,8 @@ class BindingFunctionIntegrationTests extends AbstractRouterFunctionIntegrationT
|
||||
startServer(httpServer);
|
||||
|
||||
Mono<String> result = this.webClient.get()
|
||||
.uri("/property?foo=FOO&bar=BAR")
|
||||
.uri("/property?foo=FOO")
|
||||
.header("bar", "BAR")
|
||||
.retrieve()
|
||||
.bodyToMono(String.class);
|
||||
|
||||
@@ -95,7 +98,8 @@ class BindingFunctionIntegrationTests extends AbstractRouterFunctionIntegrationT
|
||||
startServer(httpServer);
|
||||
|
||||
Mono<String> result = this.webClient.get()
|
||||
.uri("/mixed?foo=FOO&bar=BAR")
|
||||
.uri("/mixed?foo=FOO")
|
||||
.header("bar", "BAR")
|
||||
.retrieve()
|
||||
.bodyToMono(String.class);
|
||||
|
||||
|
||||
+2
-1
@@ -76,6 +76,7 @@ import org.springframework.web.bind.ServletRequestDataBinder;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder;
|
||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
import org.springframework.web.util.UriBuilder;
|
||||
@@ -258,7 +259,7 @@ class DefaultServerRequest implements ServerRequest {
|
||||
Assert.notNull(bindType, "BindType must not be null");
|
||||
Assert.notNull(dataBinderCustomizer, "DataBinderCustomizer must not be null");
|
||||
|
||||
ServletRequestDataBinder dataBinder = new ServletRequestDataBinder(null);
|
||||
ServletRequestDataBinder dataBinder = new ExtendedServletRequestDataBinder(null);
|
||||
dataBinder.setTargetType(ResolvableType.forClass(bindType));
|
||||
dataBinderCustomizer.accept(dataBinder);
|
||||
|
||||
|
||||
+4
-5
@@ -64,8 +64,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefaultServerRequest}.
|
||||
*
|
||||
* Unit tests for {@link DefaultServerRequest}.
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
class DefaultServerRequestTests {
|
||||
@@ -350,7 +349,7 @@ class DefaultServerRequestTests {
|
||||
void bindToConstructor() throws BindException {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.addParameter("foo", "FOO");
|
||||
servletRequest.addParameter("bar", "BAR");
|
||||
servletRequest.addHeader("bar", "BAR");
|
||||
|
||||
DefaultServerRequest request = new DefaultServerRequest(servletRequest, this.messageConverters);
|
||||
|
||||
@@ -363,7 +362,7 @@ class DefaultServerRequestTests {
|
||||
void bindToProperties() throws BindException {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.addParameter("foo", "FOO");
|
||||
servletRequest.addParameter("bar", "BAR");
|
||||
servletRequest.addHeader("bar", "BAR");
|
||||
|
||||
DefaultServerRequest request = new DefaultServerRequest(servletRequest, this.messageConverters);
|
||||
|
||||
@@ -376,7 +375,7 @@ class DefaultServerRequestTests {
|
||||
void bindToMixed() throws BindException {
|
||||
MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true);
|
||||
servletRequest.addParameter("foo", "FOO");
|
||||
servletRequest.addParameter("bar", "BAR");
|
||||
servletRequest.addHeader("bar", "BAR");
|
||||
|
||||
DefaultServerRequest request = new DefaultServerRequest(servletRequest, this.messageConverters);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user