parent
							
								
									8b77ed164d
								
							
						
					
					
						commit
						57ed5bf34b
					
				| 
						 | 
					@ -31,24 +31,26 @@ import org.springframework.web.service.invoker.HttpRequestValues;
 | 
				
			||||||
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
 | 
					import org.springframework.web.service.invoker.HttpServiceProxyFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * {@link HttpExchangeAdapter} that enables an {@link HttpServiceProxyFactory} to use
 | 
					 * {@link HttpExchangeAdapter} that enables an {@link HttpServiceProxyFactory}
 | 
				
			||||||
 * {@link RestClient} for request execution.
 | 
					 * to use {@link RestClient} for request execution.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * <p>
 | 
					 * <p>Use static factory methods in this class to create an
 | 
				
			||||||
 * Use static factory methods in this class to create an {@link HttpServiceProxyFactory}
 | 
					 * {@link HttpServiceProxyFactory} configured with the given {@link RestClient}.
 | 
				
			||||||
 * configured with a given {@link RestClient}.
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Olga Maciaszek-Sharma
 | 
					 * @author Olga Maciaszek-Sharma
 | 
				
			||||||
 | 
					 * @author Rossen Stoyanchev
 | 
				
			||||||
 * @since 6.1
 | 
					 * @since 6.1
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public final class RestClientAdapter implements HttpExchangeAdapter {
 | 
					public final class RestClientAdapter implements HttpExchangeAdapter {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final RestClient restClient;
 | 
						private final RestClient restClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private RestClientAdapter(RestClient restClient) {
 | 
						private RestClientAdapter(RestClient restClient) {
 | 
				
			||||||
		this.restClient = restClient;
 | 
							this.restClient = restClient;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public boolean supportsRequestAttributes() {
 | 
						public boolean supportsRequestAttributes() {
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
| 
						 | 
					@ -60,66 +62,66 @@ public final class RestClientAdapter implements HttpExchangeAdapter {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public HttpHeaders exchangeForHeaders(HttpRequestValues requestValues) {
 | 
						public HttpHeaders exchangeForHeaders(HttpRequestValues values) {
 | 
				
			||||||
		return newRequest(requestValues).retrieve().toBodilessEntity().getHeaders();
 | 
							return newRequest(values).retrieve().toBodilessEntity().getHeaders();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public <T> T exchangeForBody(HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
 | 
						public <T> T exchangeForBody(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
 | 
				
			||||||
		return newRequest(requestValues).retrieve().body(bodyType);
 | 
							return newRequest(values).retrieve().body(bodyType);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public ResponseEntity<Void> exchangeForBodilessEntity(HttpRequestValues requestValues) {
 | 
						public ResponseEntity<Void> exchangeForBodilessEntity(HttpRequestValues values) {
 | 
				
			||||||
		return newRequest(requestValues).retrieve().toBodilessEntity();
 | 
							return newRequest(values).retrieve().toBodilessEntity();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public <T> ResponseEntity<T> exchangeForEntity(HttpRequestValues requestValues,
 | 
						public <T> ResponseEntity<T> exchangeForEntity(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
 | 
				
			||||||
			ParameterizedTypeReference<T> bodyType) {
 | 
							return newRequest(values).retrieve().toEntity(bodyType);
 | 
				
			||||||
		return newRequest(requestValues).retrieve().toEntity(bodyType);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private RestClient.RequestBodySpec newRequest(HttpRequestValues requestValues) {
 | 
						private RestClient.RequestBodySpec newRequest(HttpRequestValues values) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		HttpMethod httpMethod = requestValues.getHttpMethod();
 | 
							HttpMethod httpMethod = values.getHttpMethod();
 | 
				
			||||||
		Assert.notNull(httpMethod, "HttpMethod is required");
 | 
							Assert.notNull(httpMethod, "HttpMethod is required");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RestClient.RequestBodyUriSpec uriSpec = this.restClient.method(httpMethod);
 | 
							RestClient.RequestBodyUriSpec uriSpec = this.restClient.method(httpMethod);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RestClient.RequestBodySpec bodySpec;
 | 
							RestClient.RequestBodySpec bodySpec;
 | 
				
			||||||
		if (requestValues.getUri() != null) {
 | 
							if (values.getUri() != null) {
 | 
				
			||||||
			bodySpec = uriSpec.uri(requestValues.getUri());
 | 
								bodySpec = uriSpec.uri(values.getUri());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (requestValues.getUriTemplate() != null) {
 | 
							else if (values.getUriTemplate() != null) {
 | 
				
			||||||
			bodySpec = uriSpec.uri(requestValues.getUriTemplate(), requestValues.getUriVariables());
 | 
								bodySpec = uriSpec.uri(values.getUriTemplate(), values.getUriVariables());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			throw new IllegalStateException("Neither full URL nor URI template");
 | 
								throw new IllegalStateException("Neither full URL nor URI template");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bodySpec.headers(headers -> headers.putAll(requestValues.getHeaders()));
 | 
							bodySpec.headers(headers -> headers.putAll(values.getHeaders()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!requestValues.getCookies().isEmpty()) {
 | 
							if (!values.getCookies().isEmpty()) {
 | 
				
			||||||
			List<String> cookies = new ArrayList<>();
 | 
								List<String> cookies = new ArrayList<>();
 | 
				
			||||||
			requestValues.getCookies().forEach((name, values) -> values.forEach(value -> {
 | 
								values.getCookies().forEach((name, cookieValues) -> cookieValues.forEach(value -> {
 | 
				
			||||||
				HttpCookie cookie = new HttpCookie(name, value);
 | 
									HttpCookie cookie = new HttpCookie(name, value);
 | 
				
			||||||
				cookies.add(cookie.toString());
 | 
									cookies.add(cookie.toString());
 | 
				
			||||||
			}));
 | 
								}));
 | 
				
			||||||
			bodySpec.header(HttpHeaders.COOKIE, String.join("; ", cookies));
 | 
								bodySpec.header(HttpHeaders.COOKIE, String.join("; ", cookies));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bodySpec.attributes(attributes -> attributes.putAll(requestValues.getAttributes()));
 | 
							bodySpec.attributes(attributes -> attributes.putAll(values.getAttributes()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (requestValues.getBodyValue() != null) {
 | 
							if (values.getBodyValue() != null) {
 | 
				
			||||||
			bodySpec.body(requestValues.getBodyValue());
 | 
								bodySpec.body(values.getBodyValue());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return bodySpec;
 | 
							return bodySpec;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Create a {@link RestClientAdapter} with the given {@link RestClient}.
 | 
						 * Create a {@link RestClientAdapter} for the given {@link RestClient}.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public static RestClientAdapter create(RestClient restClient) {
 | 
						public static RestClientAdapter create(RestClient restClient) {
 | 
				
			||||||
		return new RestClientAdapter(restClient);
 | 
							return new RestClientAdapter(restClient);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,11 +34,11 @@ import org.springframework.web.service.invoker.HttpRequestValues;
 | 
				
			||||||
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
 | 
					import org.springframework.web.service.invoker.HttpServiceProxyFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * {@link HttpExchangeAdapter} that enables an {@link HttpServiceProxyFactory} to use
 | 
					 * {@link HttpExchangeAdapter} that enables an {@link HttpServiceProxyFactory}
 | 
				
			||||||
 * {@link RestTemplate} for request execution.
 | 
					 * to use {@link RestTemplate} for request execution.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * <p>Use static factory methods in this class to create an
 | 
					 * <p>Use static factory methods in this class to create an
 | 
				
			||||||
 * {@link HttpServiceProxyFactory} configured with a given {@link RestTemplate}.
 | 
					 * {@link HttpServiceProxyFactory} configured with the given {@link RestTemplate}.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Olga Maciaszek-Sharma
 | 
					 * @author Olga Maciaszek-Sharma
 | 
				
			||||||
 * @since 6.1
 | 
					 * @since 6.1
 | 
				
			||||||
| 
						 | 
					@ -59,63 +59,61 @@ public final class RestTemplateAdapter implements HttpExchangeAdapter {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public void exchange(HttpRequestValues requestValues) {
 | 
						public void exchange(HttpRequestValues values) {
 | 
				
			||||||
		this.restTemplate.exchange(newRequest(requestValues), Void.class);
 | 
							this.restTemplate.exchange(newRequest(values), Void.class);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public HttpHeaders exchangeForHeaders(HttpRequestValues requestValues) {
 | 
						public HttpHeaders exchangeForHeaders(HttpRequestValues values) {
 | 
				
			||||||
		return this.restTemplate.exchange(newRequest(requestValues), Void.class).getHeaders();
 | 
							return this.restTemplate.exchange(newRequest(values), Void.class).getHeaders();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public <T> T exchangeForBody(HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
 | 
						public <T> T exchangeForBody(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
 | 
				
			||||||
		return this.restTemplate.exchange(newRequest(requestValues), bodyType).getBody();
 | 
							return this.restTemplate.exchange(newRequest(values), bodyType).getBody();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public ResponseEntity<Void> exchangeForBodilessEntity(HttpRequestValues requestValues) {
 | 
						public ResponseEntity<Void> exchangeForBodilessEntity(HttpRequestValues values) {
 | 
				
			||||||
		return this.restTemplate.exchange(newRequest(requestValues), Void.class);
 | 
							return this.restTemplate.exchange(newRequest(values), Void.class);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public <T> ResponseEntity<T> exchangeForEntity(
 | 
						public <T> ResponseEntity<T> exchangeForEntity(HttpRequestValues values, ParameterizedTypeReference<T> bodyType) {
 | 
				
			||||||
			HttpRequestValues requestValues, ParameterizedTypeReference<T> bodyType) {
 | 
							return this.restTemplate.exchange(newRequest(values), bodyType);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return this.restTemplate.exchange(newRequest(requestValues), bodyType);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private RequestEntity<?> newRequest(HttpRequestValues requestValues) {
 | 
						private RequestEntity<?> newRequest(HttpRequestValues values) {
 | 
				
			||||||
		URI uri;
 | 
							URI uri;
 | 
				
			||||||
		if (requestValues.getUri() != null) {
 | 
							if (values.getUri() != null) {
 | 
				
			||||||
			uri = requestValues.getUri();
 | 
								uri = values.getUri();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (requestValues.getUriTemplate() != null) {
 | 
							else if (values.getUriTemplate() != null) {
 | 
				
			||||||
			String uriTemplate = requestValues.getUriTemplate();
 | 
								String uriTemplate = values.getUriTemplate();
 | 
				
			||||||
			Map<String, String> variables = requestValues.getUriVariables();
 | 
								Map<String, String> variables = values.getUriVariables();
 | 
				
			||||||
			uri = this.restTemplate.getUriTemplateHandler().expand(uriTemplate, variables);
 | 
								uri = this.restTemplate.getUriTemplateHandler().expand(uriTemplate, variables);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			throw new IllegalStateException("Neither full URL nor URI template");
 | 
								throw new IllegalStateException("Neither full URL nor URI template");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		HttpMethod httpMethod = requestValues.getHttpMethod();
 | 
							HttpMethod httpMethod = values.getHttpMethod();
 | 
				
			||||||
		Assert.notNull(httpMethod, "HttpMethod is required");
 | 
							Assert.notNull(httpMethod, "HttpMethod is required");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RequestEntity.BodyBuilder builder = RequestEntity.method(httpMethod, uri);
 | 
							RequestEntity.BodyBuilder builder = RequestEntity.method(httpMethod, uri);
 | 
				
			||||||
		builder.headers(requestValues.getHeaders());
 | 
							builder.headers(values.getHeaders());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!requestValues.getCookies().isEmpty()) {
 | 
							if (!values.getCookies().isEmpty()) {
 | 
				
			||||||
			List<String> cookies = new ArrayList<>();
 | 
								List<String> cookies = new ArrayList<>();
 | 
				
			||||||
			requestValues.getCookies().forEach((name, values) -> values.forEach(value -> {
 | 
								values.getCookies().forEach((name, cookieValues) -> cookieValues.forEach(value -> {
 | 
				
			||||||
				HttpCookie cookie = new HttpCookie(name, value);
 | 
									HttpCookie cookie = new HttpCookie(name, value);
 | 
				
			||||||
				cookies.add(cookie.toString());
 | 
									cookies.add(cookie.toString());
 | 
				
			||||||
			}));
 | 
								}));
 | 
				
			||||||
			builder.header(HttpHeaders.COOKIE, String.join("; ", cookies));
 | 
								builder.header(HttpHeaders.COOKIE, String.join("; ", cookies));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (requestValues.getBodyValue() != null) {
 | 
							if (values.getBodyValue() != null) {
 | 
				
			||||||
			return builder.body(requestValues.getBodyValue());
 | 
								return builder.body(values.getBodyValue());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return builder.build();
 | 
							return builder.build();
 | 
				
			||||||
| 
						 | 
					@ -123,7 +121,7 @@ public final class RestTemplateAdapter implements HttpExchangeAdapter {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Create a {@link RestTemplateAdapter} with the given {@link RestTemplate}.
 | 
						 * Create a {@link RestTemplateAdapter} for the given {@link RestTemplate}.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public static RestTemplateAdapter create(RestTemplate restTemplate) {
 | 
						public static RestTemplateAdapter create(RestTemplate restTemplate) {
 | 
				
			||||||
		return new RestTemplateAdapter(restTemplate);
 | 
							return new RestTemplateAdapter(restTemplate);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,9 +53,9 @@ import org.springframework.web.service.annotation.HttpExchange;
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Rossen Stoyanchev
 | 
					 * @author Rossen Stoyanchev
 | 
				
			||||||
 * @since 6.0
 | 
					 * @since 6.0
 | 
				
			||||||
 * @see org.springframework.web.client.support.RestTemplateAdapter
 | 
					 | 
				
			||||||
 * @see org.springframework.web.reactive.function.client.support.WebClientAdapter
 | 
					 | 
				
			||||||
 * @see org.springframework.web.client.support.RestClientAdapter
 | 
					 * @see org.springframework.web.client.support.RestClientAdapter
 | 
				
			||||||
 | 
					 * @see org.springframework.web.reactive.function.client.support.WebClientAdapter
 | 
				
			||||||
 | 
					 * @see org.springframework.web.client.support.RestTemplateAdapter
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public final class HttpServiceProxyFactory {
 | 
					public final class HttpServiceProxyFactory {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,17 +16,21 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package org.springframework.web.client.support;
 | 
					package org.springframework.web.client.support;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.lang.annotation.ElementType;
 | 
				
			||||||
 | 
					import java.lang.annotation.Retention;
 | 
				
			||||||
 | 
					import java.lang.annotation.RetentionPolicy;
 | 
				
			||||||
 | 
					import java.lang.annotation.Target;
 | 
				
			||||||
import java.net.URI;
 | 
					import java.net.URI;
 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					import java.util.stream.Stream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import okhttp3.mockwebserver.MockResponse;
 | 
					import okhttp3.mockwebserver.MockResponse;
 | 
				
			||||||
import okhttp3.mockwebserver.MockWebServer;
 | 
					import okhttp3.mockwebserver.MockWebServer;
 | 
				
			||||||
import okhttp3.mockwebserver.RecordedRequest;
 | 
					import okhttp3.mockwebserver.RecordedRequest;
 | 
				
			||||||
import org.junit.jupiter.api.AfterEach;
 | 
					import org.junit.jupiter.params.ParameterizedTest;
 | 
				
			||||||
import org.junit.jupiter.api.BeforeEach;
 | 
					import org.junit.jupiter.params.provider.MethodSource;
 | 
				
			||||||
import org.junit.jupiter.api.Test;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.cglib.core.internal.Function;
 | 
				
			||||||
import org.springframework.http.HttpStatus;
 | 
					import org.springframework.http.HttpStatus;
 | 
				
			||||||
import org.springframework.http.MediaType;
 | 
					import org.springframework.http.MediaType;
 | 
				
			||||||
import org.springframework.http.ResponseEntity;
 | 
					import org.springframework.http.ResponseEntity;
 | 
				
			||||||
| 
						 | 
					@ -40,113 +44,127 @@ import org.springframework.web.bind.annotation.RequestHeader;
 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestParam;
 | 
					import org.springframework.web.bind.annotation.RequestParam;
 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestPart;
 | 
					import org.springframework.web.bind.annotation.RequestPart;
 | 
				
			||||||
import org.springframework.web.client.RestClient;
 | 
					import org.springframework.web.client.RestClient;
 | 
				
			||||||
 | 
					import org.springframework.web.client.RestTemplate;
 | 
				
			||||||
import org.springframework.web.multipart.MultipartFile;
 | 
					import org.springframework.web.multipart.MultipartFile;
 | 
				
			||||||
import org.springframework.web.service.annotation.GetExchange;
 | 
					import org.springframework.web.service.annotation.GetExchange;
 | 
				
			||||||
import org.springframework.web.service.annotation.PostExchange;
 | 
					import org.springframework.web.service.annotation.PostExchange;
 | 
				
			||||||
import org.springframework.web.service.annotation.PutExchange;
 | 
					import org.springframework.web.service.annotation.PutExchange;
 | 
				
			||||||
 | 
					import org.springframework.web.service.invoker.HttpExchangeAdapter;
 | 
				
			||||||
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
 | 
					import org.springframework.web.service.invoker.HttpServiceProxyFactory;
 | 
				
			||||||
import org.springframework.web.testfixture.servlet.MockMultipartFile;
 | 
					import org.springframework.web.testfixture.servlet.MockMultipartFile;
 | 
				
			||||||
 | 
					import org.springframework.web.util.DefaultUriBuilderFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
					import static org.assertj.core.api.Assertions.assertThat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Integration tests for {@link HttpServiceProxyFactory HTTP Service proxy} with
 | 
					 * Integration tests for {@link HttpServiceProxyFactory} with {@link RestClient}
 | 
				
			||||||
 * {@link RestClientAdapter} connecting to {@link MockWebServer}.
 | 
					 * and {@link RestTemplate} connecting to {@link MockWebServer}.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Olga Maciaszek-Sharma
 | 
					 * @author Olga Maciaszek-Sharma
 | 
				
			||||||
 | 
					 * @author Rossen Stoyanchev
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					@SuppressWarnings("JUnitMalformedDeclaration")
 | 
				
			||||||
class RestClientAdapterTests {
 | 
					class RestClientAdapterTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private MockWebServer server;
 | 
						@Retention(RetentionPolicy.RUNTIME)
 | 
				
			||||||
 | 
						@Target(ElementType.METHOD)
 | 
				
			||||||
	private Service service;
 | 
						@ParameterizedTest
 | 
				
			||||||
 | 
						@MethodSource("arguments")
 | 
				
			||||||
	@BeforeEach
 | 
						@interface ParameterizedAdapterTest {
 | 
				
			||||||
	void setUp() {
 | 
					 | 
				
			||||||
		this.server = new MockWebServer();
 | 
					 | 
				
			||||||
		prepareResponse();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		RestClient restClient = RestClient.builder().baseUrl(this.server.url("/").toString()).build();
 | 
					 | 
				
			||||||
		RestClientAdapter adapter = RestClientAdapter.create(restClient);
 | 
					 | 
				
			||||||
		this.service = HttpServiceProxyFactory.builderFor(adapter).build().createClient(Service.class);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@SuppressWarnings("ConstantConditions")
 | 
						public static Stream<Object[]> arguments() {
 | 
				
			||||||
	@AfterEach
 | 
							return Stream.of(
 | 
				
			||||||
	void shutDown() throws IOException {
 | 
									args(url -> {
 | 
				
			||||||
		if (this.server != null) {
 | 
										RestClient restClient = RestClient.builder().baseUrl(url).build();
 | 
				
			||||||
			this.server.shutdown();
 | 
										return RestClientAdapter.create(restClient);
 | 
				
			||||||
		}
 | 
									}),
 | 
				
			||||||
 | 
									args(url -> {
 | 
				
			||||||
 | 
										RestTemplate restTemplate = new RestTemplate();
 | 
				
			||||||
 | 
										restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(url));
 | 
				
			||||||
 | 
										return RestTemplateAdapter.create(restTemplate);
 | 
				
			||||||
 | 
									}));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@SuppressWarnings("resource")
 | 
				
			||||||
	void greeting() throws InterruptedException {
 | 
						private static Object[] args(Function<String, HttpExchangeAdapter> adapterFactory) {
 | 
				
			||||||
		String response = this.service.getGreeting();
 | 
							MockWebServer server = new MockWebServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
							MockResponse response = new MockResponse();
 | 
				
			||||||
 | 
							response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!");
 | 
				
			||||||
 | 
							server.enqueue(response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							HttpExchangeAdapter adapter = adapterFactory.apply(server.url("/").toString());
 | 
				
			||||||
 | 
							Service service = HttpServiceProxyFactory.builderFor(adapter).build().createClient(Service.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return new Object[] { server, service };
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@ParameterizedAdapterTest
 | 
				
			||||||
 | 
						void greeting(MockWebServer server, Service service) throws Exception {
 | 
				
			||||||
 | 
							String response = service.getGreeting();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							RecordedRequest request = server.takeRequest();
 | 
				
			||||||
		assertThat(response).isEqualTo("Hello Spring!");
 | 
							assertThat(response).isEqualTo("Hello Spring!");
 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("GET");
 | 
							assertThat(request.getMethod()).isEqualTo("GET");
 | 
				
			||||||
		assertThat(request.getPath()).isEqualTo("/greeting");
 | 
							assertThat(request.getPath()).isEqualTo("/greeting");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@ParameterizedAdapterTest
 | 
				
			||||||
	void greetingById() throws InterruptedException {
 | 
						void greetingById(MockWebServer server, Service service) throws Exception {
 | 
				
			||||||
		ResponseEntity<String> response = this.service.getGreetingById("456");
 | 
							ResponseEntity<String> response = service.getGreetingById("456");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
							RecordedRequest request = server.takeRequest();
 | 
				
			||||||
		assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
 | 
							assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
 | 
				
			||||||
		assertThat(response.getBody()).isEqualTo("Hello Spring!");
 | 
							assertThat(response.getBody()).isEqualTo("Hello Spring!");
 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("GET");
 | 
							assertThat(request.getMethod()).isEqualTo("GET");
 | 
				
			||||||
		assertThat(request.getPath()).isEqualTo("/greeting/456");
 | 
							assertThat(request.getPath()).isEqualTo("/greeting/456");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@ParameterizedAdapterTest
 | 
				
			||||||
	void greetingWithDynamicUri() throws InterruptedException {
 | 
						void greetingWithDynamicUri(MockWebServer server, Service service) throws Exception {
 | 
				
			||||||
		URI dynamicUri = this.server.url("/greeting/123").uri();
 | 
							URI dynamicUri = server.url("/greeting/123").uri();
 | 
				
			||||||
 | 
							Optional<String> response = service.getGreetingWithDynamicUri(dynamicUri, "456");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Optional<String> response = this.service.getGreetingWithDynamicUri(dynamicUri, "456");
 | 
							RecordedRequest request = server.takeRequest();
 | 
				
			||||||
 | 
					 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
					 | 
				
			||||||
		assertThat(response.orElse("empty")).isEqualTo("Hello Spring!");
 | 
							assertThat(response.orElse("empty")).isEqualTo("Hello Spring!");
 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("GET");
 | 
							assertThat(request.getMethod()).isEqualTo("GET");
 | 
				
			||||||
		assertThat(request.getRequestUrl().uri()).isEqualTo(dynamicUri);
 | 
							assertThat(request.getRequestUrl().uri()).isEqualTo(dynamicUri);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@ParameterizedAdapterTest
 | 
				
			||||||
	void postWithHeader() throws InterruptedException {
 | 
						void postWithHeader(MockWebServer server, Service service) throws Exception {
 | 
				
			||||||
		service.postWithHeader("testHeader", "testBody");
 | 
							service.postWithHeader("testHeader", "testBody");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
							RecordedRequest request = server.takeRequest();
 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("POST");
 | 
							assertThat(request.getMethod()).isEqualTo("POST");
 | 
				
			||||||
		assertThat(request.getPath()).isEqualTo("/greeting");
 | 
							assertThat(request.getPath()).isEqualTo("/greeting");
 | 
				
			||||||
		assertThat(request.getHeaders().get("testHeaderName")).isEqualTo("testHeader");
 | 
							assertThat(request.getHeaders().get("testHeaderName")).isEqualTo("testHeader");
 | 
				
			||||||
		assertThat(request.getBody().readUtf8()).isEqualTo("testBody");
 | 
							assertThat(request.getBody().readUtf8()).isEqualTo("testBody");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@ParameterizedAdapterTest
 | 
				
			||||||
	void formData() throws Exception {
 | 
						void formData(MockWebServer server, Service service) throws Exception {
 | 
				
			||||||
		MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
 | 
							MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
 | 
				
			||||||
		map.add("param1", "value 1");
 | 
							map.add("param1", "value 1");
 | 
				
			||||||
		map.add("param2", "value 2");
 | 
							map.add("param2", "value 2");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		service.postForm(map);
 | 
							service.postForm(map);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
							RecordedRequest request = server.takeRequest();
 | 
				
			||||||
		assertThat(request.getHeaders().get("Content-Type"))
 | 
							assertThat(request.getHeaders().get("Content-Type")).isEqualTo("application/x-www-form-urlencoded;charset=UTF-8");
 | 
				
			||||||
			.isEqualTo("application/x-www-form-urlencoded;charset=UTF-8");
 | 
					 | 
				
			||||||
		assertThat(request.getBody().readUtf8()).isEqualTo("param1=value+1¶m2=value+2");
 | 
							assertThat(request.getBody().readUtf8()).isEqualTo("param1=value+1¶m2=value+2");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test // gh-30342
 | 
						@ParameterizedAdapterTest // gh-30342
 | 
				
			||||||
	void multipart() throws InterruptedException {
 | 
						void multipart(MockWebServer server, Service service) throws Exception {
 | 
				
			||||||
		String fileName = "testFileName";
 | 
							MultipartFile file = new MockMultipartFile(
 | 
				
			||||||
		String originalFileName = "originalTestFileName";
 | 
									"testFileName", "originalTestFileName", MediaType.APPLICATION_JSON_VALUE, "test".getBytes());
 | 
				
			||||||
		MultipartFile file = new MockMultipartFile(fileName, originalFileName, MediaType.APPLICATION_JSON_VALUE,
 | 
					 | 
				
			||||||
				"test".getBytes());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		service.postMultipart(file, "test2");
 | 
							service.postMultipart(file, "test2");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
							RecordedRequest request = server.takeRequest();
 | 
				
			||||||
		assertThat(request.getHeaders().get("Content-Type")).startsWith("multipart/form-data;boundary=");
 | 
							assertThat(request.getHeaders().get("Content-Type")).startsWith("multipart/form-data;boundary=");
 | 
				
			||||||
		assertThat(request.getBody().readUtf8()).containsSubsequence(
 | 
							assertThat(request.getBody().readUtf8()).containsSubsequence(
 | 
				
			||||||
				"Content-Disposition: form-data; name=\"file\"; filename=\"originalTestFileName\"",
 | 
									"Content-Disposition: form-data; name=\"file\"; filename=\"originalTestFileName\"",
 | 
				
			||||||
| 
						 | 
					@ -155,29 +173,24 @@ class RestClientAdapterTests {
 | 
				
			||||||
				"Content-Length: 5", "test2");
 | 
									"Content-Length: 5", "test2");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@ParameterizedAdapterTest
 | 
				
			||||||
	void putWithCookies() throws InterruptedException {
 | 
						void putWithCookies(MockWebServer server, Service service) throws Exception {
 | 
				
			||||||
		service.putWithCookies("test1", "test2");
 | 
							service.putWithCookies("test1", "test2");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
							RecordedRequest request = server.takeRequest();
 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("PUT");
 | 
							assertThat(request.getMethod()).isEqualTo("PUT");
 | 
				
			||||||
		assertThat(request.getHeader("Cookie")).isEqualTo("firstCookie=test1; secondCookie=test2");
 | 
							assertThat(request.getHeader("Cookie")).isEqualTo("firstCookie=test1; secondCookie=test2");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@ParameterizedAdapterTest
 | 
				
			||||||
	void putWithSameNameCookies() throws InterruptedException {
 | 
						void putWithSameNameCookies(MockWebServer server, Service service) throws Exception {
 | 
				
			||||||
		service.putWithSameNameCookies("test1", "test2");
 | 
							service.putWithSameNameCookies("test1", "test2");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
							RecordedRequest request = server.takeRequest();
 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("PUT");
 | 
							assertThat(request.getMethod()).isEqualTo("PUT");
 | 
				
			||||||
		assertThat(request.getHeader("Cookie")).isEqualTo("testCookie=test1; testCookie=test2");
 | 
							assertThat(request.getHeader("Cookie")).isEqualTo("testCookie=test1; testCookie=test2");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void prepareResponse() {
 | 
					 | 
				
			||||||
		MockResponse response = new MockResponse();
 | 
					 | 
				
			||||||
		response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!");
 | 
					 | 
				
			||||||
		this.server.enqueue(response);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private interface Service {
 | 
						private interface Service {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -203,8 +216,8 @@ class RestClientAdapterTests {
 | 
				
			||||||
		void putWithCookies(@CookieValue String firstCookie, @CookieValue String secondCookie);
 | 
							void putWithCookies(@CookieValue String firstCookie, @CookieValue String secondCookie);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@PutExchange
 | 
							@PutExchange
 | 
				
			||||||
		void putWithSameNameCookies(@CookieValue("testCookie") String firstCookie,
 | 
							void putWithSameNameCookies(
 | 
				
			||||||
				@CookieValue("testCookie") String secondCookie);
 | 
									@CookieValue("testCookie") String firstCookie, @CookieValue("testCookie") String secondCookie);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,218 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright 2002-2023 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.
 | 
					 | 
				
			||||||
 * You may obtain a copy of the License at
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Unless required by applicable law or agreed to in writing, software
 | 
					 | 
				
			||||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
					 | 
				
			||||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					 | 
				
			||||||
 * See the License for the specific language governing permissions and
 | 
					 | 
				
			||||||
 * limitations under the License.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package org.springframework.web.client.support;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.io.IOException;
 | 
					 | 
				
			||||||
import java.net.URI;
 | 
					 | 
				
			||||||
import java.util.Optional;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import okhttp3.mockwebserver.MockResponse;
 | 
					 | 
				
			||||||
import okhttp3.mockwebserver.MockWebServer;
 | 
					 | 
				
			||||||
import okhttp3.mockwebserver.RecordedRequest;
 | 
					 | 
				
			||||||
import org.junit.jupiter.api.AfterEach;
 | 
					 | 
				
			||||||
import org.junit.jupiter.api.BeforeEach;
 | 
					 | 
				
			||||||
import org.junit.jupiter.api.Test;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.springframework.http.HttpStatus;
 | 
					 | 
				
			||||||
import org.springframework.http.MediaType;
 | 
					 | 
				
			||||||
import org.springframework.http.ResponseEntity;
 | 
					 | 
				
			||||||
import org.springframework.lang.Nullable;
 | 
					 | 
				
			||||||
import org.springframework.util.LinkedMultiValueMap;
 | 
					 | 
				
			||||||
import org.springframework.util.MultiValueMap;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.CookieValue;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.PathVariable;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestBody;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestHeader;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestParam;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestPart;
 | 
					 | 
				
			||||||
import org.springframework.web.client.RestTemplate;
 | 
					 | 
				
			||||||
import org.springframework.web.multipart.MultipartFile;
 | 
					 | 
				
			||||||
import org.springframework.web.service.annotation.GetExchange;
 | 
					 | 
				
			||||||
import org.springframework.web.service.annotation.PostExchange;
 | 
					 | 
				
			||||||
import org.springframework.web.service.annotation.PutExchange;
 | 
					 | 
				
			||||||
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
 | 
					 | 
				
			||||||
import org.springframework.web.testfixture.servlet.MockMultipartFile;
 | 
					 | 
				
			||||||
import org.springframework.web.util.DefaultUriBuilderFactory;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Integration tests for {@link HttpServiceProxyFactory HTTP Service proxy}
 | 
					 | 
				
			||||||
 * with {@link RestTemplateAdapter} connecting to {@link MockWebServer}.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @author Olga Maciaszek-Sharma
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
class RestTemplateAdapterTests {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private MockWebServer server;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private Service service;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@BeforeEach
 | 
					 | 
				
			||||||
	void setUp() {
 | 
					 | 
				
			||||||
		this.server = new MockWebServer();
 | 
					 | 
				
			||||||
		prepareResponse();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		RestTemplate restTemplate = new RestTemplate();
 | 
					 | 
				
			||||||
		restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(this.server.url("/").toString()));
 | 
					 | 
				
			||||||
		RestTemplateAdapter adapter = RestTemplateAdapter.create(restTemplate);
 | 
					 | 
				
			||||||
		this.service = HttpServiceProxyFactory.builder().exchangeAdapter(adapter).build().createClient(Service.class);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@SuppressWarnings("ConstantConditions")
 | 
					 | 
				
			||||||
	@AfterEach
 | 
					 | 
				
			||||||
	void shutDown() throws IOException {
 | 
					 | 
				
			||||||
		if (this.server != null) {
 | 
					 | 
				
			||||||
			this.server.shutdown();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void greeting() throws InterruptedException {
 | 
					 | 
				
			||||||
		String response = this.service.getGreeting();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
					 | 
				
			||||||
		assertThat(response).isEqualTo("Hello Spring!");
 | 
					 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("GET");
 | 
					 | 
				
			||||||
		assertThat(request.getPath()).isEqualTo("/greeting");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void greetingById() throws InterruptedException {
 | 
					 | 
				
			||||||
		ResponseEntity<String> response = this.service.getGreetingById("456");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
					 | 
				
			||||||
		assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
 | 
					 | 
				
			||||||
		assertThat(response.getBody()).isEqualTo("Hello Spring!");
 | 
					 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("GET");
 | 
					 | 
				
			||||||
		assertThat(request.getPath()).isEqualTo("/greeting/456");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void greetingWithDynamicUri() throws InterruptedException {
 | 
					 | 
				
			||||||
		URI dynamicUri = this.server.url("/greeting/123").uri();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Optional<String> response = this.service.getGreetingWithDynamicUri(dynamicUri, "456");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
					 | 
				
			||||||
		assertThat(response.orElse("empty")).isEqualTo("Hello Spring!");
 | 
					 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("GET");
 | 
					 | 
				
			||||||
		assertThat(request.getRequestUrl().uri()).isEqualTo(dynamicUri);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void postWithHeader() throws InterruptedException {
 | 
					 | 
				
			||||||
		service.postWithHeader("testHeader", "testBody");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
					 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("POST");
 | 
					 | 
				
			||||||
		assertThat(request.getPath()).isEqualTo("/greeting");
 | 
					 | 
				
			||||||
		assertThat(request.getHeaders().get("testHeaderName")).isEqualTo("testHeader");
 | 
					 | 
				
			||||||
		assertThat(request.getBody().readUtf8()).isEqualTo("testBody");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void formData() throws Exception {
 | 
					 | 
				
			||||||
		MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
 | 
					 | 
				
			||||||
		map.add("param1", "value 1");
 | 
					 | 
				
			||||||
		map.add("param2", "value 2");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		service.postForm(map);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
					 | 
				
			||||||
		assertThat(request.getHeaders().get("Content-Type"))
 | 
					 | 
				
			||||||
			.isEqualTo("application/x-www-form-urlencoded;charset=UTF-8");
 | 
					 | 
				
			||||||
		assertThat(request.getBody().readUtf8()).isEqualTo("param1=value+1¶m2=value+2");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test // gh-30342
 | 
					 | 
				
			||||||
	void multipart() throws InterruptedException {
 | 
					 | 
				
			||||||
		String fileName = "testFileName";
 | 
					 | 
				
			||||||
		String originalFileName = "originalTestFileName";
 | 
					 | 
				
			||||||
		MultipartFile file = new MockMultipartFile(fileName, originalFileName, MediaType.APPLICATION_JSON_VALUE,
 | 
					 | 
				
			||||||
				"test".getBytes());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		service.postMultipart(file, "test2");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
					 | 
				
			||||||
		assertThat(request.getHeaders().get("Content-Type")).startsWith("multipart/form-data;boundary=");
 | 
					 | 
				
			||||||
		assertThat(request.getBody().readUtf8()).containsSubsequence(
 | 
					 | 
				
			||||||
				"Content-Disposition: form-data; name=\"file\"; filename=\"originalTestFileName\"",
 | 
					 | 
				
			||||||
				"Content-Type: application/json", "Content-Length: 4", "test",
 | 
					 | 
				
			||||||
				"Content-Disposition: form-data; name=\"anotherPart\"", "Content-Type: text/plain;charset=UTF-8",
 | 
					 | 
				
			||||||
				"Content-Length: 5", "test2");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void putWithCookies() throws InterruptedException {
 | 
					 | 
				
			||||||
		service.putWithCookies("test1", "test2");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
					 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("PUT");
 | 
					 | 
				
			||||||
		assertThat(request.getHeader("Cookie")).isEqualTo("firstCookie=test1; secondCookie=test2");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Test
 | 
					 | 
				
			||||||
	void putWithSameNameCookies() throws InterruptedException {
 | 
					 | 
				
			||||||
		service.putWithSameNameCookies("test1", "test2");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		RecordedRequest request = this.server.takeRequest();
 | 
					 | 
				
			||||||
		assertThat(request.getMethod()).isEqualTo("PUT");
 | 
					 | 
				
			||||||
		assertThat(request.getHeader("Cookie")).isEqualTo("testCookie=test1; testCookie=test2");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private void prepareResponse() {
 | 
					 | 
				
			||||||
		MockResponse response = new MockResponse();
 | 
					 | 
				
			||||||
		response.setHeader("Content-Type", "text/plain").setBody("Hello Spring!");
 | 
					 | 
				
			||||||
		this.server.enqueue(response);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private interface Service {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@GetExchange("/greeting")
 | 
					 | 
				
			||||||
		String getGreeting();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@GetExchange("/greeting/{id}")
 | 
					 | 
				
			||||||
		ResponseEntity<String> getGreetingById(@PathVariable String id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@GetExchange("/greeting/{id}")
 | 
					 | 
				
			||||||
		Optional<String> getGreetingWithDynamicUri(@Nullable URI uri, @PathVariable String id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@PostExchange("/greeting")
 | 
					 | 
				
			||||||
		void postWithHeader(
 | 
					 | 
				
			||||||
				@RequestHeader("testHeaderName") String testHeader, @RequestBody String requestBody);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@PostExchange(contentType = "application/x-www-form-urlencoded")
 | 
					 | 
				
			||||||
		void postForm(@RequestParam MultiValueMap<String, String> params);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@PostExchange
 | 
					 | 
				
			||||||
		void postMultipart(MultipartFile file, @RequestPart String anotherPart);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@PutExchange
 | 
					 | 
				
			||||||
		void putWithCookies(
 | 
					 | 
				
			||||||
				@CookieValue String firstCookie, @CookieValue String secondCookie);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@PutExchange
 | 
					 | 
				
			||||||
		void putWithSameNameCookies(
 | 
					 | 
				
			||||||
				@CookieValue("testCookie") String firstCookie, @CookieValue("testCookie") String secondCookie);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue