Remove http -> web package dependency

See gh-24406
This commit is contained in:
Rossen Stoyanchev
2020-06-10 21:45:26 +01:00
parent adc76a1d8f
commit a0f4d81db7
3 changed files with 130 additions and 62 deletions

View File

@@ -24,13 +24,10 @@ import java.time.ZonedDateTime;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriTemplateHandler;
/** /**
* Extension of {@link HttpEntity} that also exposes the HTTP method and the * Extension of {@link HttpEntity} that also exposes the HTTP method and the
@@ -69,17 +66,14 @@ import org.springframework.web.util.UriTemplateHandler;
*/ */
public class RequestEntity<T> extends HttpEntity<T> { public class RequestEntity<T> extends HttpEntity<T> {
private final static UriTemplateHandler DEFAULT_TEMPLATE_HANDLER = new DefaultUriBuilderFactory();
@Nullable @Nullable
private final HttpMethod method; private final HttpMethod method;
private final Function<UriTemplateHandler, URI> uriFunction; private final URI url;
@Nullable @Nullable
private final Type type; private final Type type;
/** /**
* Constructor with method and URL but without body nor headers. * Constructor with method and URL but without body nor headers.
* @param method the method * @param method the method
@@ -146,19 +140,9 @@ public class RequestEntity<T> extends HttpEntity<T> {
public RequestEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, public RequestEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers,
@Nullable HttpMethod method, URI url, @Nullable Type type) { @Nullable HttpMethod method, URI url, @Nullable Type type) {
this(body, headers, method, handler -> url, type);
}
/**
* Private constructor with URI function.
* @since 5.3
*/
private RequestEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers,
@Nullable HttpMethod method, Function<UriTemplateHandler, URI> uriFunction, @Nullable Type type) {
super(body, headers); super(body, headers);
this.method = method; this.method = method;
this.uriFunction = uriFunction; this.url = url;
this.type = type; this.type = type;
} }
@@ -174,24 +158,9 @@ public class RequestEntity<T> extends HttpEntity<T> {
/** /**
* Return the URL of the request. * Return the URL of the request.
* <p>If the URL was provided as a URI template, the returned URI is expanded
* and encoded with {@link DefaultUriBuilderFactory}.
* @return the URL as a {@code URI}
*/ */
public URI getUrl() { public URI getUrl() {
return this.uriFunction.apply(DEFAULT_TEMPLATE_HANDLER); return this.url;
}
/**
* Return the URL of the request.
* <p>If the URL was provided as a URI template, the returned URI is expanded
* with the given {@link DefaultUriBuilderFactory}.
* @param templateHandler the handler to use to expand the URI template with
* @return the URL as a {@code URI}
* @since 5.3
*/
public URI getUrl(UriTemplateHandler templateHandler) {
return this.uriFunction.apply(templateHandler);
} }
@@ -235,13 +204,15 @@ public class RequestEntity<T> extends HttpEntity<T> {
@Override @Override
public String toString() { public String toString() {
return format(getMethod(), getUrl().toString(), getBody(), getHeaders());
}
static <T> String format(@Nullable HttpMethod httpMethod, String url, @Nullable T body, HttpHeaders headers) {
StringBuilder builder = new StringBuilder("<"); StringBuilder builder = new StringBuilder("<");
builder.append(getMethod()); builder.append(httpMethod);
builder.append(' '); builder.append(' ');
builder.append(getUrl()); builder.append(url);
builder.append(','); builder.append(',');
T body = getBody();
HttpHeaders headers = getHeaders();
if (body != null) { if (body != null) {
builder.append(body); builder.append(body);
builder.append(','); builder.append(',');
@@ -563,24 +534,42 @@ public class RequestEntity<T> extends HttpEntity<T> {
private final HttpMethod method; private final HttpMethod method;
private final Function<UriTemplateHandler, URI> uriFunction;
private final HttpHeaders headers = new HttpHeaders(); private final HttpHeaders headers = new HttpHeaders();
@Nullable
private final URI uri;
public DefaultBodyBuilder(HttpMethod method, URI url) { @Nullable
String uriTemplate;
@Nullable
private Object[] uriVarsArray;
@Nullable
Map<String, ?> uriVarsMap;
DefaultBodyBuilder(HttpMethod method, URI url) {
this.method = method; this.method = method;
this.uriFunction = handler -> url; this.uri = url;
this.uriTemplate = null;
this.uriVarsArray = null;
this.uriVarsMap = null;
} }
public DefaultBodyBuilder(HttpMethod method, String uriTemplate, Object... uriVars) { DefaultBodyBuilder(HttpMethod method, String uriTemplate, Object... uriVars) {
this.method = method; this.method = method;
this.uriFunction = handler -> handler.expand(uriTemplate, uriVars); this.uri = null;
this.uriTemplate = uriTemplate;
this.uriVarsArray = uriVars;
this.uriVarsMap = null;
} }
public DefaultBodyBuilder(HttpMethod method, String uriTemplate, Map<String, ?> uriVars) { DefaultBodyBuilder(HttpMethod method, String uriTemplate, Map<String, ?> uriVars) {
this.method = method; this.method = method;
this.uriFunction = handler -> handler.expand(uriTemplate, uriVars); this.uri = null;
this.uriTemplate = uriTemplate;
this.uriVarsArray = null;
this.uriVarsMap = uriVars;
} }
@Override @Override
@@ -655,17 +644,85 @@ public class RequestEntity<T> extends HttpEntity<T> {
@Override @Override
public RequestEntity<Void> build() { public RequestEntity<Void> build() {
return new RequestEntity<>(null, this.headers, this.method, this.uriFunction, null); return buildInternal(null, null);
} }
@Override @Override
public <T> RequestEntity<T> body(T body) { public <T> RequestEntity<T> body(T body) {
return new RequestEntity<>(body, this.headers, this.method, this.uriFunction, null); return buildInternal(body, null);
} }
@Override @Override
public <T> RequestEntity<T> body(T body, Type type) { public <T> RequestEntity<T> body(T body, Type type) {
return new RequestEntity<>(body, this.headers, this.method, this.uriFunction, type); return buildInternal(body, type);
}
private <T> RequestEntity<T> buildInternal(@Nullable T body, @Nullable Type type) {
if (this.uri != null) {
return new RequestEntity<>(body, this.headers, this.method, this.uri, type);
}
else if (this.uriTemplate != null){
return new UriTemplateRequestEntity<>(body, this.headers, this.method, type,
this.uriTemplate, this.uriVarsArray, this.uriVarsMap);
}
else {
throw new IllegalStateException("Neither URI nor URI template");
}
} }
} }
/**
* RequestEntity initialized with a URI template and variables instead of a {@link URI}.
* @since 5.3
* @param <T> the body type
*/
public static class UriTemplateRequestEntity<T> extends RequestEntity<T> {
String uriTemplate;
@Nullable
private Object[] uriVarsArray;
@Nullable
Map<String, ?> uriVarsMap;
UriTemplateRequestEntity(
@Nullable T body, @Nullable MultiValueMap<String, String> headers,
@Nullable HttpMethod method, @Nullable Type type, String uriTemplate,
@Nullable Object[] uriVarsArray, @Nullable Map<String, ?> uriVarsMap) {
super(body, headers, method, null, type);
this.uriTemplate = uriTemplate;
this.uriVarsArray = uriVarsArray;
this.uriVarsMap = uriVarsMap;
}
public String getUriTemplate() {
return this.uriTemplate;
}
@Nullable
public Object[] getVars() {
return this.uriVarsArray;
}
@Nullable
public Map<String, ?> getVarsMap() {
return this.uriVarsMap;
}
@Override
public URI getUrl() {
throw new UnsupportedOperationException();
}
@Override
public String toString() {
return format(getMethod(), getUriTemplate(), getBody(), getHeaders());
}
}
} }

View File

@@ -633,24 +633,34 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
} }
@Override @Override
public <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType) public <T> ResponseEntity<T> exchange(RequestEntity<?> entity, Class<T> responseType)
throws RestClientException { throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType); RequestCallback requestCallback = httpEntityCallback(entity, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType); ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
URI url = requestEntity.getUrl(this.uriTemplateHandler); return nonNull(doExecute(resolveUrl(entity), entity.getMethod(), requestCallback, responseExtractor));
return nonNull(doExecute(url, requestEntity.getMethod(), requestCallback, responseExtractor));
} }
@Override @Override
public <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, ParameterizedTypeReference<T> responseType) public <T> ResponseEntity<T> exchange(RequestEntity<?> entity, ParameterizedTypeReference<T> responseType)
throws RestClientException { throws RestClientException {
Type type = responseType.getType(); Type type = responseType.getType();
RequestCallback requestCallback = httpEntityCallback(requestEntity, type); RequestCallback requestCallback = httpEntityCallback(entity, type);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(type); ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(type);
URI url = requestEntity.getUrl(this.uriTemplateHandler); return nonNull(doExecute(resolveUrl(entity), entity.getMethod(), requestCallback, responseExtractor));
return nonNull(doExecute(url, requestEntity.getMethod(), requestCallback, responseExtractor)); }
private URI resolveUrl(RequestEntity<?> entity) {
if (entity instanceof RequestEntity.UriTemplateRequestEntity) {
RequestEntity.UriTemplateRequestEntity<?> ext = (RequestEntity.UriTemplateRequestEntity<?>) entity;
return (ext.getVars() != null ?
this.uriTemplateHandler.expand(ext.getUriTemplate(), ext.getVars()) :
this.uriTemplateHandler.expand(ext.getUriTemplate(), ext.getVarsMap()));
}
else {
return entity.getUrl();
}
} }

View File

@@ -82,16 +82,17 @@ public class RequestEntityTests {
} }
@Test @Test
public void uriExpansion() throws URISyntaxException{ public void uriExpansion() {
RequestEntity<Void> entity = RequestEntity<Void> entity =
RequestEntity.get("https://www.{host}.com/{path}", "example", "foo/bar").build(); RequestEntity.get("https://www.{host}.com/{path}", "example", "foo/bar").build();
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(); assertThat(entity).isInstanceOf(RequestEntity.UriTemplateRequestEntity.class);
assertThat(entity.getUrl(factory)).isEqualTo(new URI("https://www.example.com/foo%2Fbar")); RequestEntity.UriTemplateRequestEntity<Void> ext = (RequestEntity.UriTemplateRequestEntity<Void>) entity;
factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE); DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
assertThat(entity.getUrl(factory)).isEqualTo(new URI("https://www.example.com/foo/bar")); assertThat(ext.getUriTemplate()).isEqualTo("https://www.{host}.com/{path}");
assertThat(ext.getVars()).containsExactly("example", "foo/bar");
} }