Browse Source

Refine default filtered headers for web data binding

Prior to this commit, HTTP request data binding had been improved to
filter out by default the "Priority" header in #34039.

This commit extends the set of filtered header names with:
"Accept", "Authorization", "Connection", "Cookie", "From", "Host",
"Origin", "Priority", "Range", "Referer", "Upgrade".

If an application wishes to let those header be bound, it will need to
configure the binder and replace the default header predicate by calling
`setHeaderPredicate`.

Closes gh-34182
pull/34398/head
Brian Clozel 11 months ago
parent
commit
c971276f34
  1. 5
      spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ExtendedWebExchangeDataBinder.java
  2. 21
      spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/InitBinderBindingContextTests.java
  3. 5
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinder.java
  4. 17
      spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinderTests.java

5
spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ExtendedWebExchangeDataBinder.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -43,7 +43,8 @@ import org.springframework.web.server.ServerWebExchange; @@ -43,7 +43,8 @@ import org.springframework.web.server.ServerWebExchange;
*/
public class ExtendedWebExchangeDataBinder extends WebExchangeDataBinder {
private static final Set<String> FILTERED_HEADER_NAMES = Set.of("Priority");
private static final Set<String> FILTERED_HEADER_NAMES = Set.of("Accept", "Authorization", "Connection",
"Cookie", "From", "Host", "Origin", "Priority", "Range", "Referer", "Upgrade");
private Predicate<String> headerPredicate = name -> !FILTERED_HEADER_NAMES.contains(name);

21
spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/InitBinderBindingContextTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -23,6 +23,8 @@ import java.util.List; @@ -23,6 +23,8 @@ import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.core.DefaultParameterNameDiscoverer;
@ -220,6 +222,23 @@ class InitBinderBindingContextTests { @@ -220,6 +222,23 @@ class InitBinderBindingContextTests {
assertThat(map).containsExactlyInAnyOrderEntriesOf(Map.of("someIntArray", "1", "Some-Int-Array", "1"));
}
@ParameterizedTest
@ValueSource(strings = {"Accept", "Authorization", "Connection",
"Cookie", "From", "Host", "Origin", "Priority", "Range", "Referer", "Upgrade"})
void filteredHeaders(String headerName) throws Exception {
MockServerHttpRequest request = MockServerHttpRequest.get("/path")
.header(headerName, "u1")
.build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);
BindingContext context = createBindingContext("initBinderWithAttributeName", WebDataBinder.class);
ExtendedWebExchangeDataBinder binder = (ExtendedWebExchangeDataBinder) context.createDataBinder(exchange, null, "", null);
Map<String, Object> map = binder.getValuesToBind(exchange).block();
assertThat(map).isEmpty();
}
private BindingContext createBindingContext(String methodName, Class<?>... parameterTypes) throws Exception {
Object handler = new InitBinderHandler();
Method method = handler.getClass().getMethod(methodName, parameterTypes);

5
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinder.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -53,7 +53,8 @@ import org.springframework.web.servlet.HandlerMapping; @@ -53,7 +53,8 @@ import org.springframework.web.servlet.HandlerMapping;
*/
public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
private static final Set<String> FILTERED_HEADER_NAMES = Set.of("Priority");
private static final Set<String> FILTERED_HEADER_NAMES = Set.of("Accept", "Authorization", "Connection",
"Cookie", "From", "Host", "Origin", "Priority", "Range", "Referer", "Upgrade");
private Predicate<String> headerPredicate = name -> !FILTERED_HEADER_NAMES.contains(name);

17
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExtendedServletRequestDataBinderTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -21,6 +21,8 @@ import java.util.Map; @@ -21,6 +21,8 @@ import java.util.Map;
import jakarta.servlet.ServletRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.testfixture.beans.TestBean;
@ -104,6 +106,19 @@ class ExtendedServletRequestDataBinderTests { @@ -104,6 +106,19 @@ class ExtendedServletRequestDataBinderTests {
assertThat(target.getAge()).isEqualTo(25);
}
@ParameterizedTest
@ValueSource(strings = {"Accept", "Authorization", "Connection",
"Cookie", "From", "Host", "Origin", "Priority", "Range", "Referer", "Upgrade"})
void filteredHeaders(String headerName) {
TestBinder binder = new TestBinder();
MutablePropertyValues mpvs = new MutablePropertyValues();
request.addHeader(headerName, "u1");
binder.addBindValues(mpvs, request);
assertThat(mpvs).isEmpty();
}
@Test
void headerPredicate() {
TestBinder binder = new TestBinder();

Loading…
Cancel
Save