HTTP Service proxy sets body type

Closes gh-34793
This commit is contained in:
rstoyanchev
2025-04-25 14:31:37 +01:00
parent 190dabb8e1
commit c48ff357dc
8 changed files with 151 additions and 30 deletions

View File

@@ -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.
@@ -98,8 +98,8 @@ public final class WebClientAdapter extends AbstractReactorHttpExchangeAdapter {
return newRequest(requestValues).retrieve().toEntityFlux(bodyType);
}
@SuppressWarnings("ReactiveStreamsUnusedPublisher")
private WebClient.RequestBodySpec newRequest(HttpRequestValues values) {
@SuppressWarnings({"ReactiveStreamsUnusedPublisher", "unchecked"})
private <B> WebClient.RequestBodySpec newRequest(HttpRequestValues values) {
HttpMethod httpMethod = values.getHttpMethod();
Assert.notNull(httpMethod, "HttpMethod is required");
@@ -130,12 +130,18 @@ public final class WebClientAdapter extends AbstractReactorHttpExchangeAdapter {
bodySpec.attributes(attributes -> attributes.putAll(values.getAttributes()));
if (values.getBodyValue() != null) {
bodySpec.bodyValue(values.getBodyValue());
if (values.getBodyValueType() != null) {
B body = (B) values.getBodyValue();
bodySpec.bodyValue(body, (ParameterizedTypeReference<B>) values.getBodyValueType());
}
else {
bodySpec.bodyValue(values.getBodyValue());
}
}
else if (values instanceof ReactiveHttpRequestValues reactiveRequestValues) {
Publisher<?> body = reactiveRequestValues.getBodyPublisher();
else if (values instanceof ReactiveHttpRequestValues rhrv) {
Publisher<?> body = rhrv.getBodyPublisher();
if (body != null) {
ParameterizedTypeReference<?> elementType = reactiveRequestValues.getBodyPublisherElementType();
ParameterizedTypeReference<?> elementType = rhrv.getBodyPublisherElementType();
Assert.notNull(elementType, "Publisher body element type is required");
bodySpec.body(body, elementType);
}

View File

@@ -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.
@@ -21,7 +21,9 @@ import java.io.IOException;
import java.net.URI;
import java.time.Duration;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import okhttp3.mockwebserver.MockResponse;
@@ -39,6 +41,7 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
@@ -168,6 +171,22 @@ class WebClientAdapterTests {
"Content-Type: text/plain;charset=UTF-8", "Content-Length: 5", "test2");
}
@Test // gh-34793
void postSet() throws InterruptedException {
prepareResponse(response -> response.setResponseCode(201));
Set<Person> persons = new LinkedHashSet<>();
persons.add(new Person("John"));
persons.add(new Person("Richard"));
initService().postPersonSet(persons);
RecordedRequest request = server.takeRequest();
assertThat(request.getMethod()).isEqualTo("POST");
assertThat(request.getPath()).isEqualTo("/persons");
assertThat(request.getBody().readUtf8()).isEqualTo("[{\"name\":\"John\"},{\"name\":\"Richard\"}]");
}
@Test
void uriBuilderFactory() throws Exception {
String ignoredResponseBody = "hello";
@@ -251,6 +270,9 @@ class WebClientAdapterTests {
@PostExchange
void postMultipart(MultipartFile file, @RequestPart String anotherPart);
@PostExchange("/persons")
void postPersonSet(@RequestBody Set<Person> set);
@GetExchange("/greeting")
String getWithUriBuilderFactory(UriBuilderFactory uriBuilderFactory);
@@ -263,4 +285,19 @@ class WebClientAdapterTests {
}
static final class Person {
private final String name;
Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
}