Expose request URI in McpHttpClientAuthorizationErrorHandler

Breaking change

Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
This commit is contained in:
Daniel Garnier-Moiroux 2026-05-22 09:38:18 +02:00 • committed by Daniel Garnier-Moiroux
commit 4f3f7d9fa4

View file

@ -16,7 +16,7 @@ import java.util.function.Consumer;
import java.util.function.Predicate;
import com.sun.net.httpserver.HttpServer;
import io.modelcontextprotocol.client.transport.customizer.McpHttpClientAuthorizationErrorHandler;
import io.modelcontextprotocol.client.transport.customizer.McpHttpClientTransportAuthorizationErrorHandler;
import io.modelcontextprotocol.common.McpTransportContext;
import io.modelcontextprotocol.server.transport.TomcatTestUtil;
import io.modelcontextprotocol.spec.HttpHeaders;
@ -403,9 +403,12 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
AtomicReference<HttpResponse.ResponseInfo> capturedResponseInfo = new AtomicReference<>();
AtomicReference<McpTransportContext> capturedContext = new AtomicReference<>();
AtomicReference<HttpRequestSnapshot> capturedSnapshot = new AtomicReference<>();
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.authorizationErrorHandler((responseInfo, context) -> {
.authorizationErrorHandler((requestSnapshot, responseInfo, context) -> {
capturedResponseInfo.set(responseInfo);
capturedSnapshot.set(requestSnapshot);
capturedContext.set(context);
return Mono.just(false);
})
@ -417,6 +420,8 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
assertThat(processedMessagesCount.get()).isEqualTo(1);
assertThat(capturedResponseInfo.get()).isNotNull();
assertThat(capturedResponseInfo.get().statusCode()).isEqualTo(httpStatus);
assertThat(capturedSnapshot.get()).isNotNull();
assertThat(capturedSnapshot.get().requestUri().toString()).isEqualTo(HOST + "/mcp");
assertThat(capturedContext.get()).isNotNull();
StepVerifier.create(authTransport.closeGracefully()).verifyComplete();
@ -440,7 +445,7 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
void retry() {
serverResponseStatus.set(401);
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.authorizationErrorHandler((responseInfo, context) -> {
.authorizationErrorHandler((requestSnapshot, responseInfo, context) -> {
serverResponseStatus.set(200);
return Mono.just(true);
})
@ -456,7 +461,7 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
void retryAtMostOnce() {
serverResponseStatus.set(401);
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.authorizationErrorHandler((responseInfo, context) -> Mono.just(true))
.authorizationErrorHandler((requestSnapshot, responseInfo, context) -> Mono.just(true))
.build();
StepVerifier.create(authTransport.sendMessage(createTestRequestMessage()))
.expectErrorMatches(authorizationError(401))
@ -471,10 +476,10 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
void customMaxRetries() {
serverResponseStatus.set(401);
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.authorizationErrorHandler(new McpHttpClientAuthorizationErrorHandler() {
.authorizationErrorHandler(new McpHttpClientTransportAuthorizationErrorHandler() {
@Override
public Publisher<Boolean> handle(HttpResponse.ResponseInfo responseInfo,
McpTransportContext context) {
public Publisher<Boolean> handle(HttpRequestSnapshot requestSnapshot,
HttpResponse.ResponseInfo responseInfo, McpTransportContext context) {
return Mono.just(true);
}
@ -498,7 +503,7 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
serverResponseStatus.set(401);
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.authorizationErrorHandler((responseInfo, context) -> Mono.just(false))
.authorizationErrorHandler((requestSnapshot, responseInfo, context) -> Mono.just(false))
.build();
StepVerifier.create(authTransport.sendMessage(createTestRequestMessage()))
@ -513,8 +518,8 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
void propagateHandlerError() {
serverResponseStatus.set(401);
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.authorizationErrorHandler(
(responseInfo, context) -> Mono.error(new IllegalStateException("handler error")))
.authorizationErrorHandler((requestUri, responseInfo, context) -> Mono
.error(new IllegalStateException("handler error")))
.build();
StepVerifier.create(authTransport.sendMessage(createTestRequestMessage()))
@ -529,7 +534,7 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
void emptyHandler() {
serverResponseStatus.set(401);
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.authorizationErrorHandler((responseInfo, context) -> Mono.empty())
.authorizationErrorHandler((requestSnapshot, responseInfo, context) -> Mono.empty())
.build();
StepVerifier.create(authTransport.sendMessage(createTestRequestMessage()))
@ -552,11 +557,13 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
AtomicReference<Throwable> capturedException = new AtomicReference<>();
AtomicReference<HttpResponse.ResponseInfo> capturedResponseInfo = new AtomicReference<>();
AtomicReference<HttpRequestSnapshot> capturedSnapshot = new AtomicReference<>();
AtomicReference<McpTransportContext> capturedContext = new AtomicReference<>();
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.authorizationErrorHandler((responseInfo, context) -> {
.authorizationErrorHandler((requestSnapshot, responseInfo, context) -> {
capturedResponseInfo.set(responseInfo);
capturedSnapshot.set(requestSnapshot);
capturedContext.set(context);
return Mono.just(false);
})
@ -572,6 +579,8 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
assertThat(messages).isEmpty();
assertThat(capturedResponseInfo.get()).isNotNull();
assertThat(capturedResponseInfo.get().statusCode()).isEqualTo(httpStatus);
assertThat(capturedSnapshot.get()).isNotNull();
assertThat(capturedSnapshot.get().requestUri().toString()).isEqualTo(HOST + "/mcp");
assertThat(capturedContext.get()).isNotNull();
assertThat(capturedException.get()).hasMessage("Authorization error connecting to SSE stream")
.asInstanceOf(type(McpHttpClientTransportAuthorizationException.class))
@ -606,7 +615,7 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
AtomicReference<Throwable> capturedException = new AtomicReference<>();
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.openConnectionOnStartup(true)
.authorizationErrorHandler((responseInfo, context) -> {
.authorizationErrorHandler((requestSnapshot, responseInfo, context) -> {
serverSseResponseStatus.set(200);
return Mono.just(true);
})
@ -636,7 +645,7 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
AtomicReference<Throwable> capturedException = new AtomicReference<>();
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.openConnectionOnStartup(true)
.authorizationErrorHandler((responseInfo, context) -> {
.authorizationErrorHandler((requestSnapshot, responseInfo, context) -> {
return Mono.just(true);
})
.build();
@ -661,10 +670,10 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
AtomicReference<Throwable> capturedException = new AtomicReference<>();
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.openConnectionOnStartup(true)
.authorizationErrorHandler(new McpHttpClientAuthorizationErrorHandler() {
.authorizationErrorHandler(new McpHttpClientTransportAuthorizationErrorHandler() {
@Override
public Publisher<Boolean> handle(HttpResponse.ResponseInfo responseInfo,
McpTransportContext context) {
public Publisher<Boolean> handle(HttpRequestSnapshot requestSnapshot,
HttpResponse.ResponseInfo responseInfo, McpTransportContext context) {
return Mono.just(true);
}
@ -695,7 +704,7 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
AtomicReference<Throwable> capturedException = new AtomicReference<>();
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.openConnectionOnStartup(true)
.authorizationErrorHandler((responseInfo, context) -> {
.authorizationErrorHandler((requestUri, responseInfo, context) -> {
// if there was a retry, the request would succeed.
serverSseResponseStatus.set(200);
return Mono.just(false);
@ -720,7 +729,7 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
AtomicReference<Throwable> capturedException = new AtomicReference<>();
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.openConnectionOnStartup(true)
.authorizationErrorHandler((responseInfo, context) -> Mono.empty())
.authorizationErrorHandler((requestUri, responseInfo, context) -> Mono.empty())
.build();
authTransport.setExceptionHandler(capturedException::set);
@ -741,8 +750,8 @@ public class HttpClientStreamableHttpTransportErrorHandlingTest {
AtomicReference<Throwable> capturedException = new AtomicReference<>();
var authTransport = HttpClientStreamableHttpTransport.builder(HOST)
.openConnectionOnStartup(true)
.authorizationErrorHandler(
(responseInfo, context) -> Mono.error(new IllegalStateException("handler error")))
.authorizationErrorHandler((requestUri, responseInfo, context) -> Mono
.error(new IllegalStateException("handler error")))
.build();
authTransport.setExceptionHandler(capturedException::set);