Skip to content

Commit 45770d7

Browse files
committed
Remove parameterisation from ClientRequest
This commit removes the parameterisation from ClientRequest, similarly to ServerResponse. Dropping the parameterisation facilitates a ClientRequest.from method that also copies the body of the target request. SPR-15234 Work in Progress
1 parent d513fe8 commit 45770d7

File tree

12 files changed

+73
-67
lines changed

12 files changed

+73
-67
lines changed

spring-test/src/test/java/org/springframework/test/web/reactive/server/WiretapConnectorTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
package org.springframework.test.web.reactive.server;
1718

1819
import java.net.URI;
@@ -54,7 +55,7 @@ public void listener() throws Exception {
5455
wiretapConnector.addListener(infoRef::set);
5556

5657
ExchangeFunction exchangeFn = ExchangeFunctions.create(wiretapConnector);
57-
ClientRequest<Void> clientRequest = ClientRequest.method(HttpMethod.GET, URI.create("/test")).build();
58+
ClientRequest clientRequest = ClientRequest.method(HttpMethod.GET, URI.create("/test")).build();
5859
exchangeFn.exchange(clientRequest).blockMillis(0);
5960

6061
WiretapConnector.Info info = infoRef.get();

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,11 @@
3636
* <p>Note that applications are more likely to perform requests through
3737
* {@link WebClient} rather than using this directly.
3838
*
39-
* @param <T> the type of the body that this request contains
4039
* @author Brian Clozel
4140
* @author Arjen Poutsma
4241
* @since 5.0
4342
*/
44-
public interface ClientRequest<T> {
43+
public interface ClientRequest {
4544

4645
/**
4746
* Return the HTTP method.
@@ -66,7 +65,7 @@ public interface ClientRequest<T> {
6665
/**
6766
* Return the body inserter of this request.
6867
*/
69-
BodyInserter<T, ? super ClientHttpRequest> inserter();
68+
BodyInserter<?, ? super ClientHttpRequest> body();
7069

7170
/**
7271
* Writes this request to the given {@link ClientHttpRequest}.
@@ -86,11 +85,12 @@ public interface ClientRequest<T> {
8685
* @param other the request to copy the method, URI, headers, and cookies from
8786
* @return the created builder
8887
*/
89-
static Builder from(ClientRequest<?> other) {
88+
static Builder from(ClientRequest other) {
9089
Assert.notNull(other, "'other' must not be null");
9190
return new DefaultClientRequestBuilder(other.method(), other.url())
9291
.headers(other.headers())
93-
.cookies(other.cookies());
92+
.cookies(other.cookies())
93+
.body(other.body());
9494
}
9595

9696
/**
@@ -143,28 +143,27 @@ interface Builder {
143143
Builder cookies(MultiValueMap<String, String> cookies);
144144

145145
/**
146-
* Builds the request entity with no body.
147-
* @return the request entity
148-
*/
149-
ClientRequest<Void> build();
150-
151-
/**
152-
* Set the body of the request to the given {@code BodyInserter} and return it.
146+
* Set the body of the request to the given {@code BodyInserter}.
153147
* @param inserter the {@code BodyInserter} that writes to the request
154-
* @param <T> the type contained in the body
155-
* @return the built request
148+
* @return this builder
156149
*/
157-
<T> ClientRequest<T> body(BodyInserter<T, ? super ClientHttpRequest> inserter);
150+
Builder body(BodyInserter<?, ? super ClientHttpRequest> inserter);
158151

159152
/**
160153
* Set the body of the request to the given {@code Publisher} and return it.
161154
* @param publisher the {@code Publisher} to write to the request
162155
* @param elementClass the class of elements contained in the publisher
163-
* @param <T> the type of the elements contained in the publisher
164-
* @param <S> the type of the {@code Publisher}
156+
* @param <S> the type of the elements contained in the publisher
157+
* @param <P> the type of the {@code Publisher}
165158
* @return the built request
166159
*/
167-
<T, S extends Publisher<T>> ClientRequest<S> body(S publisher, Class<T> elementClass);
160+
<S, P extends Publisher<S>> Builder body(P publisher, Class<S> elementClass);
161+
162+
/**
163+
* Builds the request entity with no body.
164+
* @return the request entity
165+
*/
166+
ClientRequest build();
168167

169168
}
170169

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class DefaultClientRequestBuilder implements ClientRequest.Builder {
5353

5454
private final MultiValueMap<String, String> cookies = new LinkedMultiValueMap<>();
5555

56+
private BodyInserter<?, ? super ClientHttpRequest> inserter = BodyInserters.empty();
57+
5658

5759
public DefaultClientRequestBuilder(HttpMethod method, URI url) {
5860
this.method = method;
@@ -90,23 +92,28 @@ public ClientRequest.Builder cookies(MultiValueMap<String, String> cookies) {
9092
}
9193

9294
@Override
93-
public ClientRequest<Void> build() {
94-
return body(BodyInserters.empty());
95+
public <S, P extends Publisher<S>> ClientRequest.Builder body(P publisher,
96+
Class<S> elementClass) {
97+
Assert.notNull(publisher, "'publisher' must not be null");
98+
Assert.notNull(elementClass, "'elementClass' must not be null");
99+
100+
this.inserter = BodyInserters.fromPublisher(publisher, elementClass);
101+
return this;
95102
}
96103

97104
@Override
98-
public <T> ClientRequest<T> body(BodyInserter<T, ? super ClientHttpRequest> inserter) {
99-
Assert.notNull(inserter, "'inserter' must not be null");
100-
return new BodyInserterRequest<T>(this.method, this.url, this.headers, this.cookies,
101-
inserter);
105+
public ClientRequest.Builder body(BodyInserter<?, ? super ClientHttpRequest> inserter) {
106+
this.inserter = inserter != null ? inserter : BodyInserters.empty();
107+
return this;
102108
}
103109

104110
@Override
105-
public <T, S extends Publisher<T>> ClientRequest<S> body(S publisher, Class<T> elementClass) {
106-
return body(BodyInserters.fromPublisher(publisher, elementClass));
111+
public ClientRequest build() {
112+
return new BodyInserterRequest(this.method, this.url, this.headers, this.cookies,
113+
this.inserter);
107114
}
108115

109-
private static class BodyInserterRequest<T> implements ClientRequest<T> {
116+
private static class BodyInserterRequest implements ClientRequest {
110117

111118
private final HttpMethod method;
112119

@@ -116,11 +123,11 @@ private static class BodyInserterRequest<T> implements ClientRequest<T> {
116123

117124
private final MultiValueMap<String, String> cookies;
118125

119-
private final BodyInserter<T, ? super ClientHttpRequest> inserter;
126+
private final BodyInserter<?, ? super ClientHttpRequest> inserter;
120127

121128
public BodyInserterRequest(HttpMethod method, URI url, HttpHeaders headers,
122129
MultiValueMap<String, String> cookies,
123-
BodyInserter<T, ? super ClientHttpRequest> inserter) {
130+
BodyInserter<?, ? super ClientHttpRequest> inserter) {
124131
this.method = method;
125132
this.url = url;
126133
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
@@ -149,7 +156,7 @@ public MultiValueMap<String, String> cookies() {
149156
}
150157

151158
@Override
152-
public BodyInserter<T, ? super ClientHttpRequest> inserter() {
159+
public BodyInserter<?, ? super ClientHttpRequest> body() {
153160
return this.inserter;
154161
}
155162

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,19 +262,19 @@ public DefaultHeaderSpec ifNoneMatch(String... ifNoneMatches) {
262262

263263
@Override
264264
public Mono<ClientResponse> exchange() {
265-
ClientRequest<Void> request = initRequestBuilder().build();
265+
ClientRequest request = this.initRequestBuilder().build();
266266
return getExchangeFunction().exchange(request);
267267
}
268268

269269
@Override
270270
public <T> Mono<ClientResponse> exchange(BodyInserter<T, ? super ClientHttpRequest> inserter) {
271-
ClientRequest<T> request = initRequestBuilder().body(inserter);
271+
ClientRequest request = this.initRequestBuilder().body(inserter).build();
272272
return getExchangeFunction().exchange(request);
273273
}
274274

275275
@Override
276276
public <T, S extends Publisher<T>> Mono<ClientResponse> exchange(S publisher, Class<T> elementClass) {
277-
ClientRequest<S> request = initRequestBuilder().headers(this.headers).body(publisher, elementClass);
277+
ClientRequest request = initRequestBuilder().headers(this.headers).body(publisher, elementClass).build();
278278
return getExchangeFunction().exchange(request);
279279
}
280280

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunction.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ public interface ExchangeFilterFunction {
4141
* @param next the next exchange function in the chain
4242
* @return the filtered response
4343
*/
44-
Mono<ClientResponse> filter(ClientRequest<?> request, ExchangeFunction next);
44+
Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next);
4545

4646
/**
4747
* Return a composed filter function that first applies this filter, and then applies the
@@ -74,8 +74,8 @@ default ExchangeFunction apply(ExchangeFunction exchange) {
7474
* @param requestProcessor the request processor
7575
* @return the filter adaptation of the request processor
7676
*/
77-
static ExchangeFilterFunction ofRequestProcessor(Function<ClientRequest<?>,
78-
Mono<ClientRequest<?>>> requestProcessor) {
77+
static ExchangeFilterFunction ofRequestProcessor(Function<ClientRequest,
78+
Mono<ClientRequest>> requestProcessor) {
7979

8080
Assert.notNull(requestProcessor, "'requestProcessor' must not be null");
8181
return (request, next) -> requestProcessor.apply(request).then(next::exchange);

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctions.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -47,9 +47,9 @@ public static ExchangeFilterFunction basicAuthentication(String username, String
4747
return ExchangeFilterFunction.ofRequestProcessor(
4848
clientRequest -> {
4949
String authorization = authorization(username, password);
50-
ClientRequest<?> authorizedRequest = ClientRequest.from(clientRequest)
50+
ClientRequest authorizedRequest = ClientRequest.from(clientRequest)
5151
.header(HttpHeaders.AUTHORIZATION, authorization)
52-
.body(clientRequest.inserter());
52+
.build();
5353
return Mono.just(authorizedRequest);
5454
});
5555
}

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public interface ExchangeFunction {
4545
* @param request the request to exchange
4646
* @return the delayed response
4747
*/
48-
Mono<ClientResponse> exchange(ClientRequest<?> request);
48+
Mono<ClientResponse> exchange(ClientRequest request);
4949

5050
/**
5151
* Filters this exchange function with the given {@code ExchangeFilterFunction}, resulting in a

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public DefaultExchangeFunction(
7272
}
7373

7474
@Override
75-
public Mono<ClientResponse> exchange(ClientRequest<?> request) {
75+
public Mono<ClientResponse> exchange(ClientRequest request) {
7676
Assert.notNull(request, "'request' must not be null");
7777

7878
return this.connector

spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import static java.nio.charset.StandardCharsets.UTF_8;
3838
import static org.junit.Assert.assertEquals;
3939
import static org.junit.Assert.assertNotNull;
40-
import static org.junit.Assert.assertNull;
4140
import static org.mockito.Mockito.mock;
4241
import static org.mockito.Mockito.when;
4342
import static org.springframework.http.HttpMethod.DELETE;
@@ -51,10 +50,10 @@ public class DefaultClientRequestBuilderTests {
5150

5251
@Test
5352
public void from() throws Exception {
54-
ClientRequest<Void> other = ClientRequest.method(GET, URI.create("http://example.com"))
53+
ClientRequest other = ClientRequest.method(GET, URI.create("http://example.com"))
5554
.header("foo", "bar")
5655
.cookie("baz", "qux").build();
57-
ClientRequest<Void> result = ClientRequest.from(other).build();
56+
ClientRequest result = ClientRequest.from(other).build();
5857
assertEquals(new URI("http://example.com"), result.url());
5958
assertEquals(GET, result.method());
6059
assertEquals("bar", result.headers().getFirst("foo"));
@@ -64,21 +63,21 @@ public void from() throws Exception {
6463
@Test
6564
public void method() throws Exception {
6665
URI url = new URI("http://example.com");
67-
ClientRequest<Void> result = ClientRequest.method(DELETE, url).build();
66+
ClientRequest result = ClientRequest.method(DELETE, url).build();
6867
assertEquals(url, result.url());
6968
assertEquals(DELETE, result.method());
7069
}
7170

7271
@Test
7372
public void cookie() throws Exception {
74-
ClientRequest<Void> result = ClientRequest.method(GET, URI.create("http://example.com"))
73+
ClientRequest result = ClientRequest.method(GET, URI.create("http://example.com"))
7574
.cookie("foo", "bar").build();
7675
assertEquals("bar", result.cookies().getFirst("foo"));
7776
}
7877

7978
@Test
8079
public void build() throws Exception {
81-
ClientRequest<Void> result = ClientRequest.method(GET, URI.create("http://example.com"))
80+
ClientRequest result = ClientRequest.method(GET, URI.create("http://example.com"))
8281
.header("MyKey", "MyValue")
8382
.cookie("foo", "bar")
8483
.build();
@@ -105,8 +104,8 @@ public void bodyInserter() throws Exception {
105104
return response.writeWith(Mono.just(buffer));
106105
};
107106

108-
ClientRequest<String> result = ClientRequest.method(POST, URI.create("http://example.com"))
109-
.body(inserter);
107+
ClientRequest result = ClientRequest.method(POST, URI.create("http://example.com"))
108+
.body(inserter).build();
110109

111110
List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
112111
messageWriters.add(new EncoderHttpMessageWriter<>(new CharSequenceEncoder()));

spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultWebClientTests.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
package org.springframework.web.reactive.function.client;
1718

1819
import java.util.Collections;
@@ -42,7 +43,7 @@ public class DefaultWebClientTests {
4243
private ExchangeFunction exchangeFunction;
4344

4445
@Captor
45-
private ArgumentCaptor<ClientRequest<?>> captor;
46+
private ArgumentCaptor<ClientRequest> captor;
4647

4748

4849
@Before
@@ -58,7 +59,7 @@ public void basic() throws Exception {
5859
WebClient client = builder().build();
5960
client.get().uri("/path").exchange();
6061

61-
ClientRequest<?> request = verifyExchange();
62+
ClientRequest request = verifyExchange();
6263
assertEquals("/base/path", request.url().toString());
6364
assertEquals(new HttpHeaders(), request.headers());
6465
assertEquals(Collections.emptyMap(), request.cookies());
@@ -69,7 +70,7 @@ public void uriBuilder() throws Exception {
6970
WebClient client = builder().build();
7071
client.get().uri(builder -> builder.path("/path").queryParam("q", "12").build()).exchange();
7172

72-
ClientRequest<?> request = verifyExchange();
73+
ClientRequest request = verifyExchange();
7374
assertEquals("/base/path?q=12", request.url().toString());
7475
verifyNoMoreInteractions(this.exchangeFunction);
7576
}
@@ -79,7 +80,7 @@ public void uriBuilderWithPathOverride() throws Exception {
7980
WebClient client = builder().build();
8081
client.get().uri(builder -> builder.replacePath("/path").build()).exchange();
8182

82-
ClientRequest<?> request = verifyExchange();
83+
ClientRequest request = verifyExchange();
8384
assertEquals("/path", request.url().toString());
8485
verifyNoMoreInteractions(this.exchangeFunction);
8586
}
@@ -89,7 +90,7 @@ public void requestHeaderAndCookie() throws Exception {
8990
WebClient client = builder().build();
9091
client.get().uri("/path").accept(MediaType.APPLICATION_JSON).cookie("id", "123").exchange();
9192

92-
ClientRequest<?> request = verifyExchange();
93+
ClientRequest request = verifyExchange();
9394
assertEquals("application/json", request.headers().getFirst("Accept"));
9495
assertEquals("123", request.cookies().getFirst("id"));
9596
verifyNoMoreInteractions(this.exchangeFunction);
@@ -100,7 +101,7 @@ public void defaultHeaderAndCookie() throws Exception {
100101
WebClient client = builder().defaultHeader("Accept", "application/json").defaultCookie("id", "123").build();
101102
client.get().uri("/path").exchange();
102103

103-
ClientRequest<?> request = verifyExchange();
104+
ClientRequest request = verifyExchange();
104105
assertEquals("application/json", request.headers().getFirst("Accept"));
105106
assertEquals("123", request.cookies().getFirst("id"));
106107
verifyNoMoreInteractions(this.exchangeFunction);
@@ -111,7 +112,7 @@ public void defaultHeaderAndCookieOverrides() throws Exception {
111112
WebClient client = builder().defaultHeader("Accept", "application/json").defaultCookie("id", "123").build();
112113
client.get().uri("/path").header("Accept", "application/xml").cookie("id", "456").exchange();
113114

114-
ClientRequest<?> request = verifyExchange();
115+
ClientRequest request = verifyExchange();
115116
assertEquals("application/xml", request.headers().getFirst("Accept"));
116117
assertEquals("456", request.cookies().getFirst("id"));
117118
verifyNoMoreInteractions(this.exchangeFunction);
@@ -122,8 +123,8 @@ private WebClient.Builder builder() {
122123
return WebClient.builder().baseUrl("/base").exchangeFunction(this.exchangeFunction);
123124
}
124125

125-
private ClientRequest<?> verifyExchange() {
126-
ClientRequest<?> request = this.captor.getValue();
126+
private ClientRequest verifyExchange() {
127+
ClientRequest request = this.captor.getValue();
127128
Mockito.verify(this.exchangeFunction).exchange(request);
128129
verifyNoMoreInteractions(this.exchangeFunction);
129130
return request;

0 commit comments

Comments
 (0)