Skip to content

Commit ddf996c

Browse files
committed
Polish HttpRequestBuilder API
This commit makes messageEncoders a required argument for building a client request - those are needed to actually encode the body object as a reactive stream to be written to the HTTP request body. Removed raw types usage in DefaultHttpRequestBuilder. DefaultHttpRequestBuilder now uses a UriTemplateHandler to expand URI templates + variables into a concrete URI. Fixes spring-projects#80, fixes spring-projects#85, fixes spring-projects#86
1 parent 8ed2925 commit ddf996c

File tree

3 files changed

+20
-37
lines changed

3 files changed

+20
-37
lines changed

spring-web-reactive/src/main/java/org/springframework/web/client/reactive/DefaultHttpRequestBuilder.java

+11-31
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919

2020
import java.net.URI;
21-
import java.net.URISyntaxException;
2221
import java.util.ArrayList;
2322
import java.util.Arrays;
2423
import java.util.List;
@@ -40,6 +39,8 @@
4039
import org.springframework.http.client.reactive.ClientHttpRequestFactory;
4140
import org.springframework.util.Assert;
4241
import org.springframework.web.client.RestClientException;
42+
import org.springframework.web.util.DefaultUriTemplateHandler;
43+
import org.springframework.web.util.UriTemplateHandler;
4344

