From 48ead578b0a8e908cde1e79f04234bf6226c29ae Mon Sep 17 00:00:00 2001 From: yawkat Date: Fri, 20 Oct 2023 10:53:03 +0200 Subject: [PATCH 1/4] Add eq/hc for HttpVersionSelection Fixes #9994 --- .../http/client/HttpVersionSelection.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/http-client-core/src/main/java/io/micronaut/http/client/HttpVersionSelection.java b/http-client-core/src/main/java/io/micronaut/http/client/HttpVersionSelection.java index 5a1a243df49..902ecdffd82 100644 --- a/http-client-core/src/main/java/io/micronaut/http/client/HttpVersionSelection.java +++ b/http-client-core/src/main/java/io/micronaut/http/client/HttpVersionSelection.java @@ -23,6 +23,7 @@ import io.micronaut.http.client.annotation.Client; import java.util.Arrays; +import java.util.Objects; /** * This class collects information about HTTP client protocol version settings, such as the @@ -196,6 +197,25 @@ public boolean isHttp3() { return http3; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + HttpVersionSelection that = (HttpVersionSelection) o; + return alpn == that.alpn && http2CipherSuites == that.http2CipherSuites && http3 == that.http3 && plaintextMode == that.plaintextMode && Arrays.equals(alpnSupportedProtocols, that.alpnSupportedProtocols); + } + + @Override + public int hashCode() { + int result = Objects.hash(plaintextMode, alpn, http2CipherSuites, http3); + result = 31 * result + Arrays.hashCode(alpnSupportedProtocols); + return result; + } + /** * The connection mode to use for plaintext (non-TLS) connections. */ From 2b95901a1caa737205ef0b4ce4de1acb2184d4f7 Mon Sep 17 00:00:00 2001 From: yawkat Date: Fri, 20 Oct 2023 11:02:35 +0200 Subject: [PATCH 2/4] add test --- .../client/HttpVersionSelectionSpec.groovy | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 http-client-core/src/test/groovy/io/micronaut/http/client/HttpVersionSelectionSpec.groovy diff --git a/http-client-core/src/test/groovy/io/micronaut/http/client/HttpVersionSelectionSpec.groovy b/http-client-core/src/test/groovy/io/micronaut/http/client/HttpVersionSelectionSpec.groovy new file mode 100644 index 00000000000..2a2b5dbe69a --- /dev/null +++ b/http-client-core/src/test/groovy/io/micronaut/http/client/HttpVersionSelectionSpec.groovy @@ -0,0 +1,24 @@ +package io.micronaut.http.client + + +import io.micronaut.core.annotation.Introspected +import io.micronaut.core.beans.BeanIntrospector +import io.micronaut.http.client.annotation.Client +import spock.lang.Specification + +class HttpVersionSelectionSpec extends Specification { + def 'annotation equals'() { + given: + def introspection = BeanIntrospector.SHARED.findIntrospection(TestClass).get() + def s1 = HttpVersionSelection.forClientAnnotation(introspection) + def s2 = HttpVersionSelection.forClientAnnotation(introspection) + + expect: + s1 == s2 + } + + @Client(alpnModes = ["h2"], plaintextMode = HttpVersionSelection.PlaintextMode.HTTP_1) + @Introspected + static interface TestClass { + } +} From dd872af8bc32f4c3bc2160f14c46b869a617d705 Mon Sep 17 00:00:00 2001 From: yawkat Date: Mon, 23 Oct 2023 08:48:04 +0200 Subject: [PATCH 3/4] fix ClientKey.equals too --- .../http/client/netty/DefaultNettyHttpClientRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-client/src/main/java/io/micronaut/http/client/netty/DefaultNettyHttpClientRegistry.java b/http-client/src/main/java/io/micronaut/http/client/netty/DefaultNettyHttpClientRegistry.java index 251211c77e4..6cbf4b7f633 100644 --- a/http-client/src/main/java/io/micronaut/http/client/netty/DefaultNettyHttpClientRegistry.java +++ b/http-client/src/main/java/io/micronaut/http/client/netty/DefaultNettyHttpClientRegistry.java @@ -590,7 +590,7 @@ public boolean equals(Object o) { return false; } ClientKey clientKey = (ClientKey) o; - return httpVersion == clientKey.httpVersion && + return Objects.equals(httpVersion, clientKey.httpVersion) && Objects.equals(clientId, clientKey.clientId) && Objects.equals(filterAnnotations, clientKey.filterAnnotations) && Objects.equals(path, clientKey.path) && From 99e1a1a832d0389f6deaa35e4df3cd46dc72681d Mon Sep 17 00:00:00 2001 From: yawkat Date: Mon, 23 Oct 2023 11:17:36 +0200 Subject: [PATCH 4/4] test --- .../DefaultNettyHttpClientRegistrySpec.groovy | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/http-client/src/test/groovy/io/micronaut/http/client/netty/DefaultNettyHttpClientRegistrySpec.groovy b/http-client/src/test/groovy/io/micronaut/http/client/netty/DefaultNettyHttpClientRegistrySpec.groovy index 2aa503905ad..8fd9f82efd2 100644 --- a/http-client/src/test/groovy/io/micronaut/http/client/netty/DefaultNettyHttpClientRegistrySpec.groovy +++ b/http-client/src/test/groovy/io/micronaut/http/client/netty/DefaultNettyHttpClientRegistrySpec.groovy @@ -4,8 +4,12 @@ import io.micronaut.context.ApplicationContext import io.micronaut.context.annotation.Requires import io.micronaut.context.event.BeanCreatedEvent import io.micronaut.context.event.BeanCreatedEventListener +import io.micronaut.core.annotation.Introspected +import io.micronaut.core.beans.BeanIntrospector import io.micronaut.http.annotation.Get import io.micronaut.http.client.HttpClient +import io.micronaut.http.client.HttpClientRegistry +import io.micronaut.http.client.HttpVersionSelection import io.micronaut.http.client.annotation.Client import io.netty.channel.Channel import io.netty.util.AttributeKey @@ -75,6 +79,26 @@ class DefaultNettyHttpClientRegistrySpec extends Specification { !customizer.duplicate } + @Issue("https://github.com/micronaut-projects/micronaut-core/pull/9999") + def 'same client with protocol customizations'() { + given: + def ctx = ApplicationContext.run([ + 'spec.name': 'DefaultNettyHttpClientRegistrySpec', + 'micronaut.http.services.test-client2.url': 'https://micronaut.io' + ]) + def registry = ctx.getBean(HttpClientRegistry) + def introspection = BeanIntrospector.SHARED.findIntrospection(DeclarativeClient2).get() + + when: + def client1 = registry.getClient(introspection) + def client2 = registry.getClient(introspection) + then: + client1 == client2 + + cleanup: + ctx.close() + } + @Requires(property = 'spec.name', value = 'DefaultNettyHttpClientRegistrySpec') @Client('test-client') static interface DeclarativeClient { @@ -124,4 +148,10 @@ class DefaultNettyHttpClientRegistrySpec extends Specification { @Client('test-client') HttpClient client; } + + @Requires(property = 'spec.name', value = 'DefaultNettyHttpClientRegistrySpec') + @Introspected + @Client(value = 'test-client2', alpnModes = ["h2"], plaintextMode = HttpVersionSelection.PlaintextMode.HTTP_1) + static interface DeclarativeClient2 { + } }