Merge branch '6.2.x'
This commit is contained in:
@@ -21,12 +21,14 @@ import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.ServletRequestDataBinder;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
@@ -51,6 +53,12 @@ import org.springframework.web.servlet.HandlerMapping;
|
||||
*/
|
||||
public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
||||
|
||||
private static final Set<String> FILTERED_HEADER_NAMES = Set.of("Priority");
|
||||
|
||||
|
||||
private Predicate<String> headerPredicate = name -> !FILTERED_HEADER_NAMES.contains(name);
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance, with default object name.
|
||||
* @param target the target object to bind onto (or {@code null}
|
||||
@@ -73,6 +81,29 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a Predicate that filters the header names to use for data binding.
|
||||
* Multiple predicates are combined with {@code AND}.
|
||||
* @param headerPredicate the predicate to add
|
||||
* @since 6.2.1
|
||||
*/
|
||||
public void addHeaderPredicate(Predicate<String> headerPredicate) {
|
||||
this.headerPredicate = this.headerPredicate.and(headerPredicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Predicate that filters the header names to use for data binding.
|
||||
* <p>Note that this method resets any previous predicates that may have been
|
||||
* set, including headers excluded by default such as the RFC 9218 defined
|
||||
* "Priority" header.
|
||||
* @param headerPredicate the predicate to add
|
||||
* @since 6.2.1
|
||||
*/
|
||||
public void setHeaderPredicate(Predicate<String> headerPredicate) {
|
||||
this.headerPredicate = headerPredicate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected ServletRequestValueResolver createValueResolver(ServletRequest request) {
|
||||
return new ExtendedServletRequestValueResolver(request, this);
|
||||
@@ -93,7 +124,7 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
||||
String name = names.nextElement();
|
||||
Object value = getHeaderValue(httpRequest, name);
|
||||
if (value != null) {
|
||||
name = name.replace("-", "");
|
||||
name = StringUtils.uncapitalize(name.replace("-", ""));
|
||||
addValueIfNotPresent(mpvs, "Header", name, value);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +149,11 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Object getHeaderValue(HttpServletRequest request, String name) {
|
||||
private Object getHeaderValue(HttpServletRequest request, String name) {
|
||||
if (!this.headerPredicate.test(name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Enumeration<String> valuesEnum = request.getHeaders(name);
|
||||
if (!valuesEnum.hasMoreElements()) {
|
||||
return null;
|
||||
@@ -141,7 +176,7 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
||||
/**
|
||||
* Resolver of values that looks up URI path variables.
|
||||
*/
|
||||
private static class ExtendedServletRequestValueResolver extends ServletRequestValueResolver {
|
||||
private class ExtendedServletRequestValueResolver extends ServletRequestValueResolver {
|
||||
|
||||
ExtendedServletRequestValueResolver(ServletRequest request, WebDataBinder dataBinder) {
|
||||
super(request, dataBinder);
|
||||
@@ -156,6 +191,9 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
||||
if (uriVars != null) {
|
||||
value = uriVars.get(name);
|
||||
}
|
||||
if (value == null && getRequest() instanceof HttpServletRequest httpServletRequest) {
|
||||
value = getHeaderValue(httpServletRequest, name);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -167,6 +205,13 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
||||
if (uriVars != null) {
|
||||
set.addAll(uriVars.keySet());
|
||||
}
|
||||
if (request instanceof HttpServletRequest httpServletRequest) {
|
||||
Enumeration<String> enumeration = httpServletRequest.getHeaderNames();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
String headerName = enumeration.nextElement();
|
||||
set.add(headerName.replaceAll("-", ""));
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,16 @@ package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.web.bind.ServletRequestDataBinder;
|
||||
import org.springframework.web.bind.annotation.BindParam;
|
||||
import org.springframework.web.bind.support.BindParamNameResolver;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
@@ -45,7 +50,7 @@ class ExtendedServletRequestDataBinderTests {
|
||||
|
||||
|
||||
@Test
|
||||
void createBinder() {
|
||||
void createBinderViaSetters() {
|
||||
request.setAttribute(
|
||||
HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE,
|
||||
Map.of("name", "John", "age", "25"));
|
||||
@@ -62,6 +67,27 @@ class ExtendedServletRequestDataBinderTests {
|
||||
assertThat(target.getSomeIntArray()).containsExactly(1, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createBinderViaConstructor() {
|
||||
request.setAttribute(
|
||||
HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE,
|
||||
Map.of("name", "John", "age", "25"));
|
||||
|
||||
request.addHeader("Some-Int-Array", "1");
|
||||
request.addHeader("Some-Int-Array", "2");
|
||||
|
||||
ServletRequestDataBinder binder = new ExtendedServletRequestDataBinder(null);
|
||||
binder.setTargetType(ResolvableType.forClass(DataBean.class));
|
||||
binder.setNameResolver(new BindParamNameResolver());
|
||||
binder.construct(request);
|
||||
|
||||
DataBean bean = (DataBean) binder.getTarget();
|
||||
|
||||
assertThat(bean.name()).isEqualTo("John");
|
||||
assertThat(bean.age()).isEqualTo(25);
|
||||
assertThat(bean.someIntArray()).containsExactly(1, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uriVarsAndHeadersAddedConditionally() {
|
||||
request.addParameter("name", "John");
|
||||
@@ -78,6 +104,22 @@ class ExtendedServletRequestDataBinderTests {
|
||||
assertThat(target.getAge()).isEqualTo(25);
|
||||
}
|
||||
|
||||
@Test
|
||||
void headerPredicate() {
|
||||
TestBinder binder = new TestBinder();
|
||||
binder.addHeaderPredicate(name -> !name.equalsIgnoreCase("Another-Int-Array"));
|
||||
|
||||
MutablePropertyValues mpvs = new MutablePropertyValues();
|
||||
request.addHeader("Priority", "u1");
|
||||
request.addHeader("Some-Int-Array", "1");
|
||||
request.addHeader("Another-Int-Array", "1");
|
||||
|
||||
binder.addBindValues(mpvs, request);
|
||||
|
||||
assertThat(mpvs.size()).isEqualTo(1);
|
||||
assertThat(mpvs.get("someIntArray")).isEqualTo("1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void noUriTemplateVars() {
|
||||
TestBean target = new TestBean();
|
||||
@@ -88,4 +130,21 @@ class ExtendedServletRequestDataBinderTests {
|
||||
assertThat(target.getAge()).isEqualTo(0);
|
||||
}
|
||||
|
||||
|
||||
private record DataBean(String name, int age, @BindParam("Some-Int-Array") Integer[] someIntArray) {
|
||||
}
|
||||
|
||||
|
||||
private static class TestBinder extends ExtendedServletRequestDataBinder {
|
||||
|
||||
public TestBinder() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(MutablePropertyValues mpvs, ServletRequest request) {
|
||||
super.addBindValues(mpvs, request);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user