Add chaining methods to ClientHttpRequestInterceptor
See gh-34169
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.http.client;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Contract to intercept client-side HTTP requests. Implementations can be
|
||||
@@ -60,4 +61,32 @@ public interface ClientHttpRequestInterceptor {
|
||||
ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Return a new interceptor that invokes {@code this} interceptor first, and
|
||||
* then the one that's passed in.
|
||||
* @param interceptor the next interceptor
|
||||
* @return a new interceptor that chains the two
|
||||
* @since 7.0
|
||||
*/
|
||||
default ClientHttpRequestInterceptor andThen(ClientHttpRequestInterceptor interceptor) {
|
||||
Assert.notNull(interceptor, "ClientHttpRequestInterceptor must not be null");
|
||||
return (request, body, execution) -> {
|
||||
ClientHttpRequestExecution nextExecution =
|
||||
(nextRequest, nextBody) -> interceptor.intercept(nextRequest, nextBody, execution);
|
||||
return intercept(request, body, nextExecution);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new execution that invokes {@code this} interceptor, and then
|
||||
* delegates to the given execution.
|
||||
* @param execution the execution to delegate to
|
||||
* @return a new execution instance
|
||||
* @since 7.0
|
||||
*/
|
||||
default ClientHttpRequestExecution apply(ClientHttpRequestExecution execution) {
|
||||
Assert.notNull(execution, "ClientHttpRequestExecution must not be null");
|
||||
return (request, body) -> intercept(request, body, execution);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -69,39 +68,23 @@ class InterceptingClientHttpRequest extends AbstractBufferingClientHttpRequest {
|
||||
|
||||
@Override
|
||||
protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
|
||||
ClientHttpRequestExecution requestExecution = new DelegatingRequestExecution(this.requestFactory);
|
||||
ListIterator<ClientHttpRequestInterceptor> iterator = this.interceptors.listIterator(this.interceptors.size());
|
||||
while (iterator.hasPrevious()) {
|
||||
ClientHttpRequestInterceptor interceptor = iterator.previous();
|
||||
requestExecution = new InterceptingRequestExecution(interceptor, requestExecution);
|
||||
}
|
||||
return requestExecution.execute(this, bufferedOutput);
|
||||
return getExecution().execute(this, bufferedOutput);
|
||||
}
|
||||
|
||||
private ClientHttpRequestExecution getExecution() {
|
||||
ClientHttpRequestExecution execution = new EndOfChainRequestExecution(this.requestFactory);
|
||||
return this.interceptors.stream()
|
||||
.reduce(ClientHttpRequestInterceptor::andThen)
|
||||
.map(interceptor -> interceptor.apply(execution))
|
||||
.orElse(execution);
|
||||
}
|
||||
|
||||
|
||||
private static class InterceptingRequestExecution implements ClientHttpRequestExecution {
|
||||
|
||||
private final ClientHttpRequestInterceptor interceptor;
|
||||
|
||||
private final ClientHttpRequestExecution nextExecution;
|
||||
|
||||
public InterceptingRequestExecution(ClientHttpRequestInterceptor interceptor, ClientHttpRequestExecution nextExecution) {
|
||||
this.interceptor = interceptor;
|
||||
this.nextExecution = nextExecution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
|
||||
return this.interceptor.intercept(request, body, this.nextExecution);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DelegatingRequestExecution implements ClientHttpRequestExecution {
|
||||
private static class EndOfChainRequestExecution implements ClientHttpRequestExecution {
|
||||
|
||||
private final ClientHttpRequestFactory requestFactory;
|
||||
|
||||
public DelegatingRequestExecution(ClientHttpRequestFactory requestFactory) {
|
||||
public EndOfChainRequestExecution(ClientHttpRequestFactory requestFactory) {
|
||||
this.requestFactory = requestFactory;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user