From 4e10735e8f295db39301b3dd6f63dfb6e30b5342 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 3 May 2019 14:08:12 +0200 Subject: [PATCH 1/2] MockHttpServletRequest restores default locale for empty accept header Closes gh-22877 --- .../mock/web/MockHttpServletRequest.java | 20 ++++++++++--------- .../mock/web/MockHttpServletRequestTests.java | 9 ++++++++- .../mock/web/test/MockHttpServletRequest.java | 20 ++++++++++--------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java index 683f36e6c2..94e3a8f6cf 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -199,7 +199,7 @@ public class MockHttpServletRequest implements HttpServletRequest { private String remoteHost = DEFAULT_REMOTE_HOST; /** List of locales in descending order. */ - private final List locales = new LinkedList<>(); + private final LinkedList locales = new LinkedList<>(); private boolean secure = false; @@ -403,12 +403,11 @@ public class MockHttpServletRequest implements HttpServletRequest { private void updateContentTypeHeader() { if (StringUtils.hasLength(this.contentType)) { - StringBuilder sb = new StringBuilder(this.contentType); - if (!this.contentType.toLowerCase().contains(CHARSET_PREFIX) && - StringUtils.hasLength(this.characterEncoding)) { - sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding); + String value = this.contentType; + if (StringUtils.hasLength(this.characterEncoding) && !this.contentType.toLowerCase().contains(CHARSET_PREFIX)) { + value += ';' + CHARSET_PREFIX + this.characterEncoding; } - doAddHeaderValue(HttpHeaders.CONTENT_TYPE, sb.toString(), true); + doAddHeaderValue(HttpHeaders.CONTENT_TYPE, value, true); } } @@ -780,7 +779,7 @@ public class MockHttpServletRequest implements HttpServletRequest { */ public void addPreferredLocale(Locale locale) { Assert.notNull(locale, "Locale must not be null"); - this.locales.add(0, locale); + this.locales.addFirst(locale); updateAcceptLanguageHeader(); } @@ -818,7 +817,7 @@ public class MockHttpServletRequest implements HttpServletRequest { */ @Override public Locale getLocale() { - return this.locales.get(0); + return this.locales.getFirst(); } /** @@ -1016,6 +1015,9 @@ public class MockHttpServletRequest implements HttpServletRequest { List locales = headers.getAcceptLanguageAsLocales(); this.locales.clear(); this.locales.addAll(locales); + if (this.locales.isEmpty()) { + this.locales.add(Locale.ENGLISH); + } } catch (IllegalArgumentException ex) { // Invalid Accept-Language format -> just store plain header diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java index 1857c7a9bd..c28b95b378 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -351,6 +351,13 @@ public class MockHttpServletRequestTests { assertEquals("en_US", request.getHeader("Accept-Language")); } + @Test + public void emptyAcceptLanguageHeader() { + request.addHeader("Accept-Language", ""); + assertEquals(Locale.ENGLISH, request.getLocale()); + assertEquals("", request.getHeader("Accept-Language")); + } + @Test public void getServerNameWithDefaultName() { assertEquals("localhost", request.getServerName()); diff --git a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java index 395122c883..fbfa8721f0 100644 --- a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java +++ b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -199,7 +199,7 @@ public class MockHttpServletRequest implements HttpServletRequest { private String remoteHost = DEFAULT_REMOTE_HOST; /** List of locales in descending order. */ - private final List locales = new LinkedList<>(); + private final LinkedList locales = new LinkedList<>(); private boolean secure = false; @@ -403,12 +403,11 @@ public class MockHttpServletRequest implements HttpServletRequest { private void updateContentTypeHeader() { if (StringUtils.hasLength(this.contentType)) { - StringBuilder sb = new StringBuilder(this.contentType); - if (!this.contentType.toLowerCase().contains(CHARSET_PREFIX) && - StringUtils.hasLength(this.characterEncoding)) { - sb.append(";").append(CHARSET_PREFIX).append(this.characterEncoding); + String value = this.contentType; + if (StringUtils.hasLength(this.characterEncoding) && !this.contentType.toLowerCase().contains(CHARSET_PREFIX)) { + value += ';' + CHARSET_PREFIX + this.characterEncoding; } - doAddHeaderValue(HttpHeaders.CONTENT_TYPE, sb.toString(), true); + doAddHeaderValue(HttpHeaders.CONTENT_TYPE, value, true); } } @@ -780,7 +779,7 @@ public class MockHttpServletRequest implements HttpServletRequest { */ public void addPreferredLocale(Locale locale) { Assert.notNull(locale, "Locale must not be null"); - this.locales.add(0, locale); + this.locales.addFirst(locale); updateAcceptLanguageHeader(); } @@ -818,7 +817,7 @@ public class MockHttpServletRequest implements HttpServletRequest { */ @Override public Locale getLocale() { - return this.locales.get(0); + return this.locales.getFirst(); } /** @@ -1016,6 +1015,9 @@ public class MockHttpServletRequest implements HttpServletRequest { List locales = headers.getAcceptLanguageAsLocales(); this.locales.clear(); this.locales.addAll(locales); + if (this.locales.isEmpty()) { + this.locales.add(Locale.ENGLISH); + } } catch (IllegalArgumentException ex) { // Invalid Accept-Language format -> just store plain header From 84266d71e92701bf666c0ff1984288cc22056690 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 3 May 2019 14:08:20 +0200 Subject: [PATCH 2/2] Polishing --- .../transaction/PlatformTransactionManager.java | 6 +++--- .../function/client/ExchangeStrategies.java | 8 ++++---- .../reactive/function/server/HandlerStrategies.java | 13 +++++++------ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/spring-tx/src/main/java/org/springframework/transaction/PlatformTransactionManager.java b/spring-tx/src/main/java/org/springframework/transaction/PlatformTransactionManager.java index 3723549452..39ab82f665 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/PlatformTransactionManager.java +++ b/spring-tx/src/main/java/org/springframework/transaction/PlatformTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -41,7 +41,6 @@ import org.springframework.lang.Nullable; * @since 16.05.2003 * @see org.springframework.transaction.support.TransactionTemplate * @see org.springframework.transaction.interceptor.TransactionInterceptor - * @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean */ public interface PlatformTransactionManager { @@ -68,7 +67,8 @@ public interface PlatformTransactionManager { * @see TransactionDefinition#getTimeout * @see TransactionDefinition#isReadOnly */ - TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; + TransactionStatus getTransaction(@Nullable TransactionDefinition definition) + throws TransactionException; /** * Commit the given transaction, with regard to its status. If the transaction diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java index e62bee11ab..baefea67b5 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -37,18 +37,18 @@ public interface ExchangeStrategies { /** * Return {@link HttpMessageReader HttpMessageReaders} to read and decode the response body with. - * @return the stream of message readers + * @return the message readers */ List> messageReaders(); /** * Return {@link HttpMessageWriter HttpMessageWriters} to write and encode the request body with. - * @return the stream of message writers + * @return the message writers */ List> messageWriters(); - // Static methods + // Static builder methods /** * Return a new {@code ExchangeStrategies} with default configuration diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/HandlerStrategies.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/HandlerStrategies.java index 4933d81f4f..1d41f07d25 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/HandlerStrategies.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/HandlerStrategies.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -28,10 +28,11 @@ import org.springframework.web.server.WebFilter; import org.springframework.web.server.i18n.LocaleContextResolver; /** - * Defines the strategies to be used for processing {@link HandlerFunction HandlerFunctions}. An instance of - * this class is immutable; instances are typically created through the mutable {@link Builder}: - * either through {@link #builder()} to set up default strategies, or {@link #empty()} to start from - * scratch. + * Defines the strategies to be used for processing {@link HandlerFunction HandlerFunctions}. + * + *

An instance of this class is immutable. Instances are typically created through the + * mutable {@link Builder}: either through {@link #builder()} to set up default strategies, + * or {@link #empty()} to start from scratch. * * @author Arjen Poutsma * @author Juergen Hoeller @@ -78,7 +79,7 @@ public interface HandlerStrategies { LocaleContextResolver localeContextResolver(); - // Static methods + // Static builder methods /** * Return a new {@code HandlerStrategies} with default initialization.