4445
/**
4546
* Builds a {@link ClientHttpRequest}
@@ -51,6 +52,8 @@
5152
*/
5253
public class DefaultHttpRequestBuilder implements HttpRequestBuilder {
5354

55+
private final UriTemplateHandler uriTemplateHandler = new DefaultUriTemplateHandler();
56+
5457
protected HttpMethod httpMethod;
5558

5659
protected HttpHeaders httpHeaders;
@@ -59,8 +62,6 @@ public class DefaultHttpRequestBuilder implements HttpRequestBuilder {
5962

6063
protected Publisher contentPublisher;
6164

62-
protected List<Encoder<?>> messageEncoders;
63-
6465
protected final List<HttpCookie> cookies = new ArrayList<HttpCookie>();
6566

6667
protected DefaultHttpRequestBuilder() {
@@ -69,7 +70,7 @@ protected DefaultHttpRequestBuilder() {
6970
public DefaultHttpRequestBuilder(HttpMethod httpMethod, String urlTemplate, Object... urlVariables) throws RestClientException {
7071
this.httpMethod = httpMethod;
7172
this.httpHeaders = new HttpHeaders();
72-
this.url = parseURI(urlTemplate);
73+
this.url = this.uriTemplateHandler.expand(urlTemplate, urlVariables);
7374
}
7475

7576
public DefaultHttpRequestBuilder(HttpMethod httpMethod, URI url) {
@@ -78,24 +79,6 @@ public DefaultHttpRequestBuilder(HttpMethod httpMethod, URI url) {
7879
this.url = url;
7980
}
8081

81-
protected DefaultHttpRequestBuilder setMessageEncoders(List<Encoder<?>> messageEncoders) {
82-
this.messageEncoders = messageEncoders;
83-
return this;
84-
}
85-
86-
private URI parseURI(String uri) throws RestClientException {
87-
try {
88-
return new URI(uri);
89-
}
90-
catch (URISyntaxException e) {
91-
throw new RestClientException("could not parse URL template", e);
92-
}
93-
}
94-
95-
public DefaultHttpRequestBuilder param(String name, String... values) {
96-
return this;
97-
}
98-
9982
public DefaultHttpRequestBuilder header(String name, String... values) {
10083
Arrays.stream(values).forEach(value -> this.httpHeaders.add(name, value));
10184
return this;
@@ -133,7 +116,7 @@ public DefaultHttpRequestBuilder content(Object content) {
133116
return this;
134117
}
135118

136-
public DefaultHttpRequestBuilder contentStream(Publisher content) {
119+
public DefaultHttpRequestBuilder contentStream(Publisher<?> content) {
137120
this.contentPublisher = Flux.from(content);
138121
return this;
139122
}
@@ -153,15 +136,18 @@ public DefaultHttpRequestBuilder apply(RequestPostProcessor postProcessor) {
153136
return this;
154137
}
155138

156-
public ClientHttpRequest build(ClientHttpRequestFactory factory) {
139+
public ClientHttpRequest build(ClientHttpRequestFactory factory, List<Encoder<?>> messageEncoders) {
157140
ClientHttpRequest request = factory.createRequest(this.httpMethod, this.url, this.httpHeaders);
158141
request.getHeaders().putAll(this.httpHeaders);
159142

160143
if (this.contentPublisher != null) {
161144
ResolvableType requestBodyType = ResolvableType.forInstance(this.contentPublisher);
162145
MediaType mediaType = request.getHeaders().getContentType();
163146

164-
Optional<Encoder<?>> messageEncoder = resolveEncoder(requestBodyType, mediaType);
147+
Optional<Encoder<?>> messageEncoder = messageEncoders
148+
.stream()
149+
.filter(e -> e.canEncode(requestBodyType, mediaType))
150+
.findFirst();
165151

166152
if (messageEncoder.isPresent()) {
167153
DataBufferAllocator allocator = request.allocator();
@@ -175,13 +161,7 @@ public ClientHttpRequest build(ClientHttpRequestFactory factory) {
175161
"' for content-type '" + mediaType.toString() + "'");
176162
}
177163
}
178-
179164
return request;
180165
}
181166

182-
protected Optional<Encoder<?>> resolveEncoder(ResolvableType type, MediaType mediaType) {
183-
return this.messageEncoders.stream()
184-
.filter(e -> e.canEncode(type, mediaType)).findFirst();
185-
}
186-
187167
}

spring-web-reactive/src/main/java/org/springframework/web/client/reactive/HttpRequestBuilder.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
package org.springframework.web.client.reactive;
1818

19+
import java.util.List;
20+
21+
import org.springframework.core.codec.Encoder;
1922
import org.springframework.http.client.reactive.ClientHttpRequest;
2023
import org.springframework.http.client.reactive.ClientHttpRequestFactory;
2124

@@ -29,6 +32,9 @@ public interface HttpRequestBuilder {
2932

3033
/**
3134
* Build a {@link ClientHttpRequest}
35+
*
36+
* @param factory the factory that creates the actual {@link ClientHttpRequest}
37+
* @param messageEncoders the {@link Encoder}s to use for encoding the request body
3238
*/
33-
ClientHttpRequest build(ClientHttpRequestFactory factory);
39+
ClientHttpRequest build(ClientHttpRequestFactory factory, List<Encoder<?>> messageEncoders);
3440
}

spring-web-reactive/src/main/java/org/springframework/web/client/reactive/WebClient.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
import org.springframework.core.codec.support.JsonObjectDecoder;
3232
import org.springframework.core.codec.support.StringDecoder;
3333
import org.springframework.core.codec.support.StringEncoder;
34-
import org.springframework.core.io.buffer.DataBufferAllocator;
35-
import org.springframework.core.io.buffer.DefaultDataBufferAllocator;
3634
import org.springframework.http.HttpStatus;
3735
import org.springframework.http.client.reactive.ClientHttpRequest;
3836
import org.springframework.http.client.reactive.ClientHttpRequestFactory;
@@ -85,7 +83,6 @@ public final class WebClient {
8583
*/
8684
public WebClient(ClientHttpRequestFactory requestFactory) {
8785
this.requestFactory = requestFactory;
88-
DataBufferAllocator allocator = new DefaultDataBufferAllocator();
8986
this.messageEncoders = Arrays.asList(new ByteBufferEncoder(), new StringEncoder(),
9087
new JacksonJsonEncoder());
9188
this.messageDecoders = Arrays.asList(new ByteBufferDecoder(), new StringDecoder(),
@@ -116,9 +113,9 @@ public void setMessageDecoders(List<Decoder<?>> messageDecoders) {
116113
* <li>returning the response with a publisher of the body</li>
117114
* </ul>
118115
*/
119-
public WebResponseActions perform(DefaultHttpRequestBuilder builder) {
116+
public WebResponseActions perform(HttpRequestBuilder builder) {
120117

121-
ClientHttpRequest request = builder.setMessageEncoders(messageEncoders).build(requestFactory);
118+
ClientHttpRequest request = builder.build(this.requestFactory, this.messageEncoders);
122119
final Mono<ClientHttpResponse> clientResponse = request.execute()
123120
.log("org.springframework.http.client.reactive");
124121

0 commit comments

Comments
 (0)