From d7c13d651885e0d4fb6eadb2a5258506f7838f27 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Thu, 24 Apr 2025 17:36:29 +0800 Subject: [PATCH 1/2] HttpEntity.EMPTY should be immutable See gh-34812 Signed-off-by: Yanming Zhou --- .../main/java/org/springframework/http/HttpEntity.java | 3 ++- .../java/org/springframework/http/HttpEntityTests.java | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/spring-web/src/main/java/org/springframework/http/HttpEntity.java b/spring-web/src/main/java/org/springframework/http/HttpEntity.java index b3203e4e05d..046dac774b6 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpEntity.java +++ b/spring-web/src/main/java/org/springframework/http/HttpEntity.java @@ -49,6 +49,7 @@ import org.springframework.util.ObjectUtils; * * @author Arjen Poutsma * @author Juergen Hoeller + * @author Yanming Zhou * @since 3.0.2 * @param the body type * @see org.springframework.web.client.RestTemplate @@ -60,7 +61,7 @@ public class HttpEntity { /** * The empty {@code HttpEntity}, with no body or headers. */ - public static final HttpEntity EMPTY = new HttpEntity<>(); + public static final HttpEntity EMPTY = new HttpEntity<>(HttpHeaders.EMPTY); private final HttpHeaders headers; diff --git a/spring-web/src/test/java/org/springframework/http/HttpEntityTests.java b/spring-web/src/test/java/org/springframework/http/HttpEntityTests.java index c6a75829107..95f0165b17c 100644 --- a/spring-web/src/test/java/org/springframework/http/HttpEntityTests.java +++ b/spring-web/src/test/java/org/springframework/http/HttpEntityTests.java @@ -27,6 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; /** * @author Arjen Poutsma + * @author Yanming Zhou */ class HttpEntityTests { @@ -123,4 +124,11 @@ class HttpEntityTests { assertThat(requestEntity2).isEqualTo(requestEntity); } + @Test + void emptyHttpEntityShouldBeImmutable() { + HttpHeaders newHeaders = new HttpHeaders(HttpEntity.EMPTY.getHeaders()); + newHeaders.add("Authorization", "Bearer some-token"); + assertThat(HttpEntity.EMPTY.getHeaders().headerNames()).isEmpty(); + } + } From c88ba6c90eceb409a7628b54b9e7402f72b0c353 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Mon, 28 Apr 2025 14:22:01 +0100 Subject: [PATCH 2/2] Polishing contribution Closes gh-34812 --- .../org/springframework/http/HttpEntity.java | 6 +++--- .../springframework/http/HttpEntityTests.java | 20 +++++++++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/HttpEntity.java b/spring-web/src/main/java/org/springframework/http/HttpEntity.java index 046dac774b6..c9359ba60b8 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpEntity.java +++ b/spring-web/src/main/java/org/springframework/http/HttpEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 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. @@ -49,7 +49,6 @@ import org.springframework.util.ObjectUtils; * * @author Arjen Poutsma * @author Juergen Hoeller - * @author Yanming Zhou * @since 3.0.2 * @param the body type * @see org.springframework.web.client.RestTemplate @@ -59,7 +58,8 @@ import org.springframework.util.ObjectUtils; public class HttpEntity { /** - * The empty {@code HttpEntity}, with no body or headers. + * An {@code HttpEntity} instance with a {@code null} body and + * {@link HttpHeaders#EMPTY empty headers}. */ public static final HttpEntity EMPTY = new HttpEntity<>(HttpHeaders.EMPTY); diff --git a/spring-web/src/test/java/org/springframework/http/HttpEntityTests.java b/spring-web/src/test/java/org/springframework/http/HttpEntityTests.java index 95f0165b17c..b79de1b9dd2 100644 --- a/spring-web/src/test/java/org/springframework/http/HttpEntityTests.java +++ b/spring-web/src/test/java/org/springframework/http/HttpEntityTests.java @@ -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. @@ -26,6 +26,8 @@ import org.springframework.util.MultiValueMap; import static org.assertj.core.api.Assertions.assertThat; /** + * Unit tests for {@link HttpEntity}. + * * @author Arjen Poutsma * @author Yanming Zhou */ @@ -35,6 +37,7 @@ class HttpEntityTests { void noHeaders() { String body = "foo"; HttpEntity entity = new HttpEntity<>(body); + assertThat(entity.getBody()).isSameAs(body); assertThat(entity.getHeaders()).isEmpty(); } @@ -45,6 +48,7 @@ class HttpEntityTests { headers.setContentType(MediaType.TEXT_PLAIN); String body = "foo"; HttpEntity entity = new HttpEntity<>(body, headers); + assertThat(entity.getBody()).isEqualTo(body); assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.TEXT_PLAIN); assertThat(entity.getHeaders().getFirst("Content-Type")).isEqualTo("text/plain"); @@ -56,6 +60,7 @@ class HttpEntityTests { map.set("Content-Type", "text/plain"); String body = "foo"; HttpEntity entity = new HttpEntity<>(body, map); + assertThat(entity.getBody()).isEqualTo(body); assertThat(entity.getHeaders().getContentType()).isEqualTo(MediaType.TEXT_PLAIN); assertThat(entity.getHeaders().getFirst("Content-Type")).isEqualTo("text/plain"); @@ -124,11 +129,14 @@ class HttpEntityTests { assertThat(requestEntity2).isEqualTo(requestEntity); } - @Test - void emptyHttpEntityShouldBeImmutable() { - HttpHeaders newHeaders = new HttpHeaders(HttpEntity.EMPTY.getHeaders()); - newHeaders.add("Authorization", "Bearer some-token"); - assertThat(HttpEntity.EMPTY.getHeaders().headerNames()).isEmpty(); + @Test // gh-34806 + void mutateEmptyInstanceHeaders() { + HttpHeaders headers = new HttpHeaders(HttpEntity.EMPTY.getHeaders()); + headers.add("Authorization", "Bearer some-token"); + + assertThat(HttpEntity.EMPTY.getHeaders()) + .as("Headers of HttpEntity.EMPTY should remain empty") + .isEmpty(); } }