HTTP Service proxy sets body type
Closes gh-34793
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.
|
||||
@@ -85,7 +85,8 @@ public final class RestClientAdapter implements HttpExchangeAdapter {
|
||||
return newRequest(values).retrieve().toEntity(bodyType);
|
||||
}
|
||||
|
||||
private RestClient.RequestBodySpec newRequest(HttpRequestValues values) {
|
||||
@SuppressWarnings("unchecked")
|
||||
private <B> RestClient.RequestBodySpec newRequest(HttpRequestValues values) {
|
||||
|
||||
HttpMethod httpMethod = values.getHttpMethod();
|
||||
Assert.notNull(httpMethod, "HttpMethod is required");
|
||||
@@ -123,8 +124,14 @@ public final class RestClientAdapter implements HttpExchangeAdapter {
|
||||
|
||||
bodySpec.attributes(attributes -> attributes.putAll(values.getAttributes()));
|
||||
|
||||
if (values.getBodyValue() != null) {
|
||||
bodySpec.body(values.getBodyValue());
|
||||
B body = (B) values.getBodyValue();
|
||||
if (body != null) {
|
||||
if (values.getBodyValueType() != null) {
|
||||
bodySpec.body(body, (ParameterizedTypeReference<? super B>) values.getBodyValueType());
|
||||
}
|
||||
else {
|
||||
bodySpec.body(body);
|
||||
}
|
||||
}
|
||||
|
||||
return bodySpec;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 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.
|
||||
@@ -86,7 +86,7 @@ public final class RestTemplateAdapter implements HttpExchangeAdapter {
|
||||
return this.restTemplate.exchange(newRequest(values), bodyType);
|
||||
}
|
||||
|
||||
private RequestEntity<?> newRequest(HttpRequestValues values) {
|
||||
private <B> RequestEntity<?> newRequest(HttpRequestValues values) {
|
||||
HttpMethod httpMethod = values.getHttpMethod();
|
||||
Assert.notNull(httpMethod, "HttpMethod is required");
|
||||
|
||||
@@ -120,11 +120,16 @@ public final class RestTemplateAdapter implements HttpExchangeAdapter {
|
||||
builder.header(HttpHeaders.COOKIE, String.join("; ", cookies));
|
||||
}
|
||||
|
||||
if (values.getBodyValue() != null) {
|
||||
return builder.body(values.getBodyValue());
|
||||
Object body = values.getBodyValue();
|
||||
if (body == null) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
if (values.getBodyValueType() != null) {
|
||||
return builder.body(body, values.getBodyValueType().getType());
|
||||
}
|
||||
|
||||
return builder.body(body);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -75,6 +76,9 @@ public class HttpRequestValues {
|
||||
@Nullable
|
||||
private final Object bodyValue;
|
||||
|
||||
@Nullable
|
||||
private ParameterizedTypeReference<?> bodyValueType;
|
||||
|
||||
|
||||
/**
|
||||
* Construct {@link HttpRequestValues}.
|
||||
@@ -177,6 +181,15 @@ public class HttpRequestValues {
|
||||
return this.bodyValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type for the {@linkplain #getBodyValue() body value}.
|
||||
* @since 6.2.7
|
||||
*/
|
||||
@Nullable
|
||||
public ParameterizedTypeReference<?> getBodyValueType() {
|
||||
return this.bodyValueType;
|
||||
}
|
||||
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
@@ -253,6 +266,9 @@ public class HttpRequestValues {
|
||||
@Nullable
|
||||
private Object bodyValue;
|
||||
|
||||
@Nullable
|
||||
private ParameterizedTypeReference<?> bodyValueType;
|
||||
|
||||
/**
|
||||
* Set the HTTP method for the request.
|
||||
*/
|
||||
@@ -389,6 +405,15 @@ public class HttpRequestValues {
|
||||
this.bodyValue = bodyValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #setBodyValue(Object)} with the body type.
|
||||
* @since 6.2.7
|
||||
*/
|
||||
public void setBodyValue(@Nullable Object bodyValue, @Nullable ParameterizedTypeReference<?> valueType) {
|
||||
setBodyValue(bodyValue);
|
||||
this.bodyValueType = valueType;
|
||||
}
|
||||
|
||||
|
||||
// Implementation of {@link Metadata} methods
|
||||
|
||||
@@ -465,9 +490,14 @@ public class HttpRequestValues {
|
||||
Map<String, Object> attributes = (this.attributes != null ?
|
||||
new HashMap<>(this.attributes) : Collections.emptyMap());
|
||||
|
||||
return createRequestValues(
|
||||
HttpRequestValues requestValues = createRequestValues(
|
||||
this.httpMethod, uri, uriBuilderFactory, uriTemplate, uriVars,
|
||||
headers, cookies, attributes, bodyValue);
|
||||
|
||||
// In 6.2.x only, temporarily work around protected methods
|
||||
requestValues.bodyValueType = this.bodyValueType;
|
||||
|
||||
return requestValues;
|
||||
}
|
||||
|
||||
protected boolean hasParts() {
|
||||
|
||||
@@ -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.
|
||||
@@ -83,15 +83,16 @@ public class RequestBodyArgumentResolver implements HttpServiceArgumentResolver
|
||||
if (this.reactiveAdapterRegistry != null) {
|
||||
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(parameter.getParameterType());
|
||||
if (adapter != null) {
|
||||
MethodParameter nestedParameter = parameter.nested();
|
||||
MethodParameter nestedParam = parameter.nested();
|
||||
|
||||
String message = "Async type for @RequestBody should produce value(s)";
|
||||
Assert.isTrue(!adapter.isNoValue(), message);
|
||||
Assert.isTrue(nestedParameter.getNestedParameterType() != Void.class, message);
|
||||
Assert.isTrue(nestedParam.getNestedParameterType() != Void.class, message);
|
||||
|
||||
if (requestValues instanceof ReactiveHttpRequestValues.Builder reactiveRequestValues) {
|
||||
reactiveRequestValues.setBodyPublisher(
|
||||
adapter.toPublisher(argument), asParameterizedTypeRef(nestedParameter));
|
||||
if (requestValues instanceof ReactiveHttpRequestValues.Builder rrv) {
|
||||
rrv.setBodyPublisher(
|
||||
adapter.toPublisher(argument),
|
||||
ParameterizedTypeReference.forType(nestedParam.getNestedGenericParameterType()));
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(
|
||||
@@ -103,12 +104,8 @@ public class RequestBodyArgumentResolver implements HttpServiceArgumentResolver
|
||||
}
|
||||
|
||||
// Not a reactive type
|
||||
requestValues.setBodyValue(argument);
|
||||
requestValues.setBodyValue(argument, ParameterizedTypeReference.forType(parameter.getGenericParameterType()));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static ParameterizedTypeReference<Object> asParameterizedTypeRef(MethodParameter nestedParam) {
|
||||
return ParameterizedTypeReference.forType(nestedParam.getNestedGenericParameterType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user