Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
package org.springframework.web.reactive.function.client;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.function.Function;
import java.util.function.Predicate;

import org.jspecify.annotations.Nullable;
import reactor.core.publisher.Mono;

import org.springframework.core.io.buffer.DataBufferUtils;
Expand All @@ -34,6 +36,7 @@
* @author Rob Winch
* @author Arjen Poutsma
* @author Sam Brannen
* @author Kai Zander
* @since 5.0
*/
public abstract class ExchangeFilterFunctions {
Expand Down Expand Up @@ -76,14 +79,32 @@ public static ExchangeFilterFunction statusError(Predicate<HttpStatusCode> statu
* Return a filter that applies HTTP Basic Authentication to the request
* headers via {@link HttpHeaders#setBasicAuth(String)} and
* {@link HttpHeaders#encodeBasicAuth(String, String, Charset)}.
* <p>{@linkplain StandardCharsets#ISO_8859_1 ISO-8859-1} is used to convert the credentials into an octet sequence.
* @param username the username
* @param password the password
* @return the filter to add authentication headers with
* @see HttpHeaders#encodeBasicAuth(String, String, Charset)
* @see HttpHeaders#setBasicAuth(String)
*/
public static ExchangeFilterFunction basicAuthentication(String username, String password) {
String encodedCredentials = HttpHeaders.encodeBasicAuth(username, password, null);
return basicAuthentication(username, password, null);
}

/**
* Return a filter that applies HTTP Basic Authentication to the request
* headers via {@link HttpHeaders#setBasicAuth(String)} and
* {@link HttpHeaders#encodeBasicAuth(String, String, Charset)}.
* @param username the username
* @param password the password
* @param charset the charset to use to convert the credentials into an octet
* sequence. Defaults to {@linkplain StandardCharsets#ISO_8859_1 ISO-8859-1}.
* @return the filter to add authentication headers with
* @since 7.1
* @see HttpHeaders#encodeBasicAuth(String, String, Charset)
* @see HttpHeaders#setBasicAuth(String)
*/
public static ExchangeFilterFunction basicAuthentication(String username, String password, @Nullable Charset charset) {
String encodedCredentials = HttpHeaders.encodeBasicAuth(username, password, charset);
return (request, next) ->
next.exchange(ClientRequest.from(request)
.headers(headers -> headers.setBasicAuth(encodedCredentials))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
* Tests for {@link ExchangeFilterFunctions}.
*
* @author Arjen Poutsma
* @author Kai Zander
*/
class ExchangeFilterFunctionsTests {

Expand Down Expand Up @@ -104,7 +105,7 @@ void basicAuthenticationUsernamePassword() {

ExchangeFunction exchange = r -> {
assertThat(r.headers().containsHeader(HttpHeaders.AUTHORIZATION)).isTrue();
assertThat(r.headers().getFirst(HttpHeaders.AUTHORIZATION)).startsWith("Basic ");
assertThat(r.headers().getFirst(HttpHeaders.AUTHORIZATION)).isEqualTo("Basic Zm9vOmJhcg==");
return Mono.just(response);
};

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

@Test
void basicAuthenticationUsernameAndUnicodePassword() {
ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build();
ClientResponse response = mock();

ExchangeFunction exchange = r -> {
assertThat(r.headers().containsHeader(HttpHeaders.AUTHORIZATION)).isTrue();
assertThat(r.headers().getFirst(HttpHeaders.AUTHORIZATION)).isEqualTo("Basic Zm9vOvCfkqk=");
return Mono.just(response);
};

ExchangeFilterFunction auth = ExchangeFilterFunctions.basicAuthentication("foo", "\ud83d\udca9", StandardCharsets.UTF_8);
assertThat(request.headers().containsHeader(HttpHeaders.AUTHORIZATION)).isFalse();
ClientResponse result = auth.filter(request, exchange).block();
assertThat(result).isEqualTo(response);
}

@Test
void basicAuthenticationInvalidCharacters() {
ClientRequest request = ClientRequest.create(HttpMethod.GET, DEFAULT_URL).build();
Expand Down