Skip to content

Commit 4bb20ea

Browse files
kzander91sbrannen
authored andcommitted
Allow specifying charset to use in ExchangeFilterFunctions#basicAuthentication
Prior to this commit, it was not possible to specify the character set to use with ExchangeFilterFunctions#basicAuthentication. To address that, this commit introduces a new Closes gh-36777 Signed-off-by: Kai Zander <61500114+kzander91@users.noreply.github.com>
1 parent ac24766 commit 4bb20ea

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctions.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
package org.springframework.web.reactive.function.client;
1818

1919
import java.nio.charset.Charset;
20+
import java.nio.charset.StandardCharsets;
2021
import java.util.function.Function;
2122
import java.util.function.Predicate;
2223

24+
import org.jspecify.annotations.Nullable;
2325
import reactor.core.publisher.Mono;
2426

2527
import org.springframework.core.io.buffer.DataBufferUtils;
@@ -34,6 +36,7 @@
3436
* @author Rob Winch
3537
* @author Arjen Poutsma
3638
* @author Sam Brannen
39+
* @author Kai Zander
3740
* @since 5.0
3841
*/
3942
public abstract class ExchangeFilterFunctions {
@@ -76,14 +79,32 @@ public static ExchangeFilterFunction statusError(Predicate<HttpStatusCode> statu
7679
* Return a filter that applies HTTP Basic Authentication to the request
7780
* headers via {@link HttpHeaders#setBasicAuth(String)} and
7881
* {@link HttpHeaders#encodeBasicAuth(String, String, Charset)}.
82+
* <p>{@linkplain StandardCharsets#ISO_8859_1 ISO-8859-1} is used to convert the credentials into an octet sequence.
7983
* @param username the username
8084
* @param password the password
8185
* @return the filter to add authentication headers with
8286
* @see HttpHeaders#encodeBasicAuth(String, String, Charset)
8387
* @see HttpHeaders#setBasicAuth(String)
8488
*/
8589
public static ExchangeFilterFunction basicAuthentication(String username, String password) {
86-
String encodedCredentials = HttpHeaders.encodeBasicAuth(username, password, null);
90+
return basicAuthentication(username, password, null);
91+
}
92+
93+
/**
94+
* Return a filter that applies HTTP Basic Authentication to the request
95+
* headers via {@link HttpHeaders#setBasicAuth(String)} and
96+
* {@link HttpHeaders#encodeBasicAuth(String, String, Charset)}.
97+
* @param username the username
98+
* @param password the password
99+
* @param charset the charset to use to convert the credentials into an octet
100+
* sequence. Defaults to {@linkplain StandardCharsets#ISO_8859_1 ISO-8859-1}.
101+
* @return the filter to add authentication headers with
102+
* @since 7.0.8
103+
* @see HttpHeaders#encodeBasicAuth(String, String, Charset)
104+
* @see HttpHeaders#setBasicAuth(String)
105+
*/
106+
public static ExchangeFilterFunction basicAuthentication(String username, String password, @Nullable Charset charset) {
107+
String encodedCredentials = HttpHeaders.encodeBasicAuth(username, password, charset);
87108
return (request, next) ->
88109
next.exchange(ClientRequest.from(request)
89110
.headers(headers -> headers.setBasicAuth(encodedCredentials))

spring-webflux/src/test/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctionsTests.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
* Tests for {@link ExchangeFilterFunctions}.
4444
*
4545
* @author Arjen Poutsma
46+
* @author Kai Zander
4647
*/
4748
class ExchangeFilterFunctionsTests {
4849

@@ -104,7 +105,7 @@ void basicAuthenticationUsernamePassword() {
104105

105106
ExchangeFunction exchange = r -> {
106107
assertThat(r.headers().containsHeader(HttpHeaders.AUTHORIZATION)).isTrue();
107-
assertThat(r.headers().getFirst(HttpHeaders.AUTHORIZATION)).startsWith("Basic ");
108+
assertThat(r.headers().getFirst(HttpHeaders.AUTHORIZATION)).isEqualTo("Basic Zm9vOmJhcg==");
108109
return Mono.just(response);
109110
};
110111

@@ -114,6 +115,23 @@ void basicAuthenticationUsernamePassword() {
114115
assertThat(result).isEqualTo(response);
115116
}
116117

118+
@Test
119+
void basicAuthenticationUsernameAndUnicodePassword() {
120+
ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build();
121+
ClientResponse response = mock();
122+
123+
ExchangeFunction exchange = r -> {
124+
assertThat(r.headers().containsHeader(HttpHeaders.AUTHORIZATION)).isTrue();
125+
assertThat(r.headers().getFirst(HttpHeaders.AUTHORIZATION)).isEqualTo("Basic Zm9vOvCfkqk=");
126+
return Mono.just(response);
127+
};
128+
129+
ExchangeFilterFunction auth = ExchangeFilterFunctions.basicAuthentication("foo", "\ud83d\udca9", StandardCharsets.UTF_8);
130+
assertThat(request.headers().containsHeader(HttpHeaders.AUTHORIZATION)).isFalse();
131+
ClientResponse result = auth.filter(request, exchange).block();
132+
assertThat(result).isEqualTo(response);
133+
}
134+
117135
@Test
118136
void basicAuthenticationInvalidCharacters() {
119137
ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build();

0 commit comments

Comments
 (0)