From 3ff0f938d7af61efd2b64d273dd2794a7043cf02 Mon Sep 17 00:00:00 2001 From: Jakub Jedlicka Date: Mon, 20 Nov 2023 02:06:47 +0100 Subject: [PATCH 1/2] Add test coverage for grpc GlobalInterceptor method annotation --- .../http/advanced/GrpcClientInterceptors.java | 55 ++++++++++++++++++ .../advanced/GrpcInterceptorsService.java | 23 ++++++++ .../ts/http/advanced/GrpcResource.java | 15 +++++ .../http/advanced/GrpcServerInterceptors.java | 57 +++++++++++++++++++ .../src/main/proto/helloworld.proto | 10 +++- .../ts/http/advanced/BaseHttpAdvancedIT.java | 9 +++ 6 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcClientInterceptors.java create mode 100644 http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcInterceptorsService.java create mode 100644 http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcServerInterceptors.java diff --git a/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcClientInterceptors.java b/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcClientInterceptors.java new file mode 100644 index 000000000..10cc79e47 --- /dev/null +++ b/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcClientInterceptors.java @@ -0,0 +1,55 @@ +package io.quarkus.ts.http.advanced; + +import static io.grpc.Metadata.ASCII_STRING_MARSHALLER; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ForwardingClientCall; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import io.quarkus.grpc.GlobalInterceptor; + +class GrpcClientInterceptors { + public static Metadata.Key CLIENT_METHOD = Metadata.Key.of("client-method-target", ASCII_STRING_MARSHALLER); + public static Metadata.Key CLIENT_CLASS = Metadata.Key.of("client-class-target", ASCII_STRING_MARSHALLER); + + @GlobalInterceptor + @ApplicationScoped + static class ClassTarget extends Base { + } + + static class MethodTarget extends Base { + } + + static class Producer { + @GlobalInterceptor + @Produces + MethodTarget methodTarget() { + return new MethodTarget(); + } + } + + abstract static class Base implements ClientInterceptor { + @Override + public ClientCall interceptCall(MethodDescriptor method, CallOptions options, + Channel next) { + String interceptedTarget = getClass().getName(); + return new ForwardingClientCall.SimpleForwardingClientCall(next.newCall(method, options)) { + @Override + public void start(Listener responseListener, Metadata headers) { + if (interceptedTarget.contains("MethodTarget")) { + headers.put(CLIENT_METHOD, interceptedTarget); + } else if (interceptedTarget.contains("ClassTarget")) { + headers.put(CLIENT_CLASS, interceptedTarget); + } + super.start(responseListener, headers); + } + }; + } + } +} diff --git a/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcInterceptorsService.java b/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcInterceptorsService.java new file mode 100644 index 000000000..a0def8236 --- /dev/null +++ b/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcInterceptorsService.java @@ -0,0 +1,23 @@ +package io.quarkus.ts.http.advanced; + +import io.grpc.stub.StreamObserver; +import io.quarkus.example.HelloReply; +import io.quarkus.example.InterceptedMessageGrpc; +import io.quarkus.example.InterceptedRequest; +import io.quarkus.grpc.GrpcService; + +@GrpcService +public class GrpcInterceptorsService extends InterceptedMessageGrpc.InterceptedMessageImplBase { + + @Override + public void showInterceptedMessage(InterceptedRequest request, StreamObserver responseObserver) { + String serverMethod = GrpcServerInterceptors.SERVER_METHOD.get(); + String serverClass = GrpcServerInterceptors.SERVER_CLASS.get(); + HelloReply reply = HelloReply.newBuilder() + .setMessage("Intercepted client side method passed by server method interceptor is: " + serverMethod + + "\nIntercepted client side class passed by server class interceptor is: " + serverClass) + .build(); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + } +} diff --git a/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcResource.java b/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcResource.java index e1d173f57..864e98983 100644 --- a/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcResource.java +++ b/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcResource.java @@ -6,9 +6,13 @@ import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; import io.quarkus.example.GreeterGrpc; +import io.quarkus.example.HelloReply; import io.quarkus.example.HelloRequest; +import io.quarkus.example.InterceptedMessageGrpc; +import io.quarkus.example.InterceptedRequest; import io.quarkus.grpc.GrpcClient; @Path("/grpc") @@ -18,6 +22,10 @@ public class GrpcResource { @GrpcClient("hello") GreeterGrpc.GreeterBlockingStub client; + @Inject + @GrpcClient("hello") + InterceptedMessageGrpc.InterceptedMessageBlockingStub interceptorsClient; + @GET @Path("/{name}") @Produces(MediaType.TEXT_PLAIN) @@ -25,4 +33,11 @@ public String hello(@PathParam("name") String name) { return client.sayHello(HelloRequest.newBuilder().setName(name).build()).getMessage(); } + @GET + @Path("global/interceptors") + public Response globalInterceptors() { + HelloReply helloReply = interceptorsClient.showInterceptedMessage(InterceptedRequest.newBuilder().build()); + return Response.ok(helloReply.getMessage()).build(); + } + } diff --git a/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcServerInterceptors.java b/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcServerInterceptors.java new file mode 100644 index 000000000..d92a03607 --- /dev/null +++ b/http/http-advanced/src/main/java/io/quarkus/ts/http/advanced/GrpcServerInterceptors.java @@ -0,0 +1,57 @@ +package io.quarkus.ts.http.advanced; + +import static io.quarkus.ts.http.advanced.GrpcClientInterceptors.CLIENT_CLASS; +import static io.quarkus.ts.http.advanced.GrpcClientInterceptors.CLIENT_METHOD; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +import io.grpc.Context; +import io.grpc.Contexts; +import io.grpc.Metadata; +import io.grpc.ServerCall; +import io.grpc.ServerCallHandler; +import io.grpc.ServerInterceptor; +import io.quarkus.grpc.GlobalInterceptor; + +class GrpcServerInterceptors { + + public static Context.Key SERVER_METHOD = Context.key("server-method-target"); + public static Context.Key SERVER_CLASS = Context.key("server-class-target"); + + @GlobalInterceptor + @ApplicationScoped + static class ClassTarget extends Base { + } + + static class MethodTarget extends Base { + } + + static class Producer { + @GlobalInterceptor + @Produces + MethodTarget methodTarget() { + return new MethodTarget(); + } + } + + abstract static class Base implements ServerInterceptor { + @Override + public ServerCall.Listener interceptCall(ServerCall call, Metadata metadata, + ServerCallHandler next) { + Context ctx = null; + String interceptedTarget = getClass().getName(); + // Determine where was grpc call intercepted and put client side intercepted data to Context. + if (interceptedTarget.contains("MethodTarget")) { + ctx = Context.current().withValue(SERVER_METHOD, metadata.get(CLIENT_METHOD)); + ctx.attach(); + } else if (interceptedTarget.contains("ClassTarget")) { + ctx = Context.current().withValue(SERVER_CLASS, metadata.get(CLIENT_CLASS)); + ctx.attach(); + } else { + throw new RuntimeException("Unexpected intercepted class or method by GlobalInterceptor."); + } + return Contexts.interceptCall(ctx, call, metadata, next); + } + } +} diff --git a/http/http-advanced/src/main/proto/helloworld.proto b/http/http-advanced/src/main/proto/helloworld.proto index abcd641d8..ada91ee7d 100644 --- a/http/http-advanced/src/main/proto/helloworld.proto +++ b/http/http-advanced/src/main/proto/helloworld.proto @@ -19,6 +19,11 @@ service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } +// Intercepted message service +service InterceptedMessage { + rpc ShowInterceptedMessage (InterceptedRequest) returns (HelloReply) {} +} + // The request message containing the user's name. message HelloRequest { string name = 1; @@ -27,4 +32,7 @@ message HelloRequest { // The response message containing the greetings message HelloReply { string message = 1; -} \ No newline at end of file +} + +message InterceptedRequest { +} diff --git a/http/http-advanced/src/test/java/io/quarkus/ts/http/advanced/BaseHttpAdvancedIT.java b/http/http-advanced/src/test/java/io/quarkus/ts/http/advanced/BaseHttpAdvancedIT.java index d28e33aef..7fb2b950e 100644 --- a/http/http-advanced/src/test/java/io/quarkus/ts/http/advanced/BaseHttpAdvancedIT.java +++ b/http/http-advanced/src/test/java/io/quarkus/ts/http/advanced/BaseHttpAdvancedIT.java @@ -123,6 +123,15 @@ public void testGrpc() { getApp().given().when().get("/api/grpc/trinity").then().statusCode(HttpStatus.SC_OK).body(is("Hello trinity")); } + @Test + @Tag("QUARKUS-3742") + @DisplayName("GRPC client and server global interceptors test") + public void testGrpcGlobalInterceptors() { + getApp().given().when().get("/api/grpc/global/interceptors").then().statusCode(HttpStatus.SC_OK) + .body(containsString("ClientInterceptors$ClassTarget"), + containsString("ClientInterceptors$MethodTarget")); + } + @Test @DisplayName("Http/2 Server test") public void http2Server() throws InterruptedException, URISyntaxException { From ecf2442028ca5da274101952bcc78dc250424147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vav=C5=99=C3=ADk?= Date: Wed, 22 Nov 2023 00:32:41 +0100 Subject: [PATCH 2/2] Add tag with JIRA ticket to 3.2.9 test coverage --- .../ts/http/advanced/reactive/BaseHttpAdvancedReactiveIT.java | 2 +- .../java/io/quarkus/ts/http/advanced/BaseHttpAdvancedIT.java | 4 ++-- .../security/basic/callback/TestSecurityDisabledTest.java | 2 ++ .../security/basic/callback/TestSecurityEnabledTest.java | 2 ++ .../extended/restclient/TokenPropagationFilterIT.java | 2 ++ .../reactive/extended/TokenPropagationFilterIT.java | 2 ++ 6 files changed, 11 insertions(+), 3 deletions(-) diff --git a/http/http-advanced-reactive/src/test/java/io/quarkus/ts/http/advanced/reactive/BaseHttpAdvancedReactiveIT.java b/http/http-advanced-reactive/src/test/java/io/quarkus/ts/http/advanced/reactive/BaseHttpAdvancedReactiveIT.java index 2452f8585..b9ffc46e4 100644 --- a/http/http-advanced-reactive/src/test/java/io/quarkus/ts/http/advanced/reactive/BaseHttpAdvancedReactiveIT.java +++ b/http/http-advanced-reactive/src/test/java/io/quarkus/ts/http/advanced/reactive/BaseHttpAdvancedReactiveIT.java @@ -428,7 +428,7 @@ public void constraintsExist() throws JsonProcessingException { } @Test - @Tag("https://github.com/quarkusio/quarkus/pull/36664") + @Tag("QUARKUS-3672") public void interceptedTest() { // make server to generate a response so interceptors might intercept it // ignore response, we will read interceptors result later diff --git a/http/http-advanced/src/test/java/io/quarkus/ts/http/advanced/BaseHttpAdvancedIT.java b/http/http-advanced/src/test/java/io/quarkus/ts/http/advanced/BaseHttpAdvancedIT.java index 7fb2b950e..08ff46e81 100644 --- a/http/http-advanced/src/test/java/io/quarkus/ts/http/advanced/BaseHttpAdvancedIT.java +++ b/http/http-advanced/src/test/java/io/quarkus/ts/http/advanced/BaseHttpAdvancedIT.java @@ -255,7 +255,7 @@ public void keepRequestScopeValuesAfterEventPropagation() { } @Test - @Tag("https://github.com/quarkusio/quarkus/issues/36402") + @Tag("QUARKUS-3685") public void sseConnectionTest() { String response = getApp().given().get("/api/sse/client").thenReturn().body().asString(); @@ -265,7 +265,7 @@ public void sseConnectionTest() { } @Test - @Tag("https://github.com/quarkusio/quarkus/pull/36664") + @Tag("QUARKUS-3672") public void interceptedTest() { // make server to generate a response so interceptors might intercept it // ignore response, we will read interceptors result later diff --git a/security/basic/src/test/java/io/quarkus/ts/openshift/security/basic/callback/TestSecurityDisabledTest.java b/security/basic/src/test/java/io/quarkus/ts/openshift/security/basic/callback/TestSecurityDisabledTest.java index d04dba2b3..8bb0dd198 100644 --- a/security/basic/src/test/java/io/quarkus/ts/openshift/security/basic/callback/TestSecurityDisabledTest.java +++ b/security/basic/src/test/java/io/quarkus/ts/openshift/security/basic/callback/TestSecurityDisabledTest.java @@ -4,10 +4,12 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import io.quarkus.test.junit.QuarkusTest; +@Tag("QUARKUS-3674") @QuarkusTest public class TestSecurityDisabledTest extends AbstractSecurityCallbackTest { diff --git a/security/basic/src/test/java/io/quarkus/ts/openshift/security/basic/callback/TestSecurityEnabledTest.java b/security/basic/src/test/java/io/quarkus/ts/openshift/security/basic/callback/TestSecurityEnabledTest.java index 61e969915..b3c658eb0 100644 --- a/security/basic/src/test/java/io/quarkus/ts/openshift/security/basic/callback/TestSecurityEnabledTest.java +++ b/security/basic/src/test/java/io/quarkus/ts/openshift/security/basic/callback/TestSecurityEnabledTest.java @@ -3,11 +3,13 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.security.TestSecurity; +@Tag("QUARKUS-3674") @QuarkusTest public class TestSecurityEnabledTest extends AbstractSecurityCallbackTest { @BeforeAll diff --git a/security/keycloak-oidc-client-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/TokenPropagationFilterIT.java b/security/keycloak-oidc-client-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/TokenPropagationFilterIT.java index d3a751d7a..29b69a965 100644 --- a/security/keycloak-oidc-client-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/TokenPropagationFilterIT.java +++ b/security/keycloak-oidc-client-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/TokenPropagationFilterIT.java @@ -4,10 +4,12 @@ import static org.hamcrest.CoreMatchers.containsString; import org.apache.http.HttpStatus; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import io.quarkus.test.scenarios.QuarkusScenario; +@Tag("QUARKUS-3680") @QuarkusScenario public class TokenPropagationFilterIT extends BaseOidcIT { diff --git a/security/keycloak-oidc-client-reactive-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/TokenPropagationFilterIT.java b/security/keycloak-oidc-client-reactive-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/TokenPropagationFilterIT.java index 6c7a2b980..36648ceb3 100644 --- a/security/keycloak-oidc-client-reactive-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/TokenPropagationFilterIT.java +++ b/security/keycloak-oidc-client-reactive-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/TokenPropagationFilterIT.java @@ -4,10 +4,12 @@ import static org.hamcrest.CoreMatchers.containsString; import org.apache.http.HttpStatus; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import io.quarkus.test.scenarios.QuarkusScenario; +@Tag("QUARKUS-3680") @QuarkusScenario public class TokenPropagationFilterIT extends BaseOidcIT {