mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-23 06:29:10 +00:00
Merge branch '6.2.x'
This commit is contained in:
@@ -108,7 +108,6 @@ public class ProblemDetail implements Serializable {
|
||||
* @param type the problem type
|
||||
*/
|
||||
public void setType(URI type) {
|
||||
Assert.notNull(type, "'type' is required");
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@@ -245,7 +244,7 @@ public class ProblemDetail implements Serializable {
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
return (this == other || (other instanceof ProblemDetail that &&
|
||||
getType().equals(that.getType()) &&
|
||||
ObjectUtils.nullSafeEquals(getType(), that.getType()) &&
|
||||
ObjectUtils.nullSafeEquals(getTitle(), that.getTitle()) &&
|
||||
this.status == that.status &&
|
||||
ObjectUtils.nullSafeEquals(this.detail, that.detail) &&
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Flow;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@@ -96,12 +97,13 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
|
||||
@Override
|
||||
protected ClientHttpResponse executeInternal(HttpHeaders headers, @Nullable Body body) throws IOException {
|
||||
CompletableFuture<HttpResponse<InputStream>> responseFuture = null;
|
||||
TimeoutHandler timeoutHandler = null;
|
||||
try {
|
||||
HttpRequest request = buildRequest(headers, body);
|
||||
responseFuture = this.httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream());
|
||||
|
||||
if (this.timeout != null) {
|
||||
TimeoutHandler timeoutHandler = new TimeoutHandler(responseFuture, this.timeout);
|
||||
timeoutHandler = new TimeoutHandler(responseFuture, this.timeout);
|
||||
HttpResponse<InputStream> response = responseFuture.get();
|
||||
InputStream inputStream = timeoutHandler.wrapInputStream(response);
|
||||
return new JdkClientHttpResponse(response, inputStream);
|
||||
@@ -119,8 +121,11 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
|
||||
catch (ExecutionException ex) {
|
||||
Throwable cause = ex.getCause();
|
||||
|
||||
if (cause instanceof CancellationException) {
|
||||
throw new HttpTimeoutException("Request timed out");
|
||||
if (cause instanceof CancellationException ce) {
|
||||
if (timeoutHandler != null) {
|
||||
timeoutHandler.handleCancellationException(ce);
|
||||
}
|
||||
throw new IOException("Request cancelled", cause);
|
||||
}
|
||||
if (cause instanceof UncheckedIOException uioEx) {
|
||||
throw uioEx.getCause();
|
||||
@@ -136,6 +141,12 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
|
||||
throw (message == null ? new IOException(cause) : new IOException(message, cause));
|
||||
}
|
||||
}
|
||||
catch (CancellationException ex) {
|
||||
if (timeoutHandler != null) {
|
||||
timeoutHandler.handleCancellationException(ex);
|
||||
}
|
||||
throw new IOException("Request cancelled", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private HttpRequest buildRequest(HttpHeaders headers, @Nullable Body body) {
|
||||
@@ -234,12 +245,15 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
|
||||
|
||||
private final CompletableFuture<Void> timeoutFuture;
|
||||
|
||||
private final AtomicBoolean timeout = new AtomicBoolean(false);
|
||||
|
||||
private TimeoutHandler(CompletableFuture<HttpResponse<InputStream>> future, Duration timeout) {
|
||||
|
||||
this.timeoutFuture = new CompletableFuture<Void>()
|
||||
.completeOnTimeout(null, timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||||
|
||||
this.timeoutFuture.thenRun(() -> {
|
||||
this.timeout.set(true);
|
||||
if (future.cancel(true) || future.isCompletedExceptionally() || !future.isDone()) {
|
||||
return;
|
||||
}
|
||||
@@ -250,7 +264,6 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public @Nullable InputStream wrapInputStream(HttpResponse<InputStream> response) {
|
||||
@@ -267,6 +280,12 @@ class JdkClientHttpRequest extends AbstractStreamingClientHttpRequest {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void handleCancellationException(CancellationException ex) throws HttpTimeoutException {
|
||||
if (this.timeout.get()) {
|
||||
throw new HttpTimeoutException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-3
@@ -105,16 +105,20 @@ public @interface RequestMapping {
|
||||
|
||||
/**
|
||||
* The path mapping URIs — for example, {@code "/profile"}.
|
||||
* <p>Ant-style path patterns are also supported (for example, {@code "/profile/**"}).
|
||||
* At the method level, relative paths (for example, {@code "edit"}) are supported
|
||||
* <p>Ant-style path patterns are also supported, e.g. {@code "/profile/**"}.
|
||||
* At the method level, relative paths, e.g., {@code "edit"} are supported
|
||||
* within the primary mapping expressed at the type level.
|
||||
* Path mapping URIs may contain placeholders (for example, <code>"/${profile_path}"</code>).
|
||||
* Path mapping URIs may contain property placeholders, e.g. <code>"/${profile_path}"</code>,
|
||||
* and SpEL expressions, e.g. {@code "/profile/#{@bean.property}"}.
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* When used at the type level, all method-level mappings inherit
|
||||
* this primary mapping, narrowing it for a specific handler method.
|
||||
* <p><strong>NOTE</strong>: A handler method that is not mapped to any path
|
||||
* explicitly is effectively mapped to an empty path.
|
||||
* @since 4.2
|
||||
* @see org.springframework.beans.factory.config.EmbeddedValueResolver
|
||||
* @see org.springframework.context.expression.StandardBeanExpressionResolver
|
||||
* @see org.springframework.context.support.AbstractApplicationContext
|
||||
*/
|
||||
@AliasFor("value")
|
||||
String[] path() default {};
|
||||
|
||||
Reference in New Issue
Block a user