Add ClientRequest attributes

This commit introduces client-side request attributes, similar to those
found on the server-side. The attributes can be used, for instance, for
passing on request-specific information to a globally registered
ExchangeFilterFunction.

The client request builder, as well as WebClient.RequestHeadersSpec and
WebTestClient.RequestHeaderSpec, add methods for adding a single
attribute, as well as manipulating the entire attributes map.

The client request itself adds a accessor for the (immutable) attributes
map.

This commit also introduces a new variant of the basic authentication
filter in ExchangeFilterFunctions. This variant takes the username and
password from well-known attributes.

Issue: SPR-15691
This commit is contained in:
Arjen Poutsma
2017-07-05 14:37:23 +02:00
parent eb928ce456
commit 74b4c02881
9 changed files with 212 additions and 9 deletions

View File

@@ -145,6 +145,18 @@ public class DefaultWebClientTests {
client2.mutate().defaultCookies(cookies -> assertEquals(2, cookies.size()));
}
@Test
public void attributes() {
ExchangeFilterFunction filter = (request, next) -> {
assertEquals("bar", request.attributes().get("foo"));
return next.exchange(request);
};
WebClient client = builder().filter(filter).build();
client.get().uri("/path").attribute("foo", "bar").exchange();
}
private WebClient.Builder builder() {

View File

@@ -25,7 +25,7 @@ import org.springframework.http.HttpHeaders;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.springframework.http.HttpMethod.*;
import static org.springframework.http.HttpMethod.GET;
/**
* @author Arjen Poutsma
@@ -98,4 +98,23 @@ public class ExchangeFilterFunctionsTests {
assertEquals(response, result);
}
@Test
public void basicAuthenticationAttributes() throws Exception {
ClientRequest request = ClientRequest.method(GET, URI.create("http://example.com"))
.attribute(ExchangeFilterFunctions.USERNAME_ATTRIBUTE, "foo")
.attribute(ExchangeFilterFunctions.PASSWORD_ATTRIBUTE, "bar").build();
ClientResponse response = mock(ClientResponse.class);
ExchangeFunction exchange = r -> {
assertTrue(r.headers().containsKey(HttpHeaders.AUTHORIZATION));
assertTrue(r.headers().getFirst(HttpHeaders.AUTHORIZATION).startsWith("Basic "));
return Mono.just(response);
};
ExchangeFilterFunction auth = ExchangeFilterFunctions.basicAuthentication();
assertFalse(request.headers().containsKey(HttpHeaders.AUTHORIZATION));
ClientResponse result = auth.filter(request, exchange).block();
assertEquals(response, result);
}
}