From b6a5402d885c41c911b42d35b3cd9e1f13d63ebf Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Tue, 25 Feb 2025 17:11:37 +0100 Subject: [PATCH] Fix multiple Content-Language values in MockHttpServletResponse Prior to this commit, `MockHttpServletResponse` would only support adding a `Content-Language` once. Adding multiple header values would always replace the content-language property in the response and the entire header value. This commit ensures that this behavior is supported. Fixes gh-34488 --- .../mock/web/MockHttpServletResponse.java | 21 +++++++++++-------- .../web/MockHttpServletResponseTests.java | 8 +++++++ .../servlet/MockHttpServletResponse.java | 21 +++++++++++-------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java index 38bc1b72d14..3217d6e8eb1 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.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. @@ -743,14 +743,17 @@ public class MockHttpServletResponse implements HttpServletResponse { } else if (HttpHeaders.CONTENT_LANGUAGE.equalsIgnoreCase(name)) { String contentLanguages = value.toString(); - HttpHeaders headers = new HttpHeaders(); - headers.add(HttpHeaders.CONTENT_LANGUAGE, contentLanguages); - Locale language = headers.getContentLanguage(); - setLocale(language != null ? language : Locale.getDefault()); - // Since setLocale() sets the Content-Language header to the given - // single Locale, we have to explicitly set the Content-Language header - // to the user-provided value. - doAddHeaderValue(HttpHeaders.CONTENT_LANGUAGE, contentLanguages, true); + // only set the locale if we replace the header or if there was none before + if (replaceHeader || !this.headers.containsKey(HttpHeaders.CONTENT_LANGUAGE)) { + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_LANGUAGE, contentLanguages); + Locale language = headers.getContentLanguage(); + this.locale = language != null ? language : Locale.getDefault(); + doAddHeaderValue(HttpHeaders.CONTENT_LANGUAGE, contentLanguages, replaceHeader); + } + else { + doAddHeaderValue(HttpHeaders.CONTENT_LANGUAGE, contentLanguages, false); + } return true; } else if (HttpHeaders.SET_COOKIE.equalsIgnoreCase(name)) { diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java index 131e0696673..68c23013bda 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java @@ -641,4 +641,12 @@ class MockHttpServletResponseTests { assertThat(response.getContentAsString()).isEqualTo(content); } + @Test // gh-34488 + void shouldAddMultipleContentLanguage() { + response.addHeader("Content-Language", "en"); + response.addHeader("Content-Language", "fr"); + assertThat(response.getHeaders("Content-Language")).contains("en", "fr"); + assertThat(response.getLocale()).isEqualTo(Locale.ENGLISH); + } + } diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java index 21db9670176..5de70d3295c 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.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. @@ -743,14 +743,17 @@ public class MockHttpServletResponse implements HttpServletResponse { } else if (HttpHeaders.CONTENT_LANGUAGE.equalsIgnoreCase(name)) { String contentLanguages = value.toString(); - HttpHeaders headers = new HttpHeaders(); - headers.add(HttpHeaders.CONTENT_LANGUAGE, contentLanguages); - Locale language = headers.getContentLanguage(); - setLocale(language != null ? language : Locale.getDefault()); - // Since setLocale() sets the Content-Language header to the given - // single Locale, we have to explicitly set the Content-Language header - // to the user-provided value. - doAddHeaderValue(HttpHeaders.CONTENT_LANGUAGE, contentLanguages, true); + // only set the locale if we replace the header or if there was none before + if (replaceHeader || !this.headers.containsKey(HttpHeaders.CONTENT_LANGUAGE)) { + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_LANGUAGE, contentLanguages); + Locale language = headers.getContentLanguage(); + this.locale = language != null ? language : Locale.getDefault(); + doAddHeaderValue(HttpHeaders.CONTENT_LANGUAGE, contentLanguages, replaceHeader); + } + else { + doAddHeaderValue(HttpHeaders.CONTENT_LANGUAGE, contentLanguages, false); + } return true; } else if (HttpHeaders.SET_COOKIE.equalsIgnoreCase(name)) {