diff --git a/webclient/api/src/main/java/io/helidon/webclient/api/Proxy.java b/webclient/api/src/main/java/io/helidon/webclient/api/Proxy.java index 31fb60fab3c..ccb7eafb436 100644 --- a/webclient/api/src/main/java/io/helidon/webclient/api/Proxy.java +++ b/webclient/api/src/main/java/io/helidon/webclient/api/Proxy.java @@ -639,8 +639,9 @@ public Proxy build() { * @return updated builder instance */ public Builder config(Config config) { - if (this.type != ProxyType.SYSTEM) { - config.get("type").asString().map(ProxyType::valueOf).ifPresentOrElse(this::type, () -> type(ProxyType.HTTP)); + config.get("type").asString().map(ProxyType::valueOf).ifPresent(this::type); + + if (this.type != ProxyType.SYSTEM && this.type != ProxyType.NONE) { config.get("host").asString().ifPresent(this::host); config.get("port").asInt().ifPresent(this::port); config.get("username").asString().ifPresent(this::username); diff --git a/webclient/http2/src/main/java/io/helidon/webclient/http2/Http2ProtocolConfigProvider.java b/webclient/http2/src/main/java/io/helidon/webclient/http2/Http2ProtocolConfigProvider.java new file mode 100644 index 00000000000..a0e6c66988d --- /dev/null +++ b/webclient/http2/src/main/java/io/helidon/webclient/http2/Http2ProtocolConfigProvider.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * 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.helidon.webclient.http2; + +import io.helidon.common.config.Config; +import io.helidon.webclient.spi.ProtocolConfigProvider; + +/** + * Implementation of protocol config provider. + */ +public class Http2ProtocolConfigProvider implements ProtocolConfigProvider { + /** + * Required to be used by {@link java.util.ServiceLoader}. + * @deprecated do not use directly, use Http1ClientProtocol + */ + public Http2ProtocolConfigProvider() { + } + + @Override + public String configKey() { + return Http2ProtocolProvider.CONFIG_KEY; + } + + @Override + public Http2ClientProtocolConfig create(Config config, String name) { + return Http2ClientProtocolConfig.builder() + .config(config) + .name(name) + .build(); + } +} diff --git a/webclient/http2/src/main/java/module-info.java b/webclient/http2/src/main/java/module-info.java index ef56d1bf7ca..1f8cfa74294 100644 --- a/webclient/http2/src/main/java/module-info.java +++ b/webclient/http2/src/main/java/module-info.java @@ -39,4 +39,6 @@ provides io.helidon.webclient.spi.HttpClientSpiProvider with io.helidon.webclient.http2.Http2ClientSpiProvider; + provides io.helidon.webclient.spi.ProtocolConfigProvider + with io.helidon.webclient.http2.Http2ProtocolConfigProvider; } diff --git a/webclient/tests/http2/src/test/java/io/helidon/webclient/tests/http2/ProtocolConfigTest.java b/webclient/tests/http2/src/test/java/io/helidon/webclient/tests/http2/ProtocolConfigTest.java new file mode 100644 index 00000000000..b46630b4c47 --- /dev/null +++ b/webclient/tests/http2/src/test/java/io/helidon/webclient/tests/http2/ProtocolConfigTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * 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.helidon.webclient.tests.http2; + +import java.util.List; + +import io.helidon.config.Config; +import io.helidon.config.ConfigSources; +import io.helidon.webclient.api.WebClient; +import io.helidon.webclient.http1.Http1ClientProtocolConfig; +import io.helidon.webclient.http2.Http2ClientProtocolConfig; +import io.helidon.webclient.spi.ProtocolConfig; + +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; + +class ProtocolConfigTest { + @Test + void testProtocolConfigWorks() { + Config config = Config.just(ConfigSources.classpath("protocol-config-test.yaml")); + // reproducer for #7802 - h2 protocol not recognized + WebClient client = WebClient.builder() + .config(config.get("client")) + .build(); + assertThat(client, notNullValue()); + + List protocolConfigs = client.prototype() + .protocolConfigs(); + + assertThat(protocolConfigs, hasSize(2)); + + /* + Should be ordered by weight, first HTTP/2 + */ + ProtocolConfig http2Config = protocolConfigs.get(0); + assertThat(http2Config, instanceOf(Http2ClientProtocolConfig.class)); + + ProtocolConfig http1Config = protocolConfigs.get(1); + assertThat(http1Config, instanceOf(Http1ClientProtocolConfig.class)); + + Http2ClientProtocolConfig http2cast = (Http2ClientProtocolConfig) http2Config; + assertThat(http2cast.priorKnowledge(), is(true)); + + Http1ClientProtocolConfig http1cast = (Http1ClientProtocolConfig) http1Config; + assertThat(http1cast.maxHeaderSize(), is(20000)); + assertThat(http1cast.validateRequestHeaders(), is(false)); + } +} diff --git a/webclient/tests/http2/src/test/resources/protocol-config-test.yaml b/webclient/tests/http2/src/test/resources/protocol-config-test.yaml new file mode 100644 index 00000000000..17af7865b63 --- /dev/null +++ b/webclient/tests/http2/src/test/resources/protocol-config-test.yaml @@ -0,0 +1,23 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# 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 +# +# 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. +# + +client: + protocol-configs: + http_1_1: + max-header-size: 20000 + validate-request-headers: false + h2: + prior-knowledge: true \ No newline at end of file diff --git a/webclient/tests/webclient/src/test/java/io/helidon/webclient/tests/ProxySetupTest.java b/webclient/tests/webclient/src/test/java/io/helidon/webclient/tests/ProxySetupTest.java new file mode 100644 index 00000000000..110a3b1d8b2 --- /dev/null +++ b/webclient/tests/webclient/src/test/java/io/helidon/webclient/tests/ProxySetupTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * 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 + * + * 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.helidon.webclient.tests; + +import java.net.InetSocketAddress; + +import io.helidon.config.Config; +import io.helidon.config.ConfigSources; +import io.helidon.webclient.api.Proxy; +import io.helidon.webclient.api.WebClient; +import io.helidon.webclient.api.WebClientConfig; + +import org.junit.jupiter.api.Test; + +import static io.helidon.common.testing.junit5.OptionalMatcher.optionalValue; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +class ProxySetupTest { + private static final Config CONFIG = Config.just(ConfigSources.classpath("proxy-setup-test.yaml")); + + @Test + void testNoProxy() { + WebClient webClient = WebClient.create(WebClientConfig.create(CONFIG.get("no-proxy"))); + Proxy proxy = webClient.prototype().proxy(); + + assertThat(proxy.type(), is(Proxy.ProxyType.NONE)); + } + + @Test + void testSystemProxy() { + WebClient webClient = WebClient.create(WebClientConfig.create(CONFIG.get("system-proxy"))); + Proxy proxy = webClient.prototype().proxy(); + + assertThat(proxy.type(), is(Proxy.ProxyType.SYSTEM)); + } + + @Test + void testHttpProxy() { + WebClient webClient = WebClient.create(WebClientConfig.create(CONFIG.get("http-proxy"))); + Proxy proxy = webClient.prototype().proxy(); + + assertThat(proxy.type(), is(Proxy.ProxyType.HTTP)); + assertThat(proxy.host(), is("proxy.host.example")); + assertThat(proxy.port(), is(9999)); + assertThat(proxy.username(), optionalValue(is("user"))); + assertThat(proxy.password(), optionalValue(is("password".toCharArray()))); + assertThat(proxy.isNoHosts(new InetSocketAddress("www.helidon.io", 80)), is(true)); + assertThat(proxy.isNoHosts(new InetSocketAddress("start.helidon.io", 80)), is(true)); + assertThat(proxy.isNoHosts(new InetSocketAddress("www.oracle.com", 80)), is(false)); + } +} diff --git a/webclient/tests/webclient/src/test/resources/proxy-setup-test.yaml b/webclient/tests/webclient/src/test/resources/proxy-setup-test.yaml new file mode 100644 index 00000000000..547a255f048 --- /dev/null +++ b/webclient/tests/webclient/src/test/resources/proxy-setup-test.yaml @@ -0,0 +1,32 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# 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 +# +# 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. +# + +no-proxy: + proxy: + type: "NONE" + +system-proxy: + proxy: + type: "SYSTEM" + +http-proxy: + proxy: + type: "HTTP" + host: "proxy.host.example" + port: 9999 + username: "user" + password: "password" + no-proxy: ".helidon.io"