diff --git a/vertx-web-client/src/main/java/io/vertx/ext/web/client/CachingWebClient.java b/vertx-web-client/src/main/java/io/vertx/ext/web/client/CachingWebClient.java index 2dbde551e1..ddb157adf6 100644 --- a/vertx-web-client/src/main/java/io/vertx/ext/web/client/CachingWebClient.java +++ b/vertx-web-client/src/main/java/io/vertx/ext/web/client/CachingWebClient.java @@ -101,6 +101,19 @@ static WebClient create(WebClient webClient, CachingWebClientOptions options) { */ @GenIgnore(GenIgnore.PERMITTED_TYPE) static WebClient create(WebClient webClient, CacheStore cacheStore, CachingWebClientOptions options) { + return CachingWebClientImpl.wrap(webClient, cacheStore, new CachingWebClientConfig(options)); + } + + /** + * Create a cache aware web client using the provided {@link WebClient}. + * + * @param webClient the web client instance + * @param cacheStore the cache adapter + * @param options the caching web client options + * @return the created web client + */ + @GenIgnore(GenIgnore.PERMITTED_TYPE) + static WebClient create(WebClient webClient, CacheStore cacheStore, CachingWebClientConfig options) { return CachingWebClientImpl.wrap(webClient, cacheStore, options); } } diff --git a/vertx-web-client/src/main/java/io/vertx/ext/web/client/CachingWebClientConfig.java b/vertx-web-client/src/main/java/io/vertx/ext/web/client/CachingWebClientConfig.java new file mode 100644 index 0000000000..604947a2c7 --- /dev/null +++ b/vertx-web-client/src/main/java/io/vertx/ext/web/client/CachingWebClientConfig.java @@ -0,0 +1,308 @@ +/* + * Copyright 2021 Red Hat, Inc. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * The Apache License v2.0 is available at + * http://www.opensource.org/licenses/apache2.0.php + * + * You may elect to redistribute this code under either of these licenses. + */ +package io.vertx.ext.web.client; + +import io.vertx.codegen.annotations.DataObject; +import io.vertx.codegen.json.annotations.JsonGen; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.*; +import io.vertx.core.json.JsonObject; +import io.vertx.core.net.*; +import io.vertx.core.tracing.TracingPolicy; +import io.vertx.uritemplate.ExpandOptions; + +import java.time.Duration; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * @author Craig Day + */ +@DataObject +public class CachingWebClientConfig extends WebClientConfig { + + public static final Set DEFAULT_CACHED_STATUS_CODES = buildDefaultStatusCodes(); + public static final Set DEFAULT_CACHED_METHODS = buildDefaultMethods(); + + private boolean enableVaryCaching = false; + private Set cachedStatusCodes = DEFAULT_CACHED_STATUS_CODES; + private Set cachedMethods = DEFAULT_CACHED_METHODS; + + public CachingWebClientConfig() { + } + + CachingWebClientConfig(CachingWebClientOptions other) { + super(other); + + init(other); + } + + public CachingWebClientConfig(WebClientConfig other) { + super(other); + } + + void init(CachingWebClientConfig other) { + super.init(other); + this.enableVaryCaching = other.enableVaryCaching; + this.cachedStatusCodes = other.cachedStatusCodes; + this.cachedMethods = other.cachedMethods; + } + + void init(CachingWebClientOptions other) { + super.init(other); + this.enableVaryCaching = other.isVaryCachingEnabled(); + this.cachedStatusCodes = other.getCachedStatusCodes(); + this.cachedMethods = other.getCachedMethods(); + } + + /** + * Configure the client cache behavior for {@code Vary} responses. + * + * @param enabled true to enable caching varying responses + * @return a reference to this, so the API can be used fluently + */ + public CachingWebClientConfig setEnableVaryCaching(boolean enabled) { + this.enableVaryCaching = enabled; + return this; + } + + /** + * @return the set of status codes to consider cacheable. + */ + public Set getCachedStatusCodes() { + return cachedStatusCodes; + } + + /** + * Configure the status codes that can be cached. + * + * @param codes the cacheable status code numbers + * @return a reference to this, so the API can be used fluently + */ + public CachingWebClientConfig setCachedStatusCodes(Set codes) { + this.cachedStatusCodes = codes; + return this; + } + + /** + * Add a status code that is cacheable. + * + * @param code the additional code number + * @return a reference to this, so the API can be used fluently + */ + public CachingWebClientConfig addCachedStatusCode(Integer code) { + this.cachedStatusCodes.add(code); + return this; + } + + /** + * Remove a status code that is cacheable. + * + * @param code the code number to remove + * @return a reference to this, so the API can be used fluently + */ + public CachingWebClientConfig removeCachedStatusCode(Integer code) { + this.cachedStatusCodes.remove(code); + return this; + } + + /** + * @return the set of HTTP methods to consider cacheable. + */ + public Set getCachedMethods() { + return cachedMethods; + } + + /** + * Configure the HTTP methods that can be cached. + * + * @param methods the HTTP methods to cache + * @return a reference to this, so the API can be used fluently + */ + public CachingWebClientConfig setCachedMethods(Set methods) { + this.cachedMethods = methods; + return this; + } + + /** + * Add an HTTP method that is cacheable. + * + * @param method the method to add + * @return a reference to this, so the API can be used fluently + */ + public CachingWebClientConfig addCachedMethod(HttpMethod method) { + this.cachedMethods.add(method); + return this; + } + + /** + * Remove an HTTP method that is cacheable. + * + * @param method the method to remove + * @return a reference to this, so the API can be used fluently + */ + public CachingWebClientConfig removeCachedMethod(HttpMethod method) { + this.cachedMethods.remove(method); + return this; + } + + /** + * @return true if the client will cache responses with the {@code Vary} header, false otherwise + */ + public boolean isVaryCachingEnabled() { + return enableVaryCaching; + } + + @Override + public CachingWebClientConfig setUserAgentEnabled(boolean userAgentEnabled) { + return (CachingWebClientConfig) super.setUserAgentEnabled(userAgentEnabled); + } + + @Override + public CachingWebClientConfig setUserAgent(String userAgent) { + return (CachingWebClientConfig) super.setUserAgent(userAgent); + } + + @Override + public CachingWebClientConfig setFollowRedirects(boolean followRedirects) { + return (CachingWebClientConfig) super.setFollowRedirects(followRedirects); + } + + @Override + public CachingWebClientConfig setTemplateExpandOptions(ExpandOptions templateExpandOptions) { + return (CachingWebClientConfig) super.setTemplateExpandOptions(templateExpandOptions); + } + + @Override + public CachingWebClientConfig setSslOptions(ClientSSLOptions sslOptions) { + return (CachingWebClientConfig) super.setSslOptions(sslOptions); + } + + @Override + public CachingWebClientConfig setMetricsName(String metricsName) { + return (CachingWebClientConfig) super.setMetricsName(metricsName); + } + + @Override + public CachingWebClientConfig setConnectTimeout(Duration connectTimeout) { + return (CachingWebClientConfig) super.setConnectTimeout(connectTimeout); + } + + @Override + public CachingWebClientConfig setIdleTimeout(Duration idleTimeout) { + return (CachingWebClientConfig) super.setIdleTimeout(idleTimeout); + } + + @Override + public CachingWebClientConfig setReadIdleTimeout(Duration idleTimeout) { + return (CachingWebClientConfig) super.setReadIdleTimeout(idleTimeout); + } + + @Override + public CachingWebClientConfig setWriteIdleTimeout(Duration idleTimeout) { + return (CachingWebClientConfig) super.setWriteIdleTimeout(idleTimeout); + } + + @Override + public CachingWebClientConfig setSsl(boolean ssl) { + return (CachingWebClientConfig) super.setSsl(ssl); + } + + @Override + public CachingWebClientConfig setVersions(List versions) { + return (CachingWebClientConfig) super.setVersions(versions); + } + + @Override + public CachingWebClientConfig setHttp1Config(Http1ClientConfig config) { + return (CachingWebClientConfig) super.setHttp1Config(config); + } + + @Override + public CachingWebClientConfig setHttp2Config(Http2ClientConfig config) { + return (CachingWebClientConfig) super.setHttp2Config(config); + } + + @Override + public CachingWebClientConfig setHttp3Config(Http3ClientConfig config) { + return (CachingWebClientConfig) super.setHttp3Config(config); + } + + @Override + public CachingWebClientConfig setVerifyHost(boolean verifyHost) { + return (CachingWebClientConfig) super.setVerifyHost(verifyHost); + } + + @Override + public CachingWebClientConfig setDecompressionEnabled(boolean decompressionEnabled) { + return (CachingWebClientConfig) super.setDecompressionEnabled(decompressionEnabled); + } + + @Override + public CachingWebClientConfig setDefaultHost(String defaultHost) { + return (CachingWebClientConfig) super.setDefaultHost(defaultHost); + } + + @Override + public CachingWebClientConfig setDefaultPort(int defaultPort) { + return (CachingWebClientConfig) super.setDefaultPort(defaultPort); + } + + @Override + public CachingWebClientConfig setMaxRedirects(int maxRedirects) { + return (CachingWebClientConfig) super.setMaxRedirects(maxRedirects); + } + + @Override + public CachingWebClientConfig setForceSni(boolean forceSni) { + return (CachingWebClientConfig) super.setForceSni(forceSni); + } + + @Override + public CachingWebClientConfig setTracingPolicy(TracingPolicy tracingPolicy) { + return (CachingWebClientConfig) super.setTracingPolicy(tracingPolicy); + } + + @Override + public CachingWebClientConfig setShared(boolean shared) { + return (CachingWebClientConfig) super.setShared(shared); + } + + @Override + public CachingWebClientConfig setName(String name) { + return (CachingWebClientConfig) super.setName(name); + } + + @Override + public CachingWebClientConfig setFollowAlternativeServices(boolean followAlternativeServices) { + return (CachingWebClientConfig) super.setFollowAlternativeServices(followAlternativeServices); + } + + private static Set buildDefaultStatusCodes() { + Set codes = new HashSet<>(3); + Collections.addAll(codes, 200, 301, 404); + return codes; + } + + private static Set buildDefaultMethods() { + Set methods = new HashSet<>(1); + methods.add(HttpMethod.GET); + return methods; + } +} diff --git a/vertx-web-client/src/main/java/io/vertx/ext/web/client/WebClient.java b/vertx-web-client/src/main/java/io/vertx/ext/web/client/WebClient.java index 3312ae8fe4..00daf8f122 100644 --- a/vertx-web-client/src/main/java/io/vertx/ext/web/client/WebClient.java +++ b/vertx-web-client/src/main/java/io/vertx/ext/web/client/WebClient.java @@ -71,7 +71,7 @@ static WebClient create(Vertx vertx) { * @return the created web client */ static WebClient create(Vertx vertx, WebClientOptions options) { - return new WebClientBase(vertx.createHttpClient(options), options); + return new WebClientBase(vertx.createHttpClient(options), new WebClientConfig(options)); } /** @@ -83,6 +83,29 @@ static WebClient create(Vertx vertx, WebClientOptions options) { * @return the created web client */ static WebClient create(Vertx vertx, WebClientOptions options, PoolOptions poolOptions) { + return new WebClientBase(vertx.createHttpClient(options, poolOptions), new WebClientConfig(options)); + } + + /** + * Create a web client using the provided {@code vertx} instance and default pooling options. + * + * @param vertx the vertx instance + * @param options the Web Client options + * @return the created web client + */ + static WebClient create(Vertx vertx, WebClientConfig options) { + return new WebClientBase(vertx.createHttpClient(options), options); + } + + /** + * Create a web client using the provided {@code vertx} instance. + * + * @param vertx the vertx instance + * @param options the Web Client options + * @param poolOptions the HTTP Client pool options + * @return the created web client + */ + static WebClient create(Vertx vertx, WebClientConfig options, PoolOptions poolOptions) { return new WebClientBase(vertx.createHttpClient(options, poolOptions), options); } @@ -107,9 +130,9 @@ static WebClient wrap(HttpClient httpClient) { * @return the web client */ static WebClient wrap(HttpClient httpClient, WebClientOptions options) { - WebClientOptions actualOptions = new WebClientOptions(((HttpClientInternal) httpClient).options()); - actualOptions.init(options); - return new WebClientBase(httpClient, actualOptions); + WebClientConfig config = new WebClientConfig(((HttpClientInternal) httpClient).config()); + config.init(options); + return new WebClientBase<>(httpClient, config); } /** diff --git a/vertx-web-client/src/main/java/io/vertx/ext/web/client/WebClientConfig.java b/vertx-web-client/src/main/java/io/vertx/ext/web/client/WebClientConfig.java new file mode 100644 index 0000000000..9feb015359 --- /dev/null +++ b/vertx-web-client/src/main/java/io/vertx/ext/web/client/WebClientConfig.java @@ -0,0 +1,261 @@ +/* + * Copyright 2017 Red Hat, Inc. + * + * Red Hat licenses this file to you 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: + * + * http://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 io.vertx.ext.web.client; + +import io.vertx.codegen.annotations.DataObject; +import io.vertx.core.http.*; +import io.vertx.core.internal.VertxInternal; +import io.vertx.core.net.*; +import io.vertx.core.tracing.TracingPolicy; +import io.vertx.uritemplate.ExpandOptions; + +import java.time.Duration; +import java.util.List; + +/** + * @author Thomas Segismont + */ +@DataObject +public class WebClientConfig extends HttpClientConfig { + + private boolean userAgentEnabled = WebClientOptions.DEFAULT_USER_AGENT_ENABLED; + private String userAgent = WebClientOptions.DEFAULT_USER_AGENT; + private boolean followRedirects = WebClientOptions.DEFAULT_FOLLOW_REDIRECTS; + private ExpandOptions templateExpandOptions = WebClientOptions.DEFAULT_EXPAND_OPTIONS; + + public WebClientConfig() { + } + + /** + * Copy constructor. + * + * @param other the options to copy + */ + public WebClientConfig(WebClientConfig other) { + super(other); + + this.userAgentEnabled = other.userAgentEnabled; + this.userAgent = other.userAgent; + this.followRedirects = other.followRedirects; + this.templateExpandOptions = other.templateExpandOptions != null ? new ExpandOptions(other.templateExpandOptions) : null; + } + + /** + * Copy constructor. + * + * @param other the options to copy + */ + public WebClientConfig(HttpClientConfig other) { + super(other); + } + + WebClientConfig(WebClientOptions other) { + super(other); + init(other); + } + + void init(WebClientOptions other) { + this.userAgentEnabled = other.isUserAgentEnabled(); + this.userAgent = other.getUserAgent(); + this.followRedirects = other.isFollowRedirects(); + this.templateExpandOptions = other.getTemplateExpandOptions() != null ? new ExpandOptions(other.getTemplateExpandOptions()) : null; + } + + void init(WebClientConfig other) { + this.userAgentEnabled = other.isUserAgentEnabled(); + this.userAgent = other.getUserAgent(); + this.followRedirects = other.isFollowRedirects(); + this.templateExpandOptions = other.getTemplateExpandOptions() != null ? new ExpandOptions(other.getTemplateExpandOptions()) : null; + } + + /** + * @return true if the Web Client should send a user agent header, false otherwise + */ + public boolean isUserAgentEnabled() { + return userAgentEnabled; + } + + /** + * Sets whether the Web Client should send a user agent header. Defaults to true. + * + * @param userAgentEnabled true to send a user agent header, false otherwise + * @return a reference to this, so the API can be used fluently + */ + public WebClientConfig setUserAgentEnabled(boolean userAgentEnabled) { + this.userAgentEnabled = userAgentEnabled; + return this; + } + + /** + * @return the user agent header string + */ + public String getUserAgent() { + return userAgent; + } + + /** + * Sets the Web Client user agent header. Defaults to Vert.x-WebClient/<version>. + * + * @param userAgent user agent header value + * @return a reference to this, so the API can be used fluently + */ + public WebClientConfig setUserAgent(String userAgent) { + this.userAgent = userAgent; + return this; + } + + /** + * @return the default behavior of the client for following HTTP {@code 30x} redirections + */ + public boolean isFollowRedirects() { + return followRedirects; + } + + /** + * Configure the default behavior of the client to follow HTTP {@code 30x} redirections. + * + * @param followRedirects true when a redirect is followed + * @return a reference to this, so the API can be used fluently + */ + public WebClientConfig setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + return this; + } + + public ExpandOptions getTemplateExpandOptions() { + return templateExpandOptions; + } + + public WebClientConfig setTemplateExpandOptions(ExpandOptions templateExpandOptions) { + this.templateExpandOptions = templateExpandOptions; + return this; + } + + @Override + public WebClientConfig setSslOptions(ClientSSLOptions sslOptions) { + return (WebClientConfig) super.setSslOptions(sslOptions); + } + + @Override + public WebClientConfig setConnectTimeout(Duration connectTimeout) { + return (WebClientConfig) super.setConnectTimeout(connectTimeout); + } + + @Override + public WebClientConfig setMetricsName(String metricsName) { + return (WebClientConfig) super.setMetricsName(metricsName); + } + + @Override + public WebClientConfig setIdleTimeout(Duration idleTimeout) { + return (WebClientConfig) super.setIdleTimeout(idleTimeout); + } + + @Override + public WebClientConfig setReadIdleTimeout(Duration idleTimeout) { + return (WebClientConfig) super.setReadIdleTimeout(idleTimeout); + } + + @Override + public WebClientConfig setWriteIdleTimeout(Duration idleTimeout) { + return (WebClientConfig) super.setWriteIdleTimeout(idleTimeout); + } + + @Override + public WebClientConfig setSsl(boolean ssl) { + return (WebClientConfig) super.setSsl(ssl); + } + + @Override + public WebClientConfig setVersions(List versions) { + return (WebClientConfig) super.setVersions(versions); + } + + @Override + public WebClientConfig setHttp1Config(Http1ClientConfig config) { + return (WebClientConfig) super.setHttp1Config(config); + } + + @Override + public WebClientConfig setHttp2Config(Http2ClientConfig config) { + return (WebClientConfig) super.setHttp2Config(config); + } + + @Override + public WebClientConfig setHttp3Config(Http3ClientConfig config) { + return (WebClientConfig) super.setHttp3Config(config); + } + + @Override + public WebClientConfig setVerifyHost(boolean verifyHost) { + return (WebClientConfig) super.setVerifyHost(verifyHost); + } + + @Override + public WebClientConfig setDecompressionEnabled(boolean decompressionEnabled) { + return (WebClientConfig) super.setDecompressionEnabled(decompressionEnabled); + } + + @Override + public WebClientConfig setDefaultHost(String defaultHost) { + return (WebClientConfig) super.setDefaultHost(defaultHost); + } + + @Override + public WebClientConfig setDefaultPort(int defaultPort) { + return (WebClientConfig) super.setDefaultPort(defaultPort); + } + + @Override + public WebClientConfig setMaxRedirects(int maxRedirects) { + return (WebClientConfig) super.setMaxRedirects(maxRedirects); + } + + @Override + public WebClientConfig setForceSni(boolean forceSni) { + return (WebClientConfig) super.setForceSni(forceSni); + } + + @Override + public WebClientConfig setTracingPolicy(TracingPolicy tracingPolicy) { + return (WebClientConfig) super.setTracingPolicy(tracingPolicy); + } + + @Override + public WebClientConfig setShared(boolean shared) { + return (WebClientConfig) super.setShared(shared); + } + + @Override + public WebClientConfig setName(String name) { + return (WebClientConfig) super.setName(name); + } + + @Override + public WebClientConfig setFollowAlternativeServices(boolean followAlternativeServices) { + return (WebClientConfig) super.setFollowAlternativeServices(followAlternativeServices); + } + + public static String loadUserAgent() { + String userAgent = "Vert.x-WebClient"; + String version = VertxInternal.version(); + if (version.length() > 0) { + userAgent += "/" + version; + } + return userAgent; + } +} diff --git a/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/CachingWebClientImpl.java b/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/CachingWebClientImpl.java index 5ee6b0c205..65bc22bef6 100644 --- a/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/CachingWebClientImpl.java +++ b/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/CachingWebClientImpl.java @@ -15,6 +15,7 @@ */ package io.vertx.ext.web.client.impl; +import io.vertx.ext.web.client.CachingWebClientConfig; import io.vertx.ext.web.client.CachingWebClientOptions; import io.vertx.ext.web.client.WebClient; import io.vertx.ext.web.client.impl.cache.CacheInterceptor; @@ -25,7 +26,7 @@ */ public interface CachingWebClientImpl { - static WebClient wrap(WebClient webClient, CacheStore cacheStore, CachingWebClientOptions options) { + static WebClient wrap(WebClient webClient, CacheStore cacheStore, CachingWebClientConfig options) { WebClientInternal internal = new WebClientBase((WebClientBase) webClient); internal.addInterceptor(new CacheInterceptor(cacheStore, options)); return internal; diff --git a/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/HttpContext.java b/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/HttpContext.java index 41dc4c360e..e496181444 100644 --- a/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/HttpContext.java +++ b/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/HttpContext.java @@ -26,6 +26,7 @@ import io.vertx.core.streams.Pipe; import io.vertx.ext.web.client.HttpRequest; import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClientConfig; import io.vertx.ext.web.client.WebClientOptions; import io.vertx.ext.web.client.spi.CacheStore; import io.vertx.ext.web.codec.spi.BodyStream; @@ -39,7 +40,7 @@ public class HttpContext { private final HttpClientInternal client; - private final WebClientOptions options; + private final WebClientConfig options; private final List>> interceptors; private final ContextInternal context; private final PromiseInternal> promise; @@ -60,7 +61,7 @@ public class HttpContext { private List redirectedLocations = Collections.emptyList(); private CacheStore privateCacheStore; - HttpContext(ContextInternal context, HttpClientInternal client, WebClientOptions options, List>> interceptors, PromiseInternal> promise) { + HttpContext(ContextInternal context, HttpClientInternal client, WebClientConfig options, List>> interceptors, PromiseInternal> promise) { this.context = context; this.client = client; this.options = options; diff --git a/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/WebClientBase.java b/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/WebClientBase.java index 6eeb60800e..fe81ff058e 100644 --- a/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/WebClientBase.java +++ b/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/WebClientBase.java @@ -31,7 +31,7 @@ import io.vertx.core.net.ProxyOptions; import io.vertx.core.net.SocketAddress; import io.vertx.ext.web.client.HttpRequest; -import io.vertx.ext.web.client.WebClientOptions; +import io.vertx.ext.web.client.WebClientConfig; import io.vertx.ext.web.codec.impl.BodyCodecImpl; import io.vertx.uritemplate.ExpandOptions; import io.vertx.uritemplate.UriTemplate; @@ -47,12 +47,12 @@ public class WebClientBase> implements WebClientInternal { final HttpClient client; - final WebClientOptions options; + final WebClientConfig options; final List>> interceptors; - public WebClientBase(HttpClient client, WebClientOptions options) { + public WebClientBase(HttpClient client, WebClientConfig options) { - options = new WebClientOptions(options); + options = new WebClientConfig(options); if (options.getTemplateExpandOptions() == null) { options.setTemplateExpandOptions(new ExpandOptions()); } @@ -64,7 +64,7 @@ public WebClientBase(HttpClient client, WebClientOptions options) { WebClientBase(WebClientBase webClient) { this.client = webClient.client; - this.options = new WebClientOptions(webClient.options); + this.options = new WebClientConfig(webClient.options); this.interceptors = new CopyOnWriteArrayList<>(webClient.interceptors); } @@ -178,7 +178,7 @@ public void close() { client.close(); } - private static MultiMap buildHeaders(WebClientOptions options) { + private static MultiMap buildHeaders(WebClientConfig options) { if (options.isUserAgentEnabled()) { return HttpHeaders.set(HttpHeaders.USER_AGENT, options.getUserAgent()); } else { @@ -186,9 +186,9 @@ private static MultiMap buildHeaders(WebClientOptions options) { } } - private static ProxyOptions buildProxyOptions(WebClientOptions options) { - if (options.getProxyOptions() != null) { - return new ProxyOptions(options.getProxyOptions()); + private static ProxyOptions buildProxyOptions(WebClientConfig options) { + if (options.getTcpConfig().getProxyOptions() != null) { + return new ProxyOptions(options.getTcpConfig().getProxyOptions()); } else { return null; } diff --git a/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/cache/CacheInterceptor.java b/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/cache/CacheInterceptor.java index 9356b9d909..330c07a34e 100644 --- a/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/cache/CacheInterceptor.java +++ b/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/cache/CacheInterceptor.java @@ -21,6 +21,7 @@ import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpHeaders; import io.vertx.core.http.RequestOptions; +import io.vertx.ext.web.client.CachingWebClientConfig; import io.vertx.ext.web.client.CachingWebClientOptions; import io.vertx.ext.web.client.HttpRequest; import io.vertx.ext.web.client.HttpResponse; @@ -45,10 +46,10 @@ public class CacheInterceptor implements Handler> { private static final String IS_CACHE_REVALIDATION = "cache.revalidation"; private final CacheStore publicCacheStore; - private final CachingWebClientOptions options; + private final CachingWebClientConfig options; private final Map> variationsRegistry; - public CacheInterceptor(CacheStore store, CachingWebClientOptions options) { + public CacheInterceptor(CacheStore store, CachingWebClientConfig options) { this.publicCacheStore = store; this.options = options; this.variationsRegistry = new ConcurrentHashMap<>(); diff --git a/vertx-web-client/src/test/java/io/vertx/ext/web/client/tests/Http3Test.java b/vertx-web-client/src/test/java/io/vertx/ext/web/client/tests/Http3Test.java new file mode 100644 index 0000000000..74d3e4d8a5 --- /dev/null +++ b/vertx-web-client/src/test/java/io/vertx/ext/web/client/tests/Http3Test.java @@ -0,0 +1,40 @@ +package io.vertx.ext.web.client.tests; + +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpServer; +import io.vertx.core.http.HttpServerConfig; +import io.vertx.core.http.HttpVersion; +import io.vertx.core.net.ClientSSLOptions; +import io.vertx.core.net.ServerSSLOptions; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.WebClientConfig; +import io.vertx.test.core.LinuxOrOsx; +import io.vertx.test.http.HttpTestBase; +import io.vertx.test.tls.Cert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; + +@RunWith(LinuxOrOsx.class) +public class Http3Test extends HttpTestBase { + + @Test + public void smokeTest() { + HttpServer server = vertx.createHttpServer(new HttpServerConfig() + .setSsl(true) + .setSslOptions(new ServerSSLOptions().setKeyCertOptions(Cert.SERVER_JKS.get())) + .addVersion(HttpVersion.HTTP_3)) + .requestHandler(request -> { + request.response().end(); + }); + server.listen(4043).await(); + WebClient client = WebClient.create(vertx, new WebClientConfig() + .setVersions(List.of(HttpVersion.HTTP_3)) + .setSslOptions(new ClientSSLOptions().setTrustAll(true)) + .setDefaultHost("localhost") + .setDefaultPort(4043)); + HttpResponse response = client.get("/test").send().await(); + } +} diff --git a/vertx-web-client/src/test/java/io/vertx/ext/web/client/tests/WebClientTest.java b/vertx-web-client/src/test/java/io/vertx/ext/web/client/tests/WebClientTest.java index 37efedbfad..7c84a1659e 100644 --- a/vertx-web-client/src/test/java/io/vertx/ext/web/client/tests/WebClientTest.java +++ b/vertx-web-client/src/test/java/io/vertx/ext/web/client/tests/WebClientTest.java @@ -23,10 +23,7 @@ import io.vertx.ext.auth.authentication.TokenCredentials; import io.vertx.ext.auth.authentication.UsernamePasswordCredentials; import io.vertx.ext.auth.htdigest.HtdigestCredentials; -import io.vertx.ext.web.client.HttpRequest; -import io.vertx.ext.web.client.HttpResponse; -import io.vertx.ext.web.client.WebClient; -import io.vertx.ext.web.client.WebClientOptions; +import io.vertx.ext.web.client.*; import io.vertx.ext.web.client.tests.jackson.WineAndCheese; import io.vertx.ext.web.codec.BodyCodec; import io.vertx.ext.web.multipart.MultipartForm; @@ -2306,6 +2303,7 @@ public Future updateSSLOptions(ClientSSLOptions options, boolean force) @Override public VertxInternal vertx(){return null;} @Override public Function> redirectHandler(){return null;} @Override public HttpClientOptions options(){return new HttpClientOptions();} + @Override public HttpClientConfig config() { return new WebClientConfig(); } @Override public EndpointResolverInternal originResolver() {return null;} @Override public EndpointResolverInternal resolver() {return null;} @Override public HttpClientTransport tcpTransport() { return null; }