Introduce template methods to customize RestTemplate.

We now provide template methods on VaultTemplate and ReactiveVaultTemplate to customize RestTemplate respective WebClient.

Closes gh-200.
This commit is contained in:
Mark Paluch
2018-02-28 15:17:52 +01:00
parent 8d93493c35
commit 087d665c39
4 changed files with 102 additions and 23 deletions

View File

@@ -157,7 +157,8 @@ public abstract class AbstractVaultConfiguration implements ApplicationContextAw
}
/**
* Construct a {@link RestOperations} object configured for Vault usage.
* Construct a {@link RestOperations} object configured for Vault session management
* and authentication usage.
*
* @return the {@link RestOperations} to be used for Vault access.
* @see #vaultEndpointProvider()

View File

@@ -39,6 +39,7 @@ import org.springframework.web.reactive.function.client.WebClientException;
* session}.
*
* @author Mark Paluch
* @since 2.0
* @see ReactiveVaultOperations#doWithSession(Function)
* @see ReactiveVaultOperations#doWithVault(Function)
* @see WebClient

View File

@@ -56,6 +56,7 @@ import static org.springframework.web.reactive.function.client.ExchangeFilterFun
*
* @author Mark Paluch
* @see SessionManager
* @since 2.0
*/
public class ReactiveVaultTemplate implements ReactiveVaultOperations {
@@ -63,6 +64,8 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
private final WebClient sessionClient;
private final VaultTokenSupplier vaultTokenSupplier;
/**
* Create a new {@link ReactiveVaultTemplate} with a {@link VaultEndpoint},
* {@link ClientHttpConnector} and {@link VaultTokenSupplier}.
@@ -91,6 +94,51 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
Assert.notNull(connector, "ClientHttpConnector must not be null");
Assert.notNull(vaultTokenSupplier, "AuthenticationSupplier must not be null");
this.vaultTokenSupplier = vaultTokenSupplier;
this.statelessClient = doCreateWebClient(endpointProvider, connector);
this.sessionClient = doCreateSessionWebClient(endpointProvider, connector);
}
/**
* Create a {@link WebClient} to be used by {@link ReactiveVaultTemplate} for Vault
* communication given {@link VaultEndpointProvider} and {@link ClientHttpConnector}.
* {@link VaultEndpointProvider} is used to contribute host and port details for
* relative URLs typically used by the Template API. Subclasses may override this
* method to customize the {@link WebClient}.
*
* @param endpointProvider must not be {@literal null}.
* @param connector must not be {@literal null}.
* @return the {@link WebClient} used for Vault communication.
* @since 2.1
*/
protected WebClient doCreateWebClient(VaultEndpointProvider endpointProvider,
ClientHttpConnector connector) {
Assert.notNull(endpointProvider, "VaultEndpointProvider must not be null");
Assert.notNull(connector, "ClientHttpConnector must not be null");
return ReactiveVaultClients.createWebClient(endpointProvider, connector);
}
/**
* Create a session-bound {@link WebClient} to be used by {@link VaultTemplate} for
* Vault communication given {@link VaultEndpointProvider} and
* {@link ClientHttpConnector} for calls that require an authenticated context.
* {@link VaultEndpointProvider} is used to contribute host and port details for
* relative URLs typically used by the Template API. Subclasses may override this
* method to customize the {@link WebClient}.
*
* @param endpointProvider must not be {@literal null}.
* @param connector must not be {@literal null}.
* @return the {@link WebClient} used for Vault communication.
* @since 2.1
*/
protected WebClient doCreateSessionWebClient(VaultEndpointProvider endpointProvider,
ClientHttpConnector connector) {
Assert.notNull(endpointProvider, "VaultEndpointProvider must not be null");
Assert.notNull(connector, "ClientHttpConnector must not be null");
ExchangeFilterFunction filter = ofRequestProcessor(request -> vaultTokenSupplier
.getVaultToken().map(token -> {
@@ -99,10 +147,7 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
}).build();
}));
this.statelessClient = ReactiveVaultClients.createWebClient(endpointProvider,
connector);
this.sessionClient = ReactiveVaultClients
.createWebClient(endpointProvider, connector).mutate().filter(filter)
return doCreateWebClient(endpointProvider, connector).mutate().filter(filter)
.build();
}

View File

