diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java
index b0dd1186170..608d17084a7 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java
@@ -17,27 +17,25 @@
package org.springframework.web.reactive.function.client;
import java.net.URI;
-import java.nio.charset.Charset;
-import java.time.ZonedDateTime;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
-import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ClientHttpRequest;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserter;
-import org.springframework.web.util.DefaultUriTemplateHandler;
-import org.springframework.web.util.UriTemplateHandler;
/**
- * Represents a typed, immutable, client-side HTTP request, as executed by the {@link WebClient}.
- * Instances of this interface are created via static builder methods:
- * {@link #method(HttpMethod, String, Object...)}, {@link #GET(String, Object...)}, etc.
+ * Represents a typed, immutable, client-side HTTP request, as executed by the
+ * {@link WebClient}. Instances of this interface can be created via static
+ * builder methods in this class.
*
+ *
Note that applications are more likely to perform requests through
+ * {@link WebClientOperations} rather than using this directly.
+ * :
* @param the type of the body that this request contains
* @author Brian Clozel
* @author Arjen Poutsma
@@ -45,8 +43,6 @@ import org.springframework.web.util.UriTemplateHandler;
*/
public interface ClientRequest {
- // Instance methods
-
/**
* Return the HTTP method.
*/
@@ -81,6 +77,7 @@ public interface ClientRequest {
*/
Mono writeTo(ClientHttpRequest request, WebClientStrategies strategies);
+
// Static builder methods
/**
@@ -89,7 +86,7 @@ public interface ClientRequest {
* @param other the request to copy the method, URI, headers, and cookies from
* @return the created builder
*/
- static BodyBuilder from(ClientRequest> other) {
+ static Builder from(ClientRequest> other) {
Assert.notNull(other, "'other' must not be null");
return new DefaultClientRequestBuilder(other.method(), other.url())
.headers(other.headers())
@@ -102,100 +99,15 @@ public interface ClientRequest {
* @param url the URL
* @return the created builder
*/
- static BodyBuilder method(HttpMethod method, URI url) {
- return new DefaultClientRequestBuilder(method, url);
- }
-
- /**
- * Create a builder with the given method and url template.
- * @param method the HTTP method (GET, POST, etc)
- * @param urlTemplate the URL template
- * @param uriVariables optional variables to expand the template
- * @return the created builder
- */
- static BodyBuilder method(HttpMethod method, String urlTemplate, Object... uriVariables) {
- UriTemplateHandler templateHandler = new DefaultUriTemplateHandler();
- URI url = templateHandler.expand(urlTemplate, uriVariables);
+ static Builder method(HttpMethod method, URI url) {
return new DefaultClientRequestBuilder(method, url);
}
- /**
- * Create an HTTP GET builder with the given url template.
- * @param urlTemplate the URL template
- * @param uriVariables optional variables to expand the template
- * @return the created builder
- */
- static HeadersBuilder> GET(String urlTemplate, Object... uriVariables) {
- return method(HttpMethod.GET, urlTemplate, uriVariables);
- }
-
- /**
- * Create an HTTP HEAD builder with the given url template.
- * @param urlTemplate the URL template
- * @param uriVariables optional variables to expand the template
- * @return the created builder
- */
- static HeadersBuilder> HEAD(String urlTemplate, Object... uriVariables) {
- return method(HttpMethod.HEAD, urlTemplate, uriVariables);
- }
-
- /**
- * Create an HTTP POST builder with the given url template.
- * @param urlTemplate the URL template
- * @param uriVariables optional variables to expand the template
- * @return the created builder
- */
- static BodyBuilder POST(String urlTemplate, Object... uriVariables) {
- return method(HttpMethod.POST, urlTemplate, uriVariables);
- }
-
- /**
- * Create an HTTP PUT builder with the given url template.
- * @param urlTemplate the URL template
- * @param uriVariables optional variables to expand the template
- * @return the created builder
- */
- static BodyBuilder PUT(String urlTemplate, Object... uriVariables) {
- return method(HttpMethod.PUT, urlTemplate, uriVariables);
- }
-
- /**
- * Create an HTTP PATCH builder with the given url template.
- * @param urlTemplate the URL template
- * @param uriVariables optional variables to expand the template
- * @return the created builder
- */
- static BodyBuilder PATCH(String urlTemplate, Object... uriVariables) {
- return method(HttpMethod.PATCH, urlTemplate, uriVariables);
- }
-
- /**
- * Create an HTTP DELETE builder with the given url template.
- * @param urlTemplate the URL template
- * @param uriVariables optional variables to expand the template
- * @return the created builder
- */
- static HeadersBuilder> DELETE(String urlTemplate, Object... uriVariables) {
- return method(HttpMethod.DELETE, urlTemplate, uriVariables);
- }
-
- /**
- * Creates an HTTP OPTIONS builder with the given url template.
- * @param urlTemplate the URL template
- * @param uriVariables optional variables to expand the template
- * @return the created builder
- */
- static HeadersBuilder> OPTIONS(String urlTemplate, Object... uriVariables) {
- return method(HttpMethod.OPTIONS, urlTemplate, uriVariables);
- }
-
/**
- * Defines a builder that adds headers to the request.
- *
- * @param the builder subclass
+ * Defines a builder for a request.
*/
- interface HeadersBuilder> {
+ interface Builder {
/**
* Add the given, single header value under the given name.
@@ -204,7 +116,7 @@ public interface ClientRequest {
* @return this builder
* @see HttpHeaders#add(String, String)
*/
- B header(String headerName, String... headerValues);
+ Builder header(String headerName, String... headerValues);
/**
* Copy the given headers into the entity's headers map.
@@ -212,39 +124,7 @@ public interface ClientRequest {
* @param headers the existing HttpHeaders to copy from
* @return this builder
*/
- B headers(HttpHeaders headers);
-
- /**
- * Set the list of acceptable {@linkplain MediaType media types}, as
- * specified by the {@code Accept} header.
- * @param acceptableMediaTypes the acceptable media types
- * @return this builder
- */
- B accept(MediaType... acceptableMediaTypes);
-
- /**
- * Set the list of acceptable {@linkplain Charset charsets}, as specified
- * by the {@code Accept-Charset} header.
- * @param acceptableCharsets the acceptable charsets
- * @return this builder
- */
- B acceptCharset(Charset... acceptableCharsets);
-
- /**
- * Set the value of the {@code If-Modified-Since} header.
- * The date should be specified as the number of milliseconds since
- * January 1, 1970 GMT.
- * @param ifModifiedSince the new value of the header
- * @return this builder
- */
- B ifModifiedSince(ZonedDateTime ifModifiedSince);
-
- /**
- * Set the values of the {@code If-None-Match} header.
- * @param ifNoneMatches the new value of the header
- * @return this builder
- */
- B ifNoneMatch(String... ifNoneMatches);
+ Builder headers(HttpHeaders headers);
/**
* Add a cookie with the given name and value.
@@ -252,7 +132,7 @@ public interface ClientRequest {
* @param value the cookie value
* @return this builder
*/
- B cookie(String name, String value);
+ Builder cookie(String name, String value);
/**
* Copy the given cookies into the entity's cookies map.
@@ -260,39 +140,13 @@ public interface ClientRequest {
* @param cookies the existing cookies to copy from
* @return this builder
*/
- B cookies(MultiValueMap cookies);
+ Builder cookies(MultiValueMap cookies);
/**
* Builds the request entity with no body.
* @return the request entity
*/
ClientRequest build();
- }
-
-
- /**
- * Defines a builder that adds a body to the request entity.
- */
- interface BodyBuilder extends HeadersBuilder {
-
-
- /**
- * Set the length of the body in bytes, as specified by the
- * {@code Content-Length} header.
- * @param contentLength the content length
- * @return this builder
- * @see HttpHeaders#setContentLength(long)
- */
- BodyBuilder contentLength(long contentLength);
-
- /**
- * Set the {@linkplain MediaType media type} of the body, as specified
- * by the {@code Content-Type} header.
- * @param contentType the content type
- * @return this builder
- * @see HttpHeaders#setContentType(MediaType)
- */
- BodyBuilder contentType(MediaType contentType);
/**
* Set the body of the request to the given {@code BodyInserter} and return it.
@@ -314,5 +168,4 @@ public interface ClientRequest {
}
-
}
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java
index 0af5c1b2c20..e0f65d6db8d 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java
@@ -17,11 +17,6 @@
package org.springframework.web.reactive.function.client;
import java.net.URI;
-import java.nio.charset.Charset;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.function.Supplier;
@@ -33,7 +28,6 @@ import reactor.core.publisher.Mono;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
-import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ClientHttpRequest;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.util.Assert;
@@ -44,12 +38,12 @@ import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
/**
- * Default implementation of {@link ClientRequest.BodyBuilder}.
+ * Default implementation of {@link ClientRequest.Builder}.
*
* @author Arjen Poutsma
* @since 5.0
*/
-class DefaultClientRequestBuilder implements ClientRequest.BodyBuilder {
+class DefaultClientRequestBuilder implements ClientRequest.Builder {
private final HttpMethod method;
@@ -66,7 +60,7 @@ class DefaultClientRequestBuilder implements ClientRequest.BodyBuilder {
}
@Override
- public ClientRequest.BodyBuilder header(String headerName, String... headerValues) {
+ public ClientRequest.Builder header(String headerName, String... headerValues) {
for (String headerValue : headerValues) {
this.headers.add(headerName, headerValue);
}
@@ -74,7 +68,7 @@ class DefaultClientRequestBuilder implements ClientRequest.BodyBuilder {
}
@Override
- public ClientRequest.BodyBuilder headers(HttpHeaders headers) {
+ public ClientRequest.Builder headers(HttpHeaders headers) {
if (headers != null) {
this.headers.putAll(headers);
}
@@ -82,39 +76,13 @@ class DefaultClientRequestBuilder implements ClientRequest.BodyBuilder {
}
@Override
- public ClientRequest.BodyBuilder accept(MediaType... acceptableMediaTypes) {
- this.headers.setAccept(Arrays.asList(acceptableMediaTypes));
- return this;
- }
-
- @Override
- public ClientRequest.BodyBuilder acceptCharset(Charset... acceptableCharsets) {
- this.headers.setAcceptCharset(Arrays.asList(acceptableCharsets));
- return this;
- }
-
- @Override
- public ClientRequest.BodyBuilder ifModifiedSince(ZonedDateTime ifModifiedSince) {
- ZonedDateTime gmt = ifModifiedSince.withZoneSameInstant(ZoneId.of("GMT"));
- String headerValue = DateTimeFormatter.RFC_1123_DATE_TIME.format(gmt);
- this.headers.set(HttpHeaders.IF_MODIFIED_SINCE, headerValue);
- return this;
- }
-
- @Override
- public ClientRequest.BodyBuilder ifNoneMatch(String... ifNoneMatches) {
- this.headers.setIfNoneMatch(Arrays.asList(ifNoneMatches));
- return this;
- }
-
- @Override
- public ClientRequest.BodyBuilder cookie(String name, String value) {
+ public ClientRequest.Builder cookie(String name, String value) {
this.cookies.add(name, value);
return this;
}
@Override
- public ClientRequest.BodyBuilder cookies(MultiValueMap cookies) {
+ public ClientRequest.Builder cookies(MultiValueMap cookies) {
if (cookies != null) {
this.cookies.putAll(cookies);
}
@@ -126,18 +94,6 @@ class DefaultClientRequestBuilder implements ClientRequest.BodyBuilder {
return body(BodyInserters.empty());
}
- @Override
- public ClientRequest.BodyBuilder contentLength(long contentLength) {
- this.headers.setContentLength(contentLength);
- return this;
- }
-
- @Override
- public ClientRequest.BodyBuilder contentType(MediaType contentType) {
- this.headers.setContentType(contentType);
- return this;
- }
-
@Override
public ClientRequest body(BodyInserter inserter) {
Assert.notNull(inserter, "'inserter' must not be null");
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientOperations.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientOperations.java
index bc2ea689f81..0c06efe9dc6 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientOperations.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientOperations.java
@@ -17,7 +17,10 @@ package org.springframework.web.reactive.function.client;
import java.net.URI;
import java.nio.charset.Charset;
+import java.time.ZoneId;
import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
import java.util.function.Function;
import org.jetbrains.annotations.NotNull;
@@ -137,47 +140,53 @@ class DefaultWebClientOperations implements WebClientOperations {
private class DefaultHeaderSpec implements HeaderSpec {
- private ClientRequest.BodyBuilder requestBuilder;
+ private final ClientRequest.Builder requestBuilder;
+ private final HttpHeaders headers = new HttpHeaders();
- DefaultHeaderSpec(ClientRequest.BodyBuilder requestBuilder) {
+
+ DefaultHeaderSpec(ClientRequest.Builder requestBuilder) {
this.requestBuilder = requestBuilder;
}
@Override
public DefaultHeaderSpec header(String headerName, String... headerValues) {
- this.requestBuilder.header(headerName, headerValues);
+ for (String headerValue : headerValues) {
+ this.headers.add(headerName, headerValue);
+ }
return this;
}
@Override
public DefaultHeaderSpec headers(HttpHeaders headers) {
- this.requestBuilder.headers(headers);
+ if (headers != null) {
+ this.headers.putAll(headers);
+ }
return this;
}
@Override
public DefaultHeaderSpec accept(MediaType... acceptableMediaTypes) {
- this.requestBuilder.accept(acceptableMediaTypes);
+ this.headers.setAccept(Arrays.asList(acceptableMediaTypes));
return this;
}
@Override
public DefaultHeaderSpec acceptCharset(Charset... acceptableCharsets) {
- this.requestBuilder.acceptCharset(acceptableCharsets);
+ this.headers.setAcceptCharset(Arrays.asList(acceptableCharsets));
return this;
}
@Override
public DefaultHeaderSpec contentType(MediaType contentType) {
- this.requestBuilder.contentType(contentType);
+ this.headers.setContentType(contentType);
return this;
}
@Override
public DefaultHeaderSpec contentLength(long contentLength) {
- this.requestBuilder.contentLength(contentLength);
+ this.headers.setContentLength(contentLength);
return this;
}
@@ -195,31 +204,33 @@ class DefaultWebClientOperations implements WebClientOperations {
@Override
public DefaultHeaderSpec ifModifiedSince(ZonedDateTime ifModifiedSince) {
- this.requestBuilder.ifModifiedSince(ifModifiedSince);
+ ZonedDateTime gmt = ifModifiedSince.withZoneSameInstant(ZoneId.of("GMT"));
+ String headerValue = DateTimeFormatter.RFC_1123_DATE_TIME.format(gmt);
+ this.headers.set(HttpHeaders.IF_MODIFIED_SINCE, headerValue);
return this;
}
@Override
public DefaultHeaderSpec ifNoneMatch(String... ifNoneMatches) {
- this.requestBuilder.ifNoneMatch(ifNoneMatches);
+ this.headers.setIfNoneMatch(Arrays.asList(ifNoneMatches));
return this;
}
@Override
public Mono exchange() {
- ClientRequest request = this.requestBuilder.build();
+ ClientRequest request = this.requestBuilder.headers(this.headers).build();
return getWebClient().exchange(request);
}
@Override
public Mono exchange(BodyInserter inserter) {
- ClientRequest request = this.requestBuilder.body(inserter);
+ ClientRequest request = this.requestBuilder.headers(this.headers).body(inserter);
return getWebClient().exchange(request);
}
@Override
public > Mono exchange(S publisher, Class elementClass) {
- ClientRequest request = this.requestBuilder.body(publisher, elementClass);
+ ClientRequest request = this.requestBuilder.headers(this.headers).body(publisher, elementClass);
return getWebClient().exchange(request);
}
}
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java
index 7cd0d14e323..5e72bcea6d1 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java
@@ -37,15 +37,17 @@ import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.bootstrap.RxNettyHttpServer;
import org.springframework.util.Assert;
import org.springframework.web.reactive.function.BodyExtractors;
-import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.client.WebClientOperations;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+import org.springframework.web.util.UriBuilderFactory;
/**
* @author Sebastien Deleuze
*/
public class FlushingIntegrationTests extends AbstractHttpHandlerIntegrationTests {
- private WebClient webClient;
+ private WebClientOperations operations;
@Before
@@ -55,15 +57,18 @@ public class FlushingIntegrationTests extends AbstractHttpHandlerIntegrationTest
Assume.assumeFalse(this.server instanceof RxNettyHttpServer);
super.setup();
- this.webClient = WebClient.create(new ReactorClientHttpConnector());
+
+ WebClient client = WebClient.create(new ReactorClientHttpConnector());
+ UriBuilderFactory factory = new DefaultUriBuilderFactory("http://localhost:" + this.port);
+ this.operations = WebClientOperations.builder(client).uriBuilderFactory(factory).build();
}
@Test
public void writeAndFlushWith() throws Exception {
- ClientRequest request = ClientRequest.GET("http://localhost:" + port + "/write-and-flush").build();
- Mono result = this.webClient
- .exchange(request)
+ Mono result = this.operations.get()
+ .uri("/write-and-flush")
+ .exchange()
.flatMap(response -> response.body(BodyExtractors.toFlux(String.class)))
.takeUntil(s -> s.endsWith("data1"))
.reduce((s1, s2) -> s1 + s2);
@@ -76,9 +81,9 @@ public class FlushingIntegrationTests extends AbstractHttpHandlerIntegrationTest
@Test // SPR-14991
public void writeAndAutoFlushOnComplete() {
- ClientRequest request = ClientRequest.GET("http://localhost:" + port + "/write-and-complete").build();
- Mono result = this.webClient
- .exchange(request)
+ Mono result = this.operations.get()
+ .uri("/write-and-complete")
+ .exchange()
.flatMap(response -> response.bodyToFlux(String.class))
.reduce((s1, s2) -> s1 + s2);
@@ -90,9 +95,9 @@ public class FlushingIntegrationTests extends AbstractHttpHandlerIntegrationTest
@Test // SPR-14992
public void writeAndAutoFlushBeforeComplete() {
- ClientRequest request = ClientRequest.GET("http://localhost:" + port + "/write-and-never-complete").build();
- Flux result = this.webClient
- .exchange(request)
+ Flux result = this.operations.get()
+ .uri("/write-and-never-complete")
+ .exchange()
.flatMap(response -> response.bodyToFlux(String.class));
StepVerifier.create(result)
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java
index a32dbd53918..b16ad3c0c7e 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java
@@ -18,11 +18,7 @@ package org.springframework.web.reactive.function.client;
import java.net.URI;
import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.time.ZonedDateTime;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import org.junit.Test;
@@ -31,8 +27,6 @@ import reactor.core.publisher.Mono;
import org.springframework.core.codec.CharSequenceEncoder;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ClientHttpRequest;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageWriter;
@@ -45,6 +39,9 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import static org.springframework.http.HttpMethod.DELETE;
+import static org.springframework.http.HttpMethod.GET;
+import static org.springframework.http.HttpMethod.POST;
/**
* @author Arjen Poutsma
@@ -53,12 +50,12 @@ public class DefaultClientRequestBuilderTests {
@Test
public void from() throws Exception {
- ClientRequest other = ClientRequest.GET("http://example.com")
+ ClientRequest other = ClientRequest.method(GET, URI.create("http://example.com"))
.header("foo", "bar")
.cookie("baz", "qux").build();
ClientRequest result = ClientRequest.from(other).build();
assertEquals(new URI("http://example.com"), result.url());
- assertEquals(HttpMethod.GET, result.method());
+ assertEquals(GET, result.method());
assertEquals("bar", result.headers().getFirst("foo"));
assertEquals("qux", result.cookies().getFirst("baz"));
}
@@ -66,112 +63,26 @@ public class DefaultClientRequestBuilderTests {
@Test
public void method() throws Exception {
URI url = new URI("http://example.com");
- ClientRequest result = ClientRequest.method(HttpMethod.DELETE, url).build();
+ ClientRequest result = ClientRequest.method(DELETE, url).build();
assertEquals(url, result.url());
- assertEquals(HttpMethod.DELETE, result.method());
- }
-
- @Test
- public void GET() throws Exception {
- URI url = new URI("http://example.com");
- ClientRequest result = ClientRequest.GET(url.toString()).build();
- assertEquals(url, result.url());
- assertEquals(HttpMethod.GET, result.method());
- }
-
- @Test
- public void HEAD() throws Exception {
- URI url = new URI("http://example.com");
- ClientRequest result = ClientRequest.HEAD(url.toString()).build();
- assertEquals(url, result.url());
- assertEquals(HttpMethod.HEAD, result.method());
- }
-
- @Test
- public void POST() throws Exception {
- URI url = new URI("http://example.com");
- ClientRequest result = ClientRequest.POST(url.toString()).build();
- assertEquals(url, result.url());
- assertEquals(HttpMethod.POST, result.method());
- }
-
- @Test
- public void PUT() throws Exception {
- URI url = new URI("http://example.com");
- ClientRequest result = ClientRequest.PUT(url.toString()).build();
- assertEquals(url, result.url());
- assertEquals(HttpMethod.PUT, result.method());
- }
-
- @Test
- public void PATCH() throws Exception {
- URI url = new URI("http://example.com");
- ClientRequest result = ClientRequest.PATCH(url.toString()).build();
- assertEquals(url, result.url());
- assertEquals(HttpMethod.PATCH, result.method());
- }
-
- @Test
- public void DELETE() throws Exception {
- URI url = new URI("http://example.com");
- ClientRequest result = ClientRequest.DELETE(url.toString()).build();
- assertEquals(url, result.url());
- assertEquals(HttpMethod.DELETE, result.method());
- }
-
- @Test
- public void OPTIONS() throws Exception {
- URI url = new URI("http://example.com");
- ClientRequest result = ClientRequest.OPTIONS(url.toString()).build();
- assertEquals(url, result.url());
- assertEquals(HttpMethod.OPTIONS, result.method());
- }
-
- @Test
- public void accept() throws Exception {
- MediaType json = MediaType.APPLICATION_JSON;
- ClientRequest result = ClientRequest.GET("http://example.com").accept(json).build();
- assertEquals(Collections.singletonList(json), result.headers().getAccept());
- }
-
- @Test
- public void acceptCharset() throws Exception {
- Charset charset = Charset.defaultCharset();
- ClientRequest result = ClientRequest.GET("http://example.com")
- .acceptCharset(charset).build();
- assertEquals(Collections.singletonList(charset), result.headers().getAcceptCharset());
- }
-
- @Test
- public void ifModifiedSince() throws Exception {
- ZonedDateTime now = ZonedDateTime.now();
- ClientRequest result = ClientRequest.GET("http://example.com")
- .ifModifiedSince(now).build();
- assertEquals(now.toInstant().toEpochMilli()/1000, result.headers().getIfModifiedSince()/1000);
- }
-
- @Test
- public void ifNoneMatch() throws Exception {
- ClientRequest result = ClientRequest.GET("http://example.com")
- .ifNoneMatch("\"v2.7\"", "\"v2.8\"").build();
- assertEquals(Arrays.asList("\"v2.7\"", "\"v2.8\""), result.headers().getIfNoneMatch());
+ assertEquals(DELETE, result.method());
}
@Test
public void cookie() throws Exception {
- ClientRequest result = ClientRequest.GET("http://example.com")
+ ClientRequest result = ClientRequest.method(GET, URI.create("http://example.com"))
.cookie("foo", "bar").build();
assertEquals("bar", result.cookies().getFirst("foo"));
}
@Test
public void build() throws Exception {
- ClientRequest result = ClientRequest.GET("http://example.com")
+ ClientRequest result = ClientRequest.method(GET, URI.create("http://example.com"))
.header("MyKey", "MyValue")
.cookie("foo", "bar")
.build();
- MockClientHttpRequest request = new MockClientHttpRequest(HttpMethod.GET, "/");
+ MockClientHttpRequest request = new MockClientHttpRequest(GET, "/");
WebClientStrategies strategies = mock(WebClientStrategies.class);
result.writeTo(request, strategies).block();
@@ -193,7 +104,7 @@ public class DefaultClientRequestBuilderTests {
return response.writeWith(Mono.just(buffer));
};
- ClientRequest result = ClientRequest.POST("http://example.com")
+ ClientRequest result = ClientRequest.method(POST, URI.create("http://example.com"))
.body(inserter);
List> messageWriters = new ArrayList<>();
@@ -202,7 +113,7 @@ public class DefaultClientRequestBuilderTests {
WebClientStrategies strategies = mock(WebClientStrategies.class);
when(strategies.messageWriters()).thenReturn(messageWriters::stream);
- MockClientHttpRequest request = new MockClientHttpRequest(HttpMethod.GET, "/");
+ MockClientHttpRequest request = new MockClientHttpRequest(GET, "/");
result.writeTo(request, strategies).block();
assertNotNull(request.getBody());
}
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctionsTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctionsTests.java
index 299ce98b22b..37bcc3e4c8f 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctionsTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/ExchangeFilterFunctionsTests.java
@@ -16,15 +16,19 @@
package org.springframework.web.reactive.function.client;
+import java.net.URI;
+
import org.junit.Test;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
+import static org.springframework.http.HttpMethod.GET;
/**
* @author Arjen Poutsma
@@ -33,7 +37,7 @@ public class ExchangeFilterFunctionsTests {
@Test
public void andThen() throws Exception {
- ClientRequest request = ClientRequest.GET("http://example.com").build();
+ ClientRequest request = ClientRequest.method(GET, URI.create("http://example.com")).build();
ClientResponse response = mock(ClientResponse.class);
ExchangeFunction exchange = r -> Mono.just(response);
@@ -63,7 +67,7 @@ public class ExchangeFilterFunctionsTests {
@Test
public void apply() throws Exception {
- ClientRequest request = ClientRequest.GET("http://example.com").build();
+ ClientRequest request = ClientRequest.method(GET, URI.create("http://example.com")).build();
ClientResponse response = mock(ClientResponse.class);
ExchangeFunction exchange = r -> Mono.just(response);
@@ -82,7 +86,7 @@ public class ExchangeFilterFunctionsTests {
@Test
public void basicAuthentication() throws Exception {
- ClientRequest request = ClientRequest.GET("http://example.com").build();
+ ClientRequest request = ClientRequest.method(GET, URI.create("http://example.com")).build();
ClientResponse response = mock(ClientResponse.class);
ExchangeFunction exchange = r -> {
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java
index 9d8a2c0b924..5dabfc061cd 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java
@@ -18,7 +18,6 @@ package org.springframework.web.reactive.function.client;
import java.time.Duration;
-import okhttp3.HttpUrl;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
@@ -36,15 +35,11 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.codec.Pojo;
-import org.springframework.web.reactive.function.BodyExtractors;
-import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilderFactory;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
-import static org.springframework.web.reactive.function.BodyExtractors.toFlux;
-import static org.springframework.web.reactive.function.BodyExtractors.toMono;
import static org.springframework.web.reactive.function.BodyInserters.fromObject;
/**
@@ -171,14 +166,9 @@ public class WebClientIntegrationTests {
@Test
public void jsonPojoFlux() throws Exception {
- HttpUrl baseUrl = server.url("/pojos");
this.server.enqueue(new MockResponse().setHeader("Content-Type", "application/json")
.setBody("[{\"bar\":\"bar1\",\"foo\":\"foo1\"},{\"bar\":\"bar2\",\"foo\":\"foo2\"}]"));
- ClientRequest request = ClientRequest.GET(baseUrl.toString())
- .accept(MediaType.APPLICATION_JSON)
- .build();
-
Flux result = this.operations.get()
.uri("/pojos")
.accept(MediaType.APPLICATION_JSON)
@@ -199,7 +189,6 @@ public class WebClientIntegrationTests {
@Test
public void postJsonPojo() throws Exception {
- HttpUrl baseUrl = server.url("/pojo/capitalize");
this.server.enqueue(new MockResponse()
.setHeader("Content-Type", "application/json")
.setBody("{\"bar\":\"BARBAR\",\"foo\":\"FOOFOO\"}"));
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java
index 23618990b5c..e58fc194310 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java
@@ -18,22 +18,24 @@ package org.springframework.web.reactive.function.server;
import java.time.Duration;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.Test;
-import static org.springframework.http.MediaType.TEXT_EVENT_STREAM;
-import static org.springframework.web.reactive.function.BodyExtractors.toFlux;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
-import org.springframework.core.ResolvableType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.codec.ServerSentEvent;
-import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.client.WebClientOperations;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+import org.springframework.web.util.UriBuilderFactory;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.springframework.core.ResolvableType.forClassWithGenerics;
+import static org.springframework.http.MediaType.TEXT_EVENT_STREAM;
+import static org.springframework.web.reactive.function.BodyExtractors.toFlux;
import static org.springframework.web.reactive.function.BodyInserters.fromServerSentEvents;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
@@ -42,12 +44,15 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r
*/
public class SseHandlerFunctionIntegrationTests extends AbstractRouterFunctionIntegrationTests {
+ private WebClientOperations operations;
- private WebClient webClient;
@Before
- public void createWebClient() {
- this.webClient = WebClient.create(new ReactorClientHttpConnector());
+ public void setup() throws Exception {
+ super.setup();
+ WebClient client = WebClient.create(new ReactorClientHttpConnector());
+ UriBuilderFactory factory = new DefaultUriBuilderFactory("http://localhost:" + this.port);
+ this.operations = WebClientOperations.builder(client).uriBuilderFactory(factory).build();
}
@Override
@@ -60,13 +65,10 @@ public class SseHandlerFunctionIntegrationTests extends AbstractRouterFunctionIn
@Test
public void sseAsString() throws Exception {
- ClientRequest request = ClientRequest
- .GET("http://localhost:{port}/string", this.port)
- .accept(TEXT_EVENT_STREAM)
- .build();
-
- Flux result = this.webClient
- .exchange(request)
+ Flux result = this.operations.get()
+ .uri("/string")
+ .accept(TEXT_EVENT_STREAM)
+ .exchange()
.flatMap(response -> response.body(toFlux(String.class)));
StepVerifier.create(result)
@@ -77,14 +79,10 @@ public class SseHandlerFunctionIntegrationTests extends AbstractRouterFunctionIn
}
@Test
public void sseAsPerson() throws Exception {
- ClientRequest request =
- ClientRequest
- .GET("http://localhost:{port}/person", this.port)
- .accept(TEXT_EVENT_STREAM)
- .build();
-
- Flux result = this.webClient
- .exchange(request)
+ Flux result = this.operations.get()
+ .uri("/person")
+ .accept(TEXT_EVENT_STREAM)
+ .exchange()
.flatMap(response -> response.body(toFlux(Person.class)));
StepVerifier.create(result)
@@ -96,16 +94,12 @@ public class SseHandlerFunctionIntegrationTests extends AbstractRouterFunctionIn
@Test
public void sseAsEvent() throws Exception {
- ClientRequest request =
- ClientRequest
- .GET("http://localhost:{port}/event", this.port)
- .accept(TEXT_EVENT_STREAM)
- .build();
-
- ResolvableType type = ResolvableType.forClassWithGenerics(ServerSentEvent.class, String.class);
- Flux> result = this.webClient
- .exchange(request)
- .flatMap(response -> response.body(toFlux(type)));
+ Flux> result = this.operations.get()
+ .uri("/event")
+ .accept(TEXT_EVENT_STREAM)
+ .exchange()
+ .flatMap(response -> response.body(toFlux(
+ forClassWithGenerics(ServerSentEvent.class, String.class))));
StepVerifier.create(result)
.consumeNextWith( event -> {
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java
index 676f30c5648..83387cc0a25 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java
@@ -18,14 +18,9 @@ package org.springframework.web.reactive.result.method.annotation;
import java.time.Duration;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.Test;
-import static org.springframework.http.MediaType.TEXT_EVENT_STREAM;
-import static org.springframework.web.reactive.function.BodyExtractors.toFlux;
import reactor.core.publisher.Flux;
-
import reactor.test.StepVerifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -40,9 +35,17 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.reactive.config.EnableWebReactive;
-import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.client.WebClientOperations;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+import org.springframework.web.util.UriBuilderFactory;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.springframework.core.ResolvableType.forClassWithGenerics;
+import static org.springframework.http.MediaType.TEXT_EVENT_STREAM;
+import static org.springframework.web.reactive.function.BodyExtractors.toFlux;
/**
@@ -52,14 +55,16 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
private AnnotationConfigApplicationContext wac;
- private WebClient webClient;
+ private WebClientOperations operations;
@Override
@Before
public void setup() throws Exception {
super.setup();
- this.webClient = WebClient.create(new ReactorClientHttpConnector());
+ WebClient client = WebClient.create(new ReactorClientHttpConnector());
+ UriBuilderFactory factory = new DefaultUriBuilderFactory("http://localhost:" + this.port + "/sse");
+ this.operations = WebClientOperations.builder(client).uriBuilderFactory(factory).build();
}
@@ -74,14 +79,11 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
@Test
public void sseAsString() throws Exception {
- ClientRequest request = ClientRequest
- .GET("http://localhost:{port}/sse/string", this.port)
- .accept(TEXT_EVENT_STREAM)
- .build();
-
- Flux result = this.webClient
- .exchange(request)
- .flatMap(response -> response.body(toFlux(String.class)));
+ Flux result = this.operations.get()
+ .uri("/string")
+ .accept(TEXT_EVENT_STREAM)
+ .exchange()
+ .flatMap(response -> response.bodyToFlux(String.class));
StepVerifier.create(result)
.expectNext("foo 0")
@@ -91,15 +93,11 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
}
@Test
public void sseAsPerson() throws Exception {
- ClientRequest request =
- ClientRequest
- .GET("http://localhost:{port}/sse/person", this.port)
- .accept(TEXT_EVENT_STREAM)
- .build();
-
- Flux result = this.webClient
- .exchange(request)
- .flatMap(response -> response.body(toFlux(Person.class)));
+ Flux result = this.operations.get()
+ .uri("/person")
+ .accept(TEXT_EVENT_STREAM)
+ .exchange()
+ .flatMap(response -> response.bodyToFlux(Person.class));
StepVerifier.create(result)
.expectNext(new Person("foo 0"))
@@ -110,15 +108,11 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
@Test
public void sseAsEvent() throws Exception {
- ClientRequest request =
- ClientRequest
- .GET("http://localhost:{port}/sse/event", this.port)
- .accept(TEXT_EVENT_STREAM)
- .build();
-
- ResolvableType type = ResolvableType.forClassWithGenerics(ServerSentEvent.class, String.class);
- Flux> result = this.webClient
- .exchange(request)
+ ResolvableType type = forClassWithGenerics(ServerSentEvent.class, String.class);
+ Flux> result = this.operations.get()
+ .uri("/event")
+ .accept(TEXT_EVENT_STREAM)
+ .exchange()
.flatMap(response -> response.body(toFlux(type)));
StepVerifier.create(result)
@@ -142,15 +136,12 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
@Test
public void sseAsEventWithoutAcceptHeader() throws Exception {
- ClientRequest request =
- ClientRequest
- .GET("http://localhost:{port}/sse/event", this.port)
+ Flux> result = this.operations.get()
+ .uri("/event")
.accept(TEXT_EVENT_STREAM)
- .build();
-
- Flux> result = this.webClient
- .exchange(request)
- .flatMap(response -> response.body(toFlux(ResolvableType.forClassWithGenerics(ServerSentEvent.class, String.class))));
+ .exchange()
+ .flatMap(response -> response.body(toFlux(
+ forClassWithGenerics(ServerSentEvent.class, String.class))));
StepVerifier.create(result)
.consumeNextWith( event -> {