Polish gh-13976

Closes gh-13757
This commit is contained in:
Steve Riesenberg 2023-10-12 17:06:03 -05:00
parent a6b872dcf3
commit 5161712c35
No known key found for this signature in database
GPG Key ID: 5F311AB48A55D521
2 changed files with 20 additions and 21 deletions

View File

@ -44,22 +44,23 @@ class ReactiveRemoteJWKSource implements ReactiveJWKSource {
private final AtomicReference<Mono<JWKSet>> cachedJWKSet = new AtomicReference<>(Mono.empty()); private final AtomicReference<Mono<JWKSet>> cachedJWKSet = new AtomicReference<>(Mono.empty());
/** /**
* cached url for jwk set. * The cached JWK set URL.
*/ */
private final AtomicReference<String> cachedJwkSetUrl = new AtomicReference<>(); private final AtomicReference<String> cachedJwkSetUrl = new AtomicReference<>();
private WebClient webClient = WebClient.create(); private WebClient webClient = WebClient.create();
private Mono<String> jwkSetURLProvider; private final Mono<String> jwkSetUrlProvider;
ReactiveRemoteJWKSource(String jwkSetURL) { ReactiveRemoteJWKSource(String jwkSetURL) {
Assert.hasText(jwkSetURL, "jwkSetURL cannot be empty"); Assert.hasText(jwkSetURL, "jwkSetURL cannot be empty");
this.cachedJwkSetUrl.set(jwkSetURL); this.jwkSetUrlProvider = Mono.just(jwkSetURL);
} }
ReactiveRemoteJWKSource(Mono<String> jwkSetURLProvider) { ReactiveRemoteJWKSource(Mono<String> jwkSetUrlProvider) {
Assert.notNull(jwkSetURLProvider, "jwkSetURLProvider cannot be null"); Assert.notNull(jwkSetUrlProvider, "jwkSetUrlProvider cannot be null");
this.jwkSetURLProvider = jwkSetURLProvider; this.jwkSetUrlProvider = Mono.fromCallable(this.cachedJwkSetUrl::get)
.switchIfEmpty(Mono.defer(() -> jwkSetUrlProvider.doOnNext(this.cachedJwkSetUrl::set)));
} }
@Override @Override
@ -105,10 +106,7 @@ class ReactiveRemoteJWKSource implements ReactiveJWKSource {
*/ */
private Mono<JWKSet> getJWKSet() { private Mono<JWKSet> getJWKSet() {
// @formatter:off // @formatter:off
return Mono.justOrEmpty(this.cachedJwkSetUrl.get()) return this.jwkSetUrlProvider
.switchIfEmpty(Mono.defer(() -> this.jwkSetURLProvider
.doOnNext(this.cachedJwkSetUrl::set))
)
.flatMap((jwkSetURL) -> this.webClient.get() .flatMap((jwkSetURL) -> this.webClient.get()
.uri(jwkSetURL) .uri(jwkSetURL)
.retrieve() .retrieve()

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -32,15 +32,16 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.doReturn; import static org.mockito.BDDMockito.willReturn;
import static org.mockito.Mockito.doThrow; import static org.mockito.BDDMockito.willThrow;
/** /**
* @author Rob Winch * @author Rob Winch
@ -168,14 +169,14 @@ public class ReactiveRemoteJWKSourceTests {
@Test @Test
public void getShouldRecoverAndReturnKeysAfterErrorCase() { public void getShouldRecoverAndReturnKeysAfterErrorCase() {
given(this.matcher.matches(any())).willReturn(true); given(this.matcher.matches(any())).willReturn(true);
this.source = new ReactiveRemoteJWKSource(Mono.fromSupplier(mockStringSupplier)); this.source = new ReactiveRemoteJWKSource(Mono.fromSupplier(this.mockStringSupplier));
doThrow(WebClientResponseException.ServiceUnavailable.class).when(this.mockStringSupplier).get(); willThrow(WebClientResponseException.ServiceUnavailable.class).given(this.mockStringSupplier).get();
// first case: id provider has error state // first case: id provider has error state
assertThatThrownBy(() -> this.source.get(this.selector).block()) assertThatExceptionOfType(WebClientResponseException.ServiceUnavailable.class)
.isExactlyInstanceOf(WebClientResponseException.ServiceUnavailable.class); .isThrownBy(() -> this.source.get(this.selector).block());
// second case: id provider is healthy again // second case: id provider is healthy again
doReturn(this.server.url("/").toString()).when(this.mockStringSupplier).get(); willReturn(this.server.url("/").toString()).given(this.mockStringSupplier).get();
var actual = this.source.get(this.selector).block(); List<JWK> actual = this.source.get(this.selector).block();
assertThat(actual).isNotEmpty(); assertThat(actual).isNotEmpty();
} }