@@ -52,9 +52,9 @@ import org.springframework.web.client.RestTemplate;
*/
public class VaultTemplate implements InitializingBean, VaultOperations, DisposableBean {
private final RestTemplate sessionTemplate;
private final RestTemplate statelessTemplate;
private final RestTemplate plainTemplate;
private final RestTemplate sessionTemplate;
@Nullable
private SessionManager sessionManager;
@@ -82,9 +82,8 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
VaultEndpointProvider endpointProvider = SimpleVaultEndpointProvider
.of(vaultEndpoint);
this.sessionTemplate = createSessionTemplate(endpointProvider, requestFactory);
this.plainTemplate = VaultClients.createRestTemplate(vaultEndpoint,
requestFactory);
this.statelessTemplate = doCreateRestTemplate(endpointProvider, requestFactory);
this.sessionTemplate = doCreateSessionTemplate(endpointProvider, requestFactory);
}
/**
@@ -107,33 +106,66 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
* {@link ClientHttpRequestFactory} and {@link SessionManager}.
*
* @param endpointProvider must not be {@literal null}.
* @param clientHttpRequestFactory must not be {@literal null}.
* @param requestFactory must not be {@literal null}.
* @param sessionManager must not be {@literal null}.
* @since 1.1
*/
public VaultTemplate(VaultEndpointProvider endpointProvider,
ClientHttpRequestFactory clientHttpRequestFactory,
SessionManager sessionManager) {
ClientHttpRequestFactory requestFactory, SessionManager sessionManager) {
Assert.notNull(endpointProvider, "VaultEndpointProvider must not be null");
Assert.notNull(clientHttpRequestFactory,
"ClientHttpRequestFactory must not be null");
Assert.notNull(requestFactory, "ClientHttpRequestFactory must not be null");
Assert.notNull(sessionManager, "SessionManager must not be null");
this.sessionManager = sessionManager;
this.dedicatedSessionManager = false;
this.sessionTemplate = createSessionTemplate(endpointProvider,
clientHttpRequestFactory);
this.plainTemplate = VaultClients.createRestTemplate(endpointProvider,
clientHttpRequestFactory);
this.statelessTemplate = doCreateRestTemplate(endpointProvider, requestFactory);
this.sessionTemplate = doCreateSessionTemplate(endpointProvider, requestFactory);
}
private RestTemplate createSessionTemplate(VaultEndpointProvider endpointProvider,
/**
* Create a {@link RestTemplate} to be used by {@link VaultTemplate} for Vault
* communication given {@link VaultEndpointProvider} and
* {@link ClientHttpRequestFactory}. {@link VaultEndpointProvider} is used to
* contribute host and port details for relative URLs typically used by the Template
* API. Subclasses may override this method to customize the {@link RestTemplate}.
*
* @param endpointProvider must not be {@literal null}.
* @param requestFactory must not be {@literal null}.
* @return the {@link RestTemplate} used for Vault communication.
* @since 2.1
*/
protected RestTemplate doCreateRestTemplate(VaultEndpointProvider endpointProvider,
ClientHttpRequestFactory requestFactory) {
RestTemplate restTemplate = VaultClients.createRestTemplate(endpointProvider,
requestFactory);
Assert.notNull(endpointProvider, "VaultEndpointProvider must not be null");
Assert.notNull(requestFactory, "ClientHttpRequestFactory must not be null");
return VaultClients.createRestTemplate(endpointProvider, requestFactory);
}
/**
* Create a session-bound {@link RestTemplate} to be used by {@link VaultTemplate} for
* Vault communication given {@link VaultEndpointProvider} and
* {@link ClientHttpRequestFactory} for calls that require an authenticated context.
* {@link VaultEndpointProvider} is used to contribute host and port details for
* relative URLs typically used by the Template API. Subclasses may override this
* method to customize the {@link RestTemplate}.
*
* @param endpointProvider must not be {@literal null}.
* @param requestFactory must not be {@literal null}.
* @return the {@link RestTemplate} used for Vault communication.
* @since 2.1
*/
protected RestTemplate doCreateSessionTemplate(
VaultEndpointProvider endpointProvider,
ClientHttpRequestFactory requestFactory) {
Assert.notNull(endpointProvider, "VaultEndpointProvider must not be null");
Assert.notNull(requestFactory, "ClientHttpRequestFactory must not be null");
RestTemplate restTemplate = doCreateRestTemplate(endpointProvider, requestFactory);
restTemplate.getInterceptors().add(
(request, body, execution) -> {
@@ -291,7 +323,7 @@ public class VaultTemplate implements InitializingBean, VaultOperations, Disposa
Assert.notNull(clientCallback, "Client callback must not be null");
try {
return clientCallback.doWithRestOperations(plainTemplate);
return clientCallback.doWithRestOperations(statelessTemplate);
}
catch (HttpStatusCodeException e) {
throw VaultResponses.buildException(e);