├── .editorconfig ├── .github ├── maven-cd-settings.xml ├── maven-ci-settings.xml └── workflows │ ├── ci-4.x.yml │ ├── ci-5.x-stable.yml │ ├── ci-5.x.yml │ ├── ci-matrix-5.x.yml │ ├── ci.yml │ └── deploy.yml ├── .gitignore ├── LICENSE ├── README.md ├── pom.xml ├── vertx-grpc-client ├── pom.xml └── src │ ├── main │ └── java │ │ ├── io │ │ └── vertx │ │ │ └── grpc │ │ │ └── client │ │ │ ├── GrpcClient.java │ │ │ ├── GrpcClientBuilder.java │ │ │ ├── GrpcClientOptions.java │ │ │ ├── GrpcClientRequest.java │ │ │ ├── GrpcClientResponse.java │ │ │ ├── InvalidStatusException.java │ │ │ ├── impl │ │ │ ├── GrpcClientBuilderImpl.java │ │ │ ├── GrpcClientImpl.java │ │ │ ├── GrpcClientRequestImpl.java │ │ │ └── GrpcClientResponseImpl.java │ │ │ └── package-info.java │ │ └── module-info.java │ └── test │ └── java │ ├── io │ └── vertx │ │ └── tests │ │ └── client │ │ ├── ClientMessageEncodingTest.java │ │ ├── ClientRequestTest.java │ │ ├── ClientSideLoadBalancingTest.java │ │ ├── ClientTest.java │ │ ├── ClientTestBase.java │ │ ├── HttpClientWrappingTest.java │ │ └── impl │ │ └── TimeoutValueTest.java │ └── module-info.java ├── vertx-grpc-common ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── io │ │ │ └── vertx │ │ │ │ └── grpc │ │ │ │ └── common │ │ │ │ ├── CodecException.java │ │ │ │ ├── GrpcError.java │ │ │ │ ├── GrpcErrorException.java │ │ │ │ ├── GrpcHeaderNames.java │ │ │ │ ├── GrpcLocal.java │ │ │ │ ├── GrpcMediaType.java │ │ │ │ ├── GrpcMessage.java │ │ │ │ ├── GrpcMessageDecoder.java │ │ │ │ ├── GrpcMessageEncoder.java │ │ │ │ ├── GrpcReadStream.java │ │ │ │ ├── GrpcStatus.java │ │ │ │ ├── GrpcWriteStream.java │ │ │ │ ├── InvalidMessageException.java │ │ │ │ ├── InvalidMessagePayloadException.java │ │ │ │ ├── MessageSizeOverflowException.java │ │ │ │ ├── ServiceMethod.java │ │ │ │ ├── ServiceName.java │ │ │ │ ├── WireFormat.java │ │ │ │ ├── impl │ │ │ │ ├── GrpcMessageDeframer.java │ │ │ │ ├── GrpcMessageImpl.java │ │ │ │ ├── GrpcMethodCall.java │ │ │ │ ├── GrpcReadStreamBase.java │ │ │ │ ├── GrpcRequestLocalRegistration.java │ │ │ │ ├── GrpcWriteStreamBase.java │ │ │ │ ├── Http2GrpcMessageDeframer.java │ │ │ │ ├── ServiceNameImpl.java │ │ │ │ ├── Utils.java │ │ │ │ ├── VertxScheduledExecutorService.java │ │ │ │ └── WriteStreamAdapter.java │ │ │ │ └── package-info.java │ │ └── module-info.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── io.vertx.core.spi.VertxServiceProvider │ └── test │ ├── java │ ├── io │ │ └── vertx │ │ │ └── tests │ │ │ └── common │ │ │ ├── GrpcMethodCallTest.java │ │ │ ├── GrpcTestBase.java │ │ │ ├── ServiceNameTest.java │ │ │ └── grpc │ │ │ └── TestConstants.java │ └── module-info.java │ └── proto │ └── tests.proto ├── vertx-grpc-docs ├── pom.xml └── src │ └── main │ ├── asciidoc │ ├── client.adoc │ ├── index.adoc │ ├── ioclient.adoc │ ├── ioserver.adoc │ ├── iostorage.adoc │ ├── plugin.adoc │ ├── server.adoc │ └── transcoding.adoc │ ├── java │ ├── com │ │ └── google │ │ │ └── api │ │ │ ├── AnnotationsProto.java │ │ │ ├── CustomHttpPattern.java │ │ │ ├── CustomHttpPatternOrBuilder.java │ │ │ ├── Http.java │ │ │ ├── HttpOrBuilder.java │ │ │ ├── HttpProto.java │ │ │ ├── HttpRule.java │ │ │ └── HttpRuleOrBuilder.java │ ├── examples │ │ ├── GrpcClientExamples.java │ │ ├── GrpcContextStorageExamples.java │ │ ├── GrpcIoClientExamples.java │ │ ├── GrpcIoServerExamples.java │ │ ├── GrpcServerExamples.java │ │ ├── GrpcTranscodingExamples.java │ │ └── grpc │ │ │ ├── Docs.java │ │ │ ├── Empty.java │ │ │ ├── EmptyOrBuilder.java │ │ │ ├── Greeter.java │ │ │ ├── GreeterClient.java │ │ │ ├── GreeterGrpc.java │ │ │ ├── GreeterGrpcClient.java │ │ │ ├── GreeterGrpcIo.java │ │ │ ├── GreeterGrpcService.java │ │ │ ├── GreeterGrpcStub.java │ │ │ ├── GreeterService.java │ │ │ ├── HelloReply.java │ │ │ ├── HelloReplyOrBuilder.java │ │ │ ├── HelloRequest.java │ │ │ ├── HelloRequestOrBuilder.java │ │ │ ├── Item.java │ │ │ ├── ItemOrBuilder.java │ │ │ ├── Streaming.java │ │ │ ├── StreamingClient.java │ │ │ ├── StreamingGrpc.java │ │ │ ├── StreamingGrpcClient.java │ │ │ ├── StreamingGrpcIo.java │ │ │ ├── StreamingGrpcService.java │ │ │ ├── StreamingGrpcStub.java │ │ │ ├── StreamingService.java │ │ │ ├── VertxGreeterGrpc.java │ │ │ └── VertxStreamingGrpc.java │ └── io │ │ └── vertx │ │ └── dummy │ │ └── Dummy.java │ └── proto │ ├── docs.proto │ └── google │ └── api │ ├── annotations.proto │ └── http.proto ├── vertx-grpc-health ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── io │ │ │ └── vertx │ │ │ │ └── grpc │ │ │ │ └── health │ │ │ │ ├── HealthService.java │ │ │ │ ├── HealthServiceOptions.java │ │ │ │ ├── handler │ │ │ │ ├── GrpcHealthCheckV1Handler.java │ │ │ │ ├── GrpcHealthListV1Handler.java │ │ │ │ ├── GrpcHealthV1HandlerBase.java │ │ │ │ └── GrpcHealthWatchV1Handler.java │ │ │ │ ├── impl │ │ │ │ └── HealthServiceImpl.java │ │ │ │ └── package-info.java │ │ └── module-info.java │ └── proto │ │ └── health.proto │ └── test │ ├── java │ ├── io │ │ └── vertx │ │ │ └── tests │ │ │ └── health │ │ │ └── HealthServiceTest.java │ └── module-info.java │ └── proto │ └── health.proto ├── vertx-grpc-it ├── pom.xml └── src │ ├── main │ └── java │ │ └── io │ │ └── vertx │ │ └── grpc │ │ └── it │ │ └── Noop.java │ └── test │ ├── java │ └── io │ │ ├── grpc │ │ ├── examples │ │ │ └── package-info.java │ │ └── testing │ │ │ └── integration │ │ │ └── package-info.java │ │ └── vertx │ │ └── grpc │ │ └── it │ │ ├── DeadlineTest.java │ │ ├── JsonWireFormatTest.java │ │ ├── ProtocPluginStubTest.java │ │ ├── ProtocPluginTest.java │ │ ├── ProtocPluginTestBase.java │ │ ├── ProxyTest.java │ │ ├── ProxyTestBase.java │ │ ├── ReflectionTest.java │ │ └── TranscodingTest.java │ └── proto │ ├── empty.proto │ ├── google │ └── api │ │ ├── annotations.proto │ │ └── http.proto │ ├── hello_streaming.proto │ ├── helloworld.proto │ ├── messages.proto │ ├── optionals.proto │ ├── streaming.proto │ └── test.proto ├── vertx-grpc-protoc-plugin2 ├── pom.xml └── src │ └── main │ ├── java │ └── io │ │ └── vertx │ │ └── grpc │ │ └── plugin │ │ ├── VertxGrpcGenerator.java │ │ └── VertxGrpcGeneratorImpl.java │ └── resources │ ├── client.mustache │ ├── contract.mustache │ ├── grpc-client.mustache │ ├── grpc-io.mustache │ ├── grpc-service.mustache │ └── service.mustache ├── vertx-grpc-reflection ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── io │ │ │ └── vertx │ │ │ │ └── grpc │ │ │ │ └── reflection │ │ │ │ ├── GrpcServerReflectionV1Handler.java │ │ │ │ ├── ReflectionService.java │ │ │ │ └── package-info.java │ │ └── module-info.java │ └── proto │ │ └── reflection.proto │ └── test │ ├── java │ ├── io │ │ └── vertx │ │ │ └── tests │ │ │ └── reflection │ │ │ └── ServerReflectionTest.java │ └── module-info.java │ └── proto │ └── reflection.proto ├── vertx-grpc-server ├── pom.xml └── src │ ├── main │ ├── generated │ │ └── io │ │ │ └── vertx │ │ │ └── grpc │ │ │ └── server │ │ │ └── GrpcServerOptionsConverter.java │ └── java │ │ ├── io │ │ └── vertx │ │ │ └── grpc │ │ │ └── server │ │ │ ├── GrpcProtocol.java │ │ │ ├── GrpcServer.java │ │ │ ├── GrpcServerOptions.java │ │ │ ├── GrpcServerRequest.java │ │ │ ├── GrpcServerResponse.java │ │ │ ├── Service.java │ │ │ ├── ServiceBuilder.java │ │ │ ├── StatusException.java │ │ │ ├── impl │ │ │ ├── GrpcHttpInvoker.java │ │ │ ├── GrpcInvocation.java │ │ │ ├── GrpcServerImpl.java │ │ │ ├── GrpcServerRequestImpl.java │ │ │ ├── GrpcServerRequestInspector.java │ │ │ ├── GrpcServerResponseImpl.java │ │ │ ├── Http2GrpcServerRequest.java │ │ │ ├── Http2GrpcServerResponse.java │ │ │ ├── MountPoint.java │ │ │ ├── ServiceBuilderImpl.java │ │ │ ├── WebGrpcServerRequest.java │ │ │ └── WebGrpcServerResponse.java │ │ │ └── package-info.java │ │ └── module-info.java │ └── test │ ├── java │ ├── io │ │ └── vertx │ │ │ └── tests │ │ │ └── server │ │ │ ├── ProtocolSupportTest.java │ │ │ ├── ServerMessageEncodingTest.java │ │ │ ├── ServerRequestTest.java │ │ │ ├── ServerTest.java │ │ │ ├── ServerTestBase.java │ │ │ ├── WorkerTest.java │ │ │ └── web │ │ │ ├── BinaryServerTest.java │ │ │ ├── ServerTestBase.java │ │ │ ├── TextServerTest.java │ │ │ └── interop │ │ │ ├── InteropITest.java │ │ │ └── InteropServer.java │ └── module-info.java │ └── proto │ ├── empty.proto │ ├── messages.proto │ └── web.proto ├── vertx-grpc-transcoding ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── io │ │ │ └── vertx │ │ │ │ └── grpc │ │ │ │ └── transcoding │ │ │ │ ├── MethodTranscodingOptions.java │ │ │ │ ├── TranscodingServiceMethod.java │ │ │ │ ├── impl │ │ │ │ ├── GrpcTranscodingError.java │ │ │ │ ├── MessageWeaver.java │ │ │ │ ├── PathMatcher.java │ │ │ │ ├── PathMatcherBuilder.java │ │ │ │ ├── PathMatcherLookupResult.java │ │ │ │ ├── PathMatcherMethodData.java │ │ │ │ ├── PathMatcherNode.java │ │ │ │ ├── PathMatcherUtility.java │ │ │ │ ├── PercentEncoding.java │ │ │ │ ├── TranscodingGrpcServerRequest.java │ │ │ │ ├── TranscodingGrpcServerResponse.java │ │ │ │ ├── TranscodingInvoker.java │ │ │ │ ├── TranscodingMessageDeframer.java │ │ │ │ ├── TranscodingServiceMethodImpl.java │ │ │ │ └── config │ │ │ │ │ ├── HttpTemplate.java │ │ │ │ │ ├── HttpTemplateParser.java │ │ │ │ │ ├── HttpTemplateVariable.java │ │ │ │ │ └── HttpVariableBinding.java │ │ │ │ └── package-info.java │ │ └── module-info.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── io.vertx.grpc.server.impl.GrpcHttpInvoker │ └── test │ └── java │ ├── io │ └── vertx │ │ └── tests │ │ └── transcoding │ │ ├── HttpTemplateTest.java │ │ ├── MessageWeaverTest.java │ │ ├── PathMatcherTest.java │ │ ├── PathMatcherUtilityTest.java │ │ └── ServerTranscodingTest.java │ └── module-info.java ├── vertx-grpcio-client ├── pom.xml └── src │ ├── main │ └── java │ │ └── io │ │ └── vertx │ │ └── grpcio │ │ └── client │ │ ├── GrpcIoClient.java │ │ ├── GrpcIoClientChannel.java │ │ ├── VertxClientCall.java │ │ ├── impl │ │ ├── GrpcIoClientBuilder.java │ │ └── GrpcIoClientImpl.java │ │ └── package-info.java │ └── test │ └── java │ └── io │ └── vertx │ └── tests │ └── client │ └── ClientBridgeTest.java ├── vertx-grpcio-common ├── pom.xml └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── vertx │ │ │ └── grpcio │ │ │ └── common │ │ │ ├── Dummy.java │ │ │ ├── impl │ │ │ ├── BridgeMessageDecoder.java │ │ │ ├── BridgeMessageEncoder.java │ │ │ ├── ReadStreamAdapter.java │ │ │ ├── Utils.java │ │ │ └── stub │ │ │ │ ├── ClientCalls.java │ │ │ │ ├── GrpcWriteStream.java │ │ │ │ └── StreamObserverReadStream.java │ │ │ └── package-info.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── io.vertx.core.spi.VertxServiceProvider │ └── test │ └── java │ └── io │ └── vertx │ └── tests │ └── common │ └── UtilsTest.java ├── vertx-grpcio-context-storage ├── pom.xml └── src │ ├── main │ ├── java │ │ └── io │ │ │ ├── grpc │ │ │ └── override │ │ │ │ └── ContextStorageOverride.java │ │ │ └── vertx │ │ │ └── grpc │ │ │ └── contextstorage │ │ │ ├── ContextStorageService.java │ │ │ └── GrpcStorage.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── io.vertx.core.spi.VertxServiceProvider │ └── test │ ├── java │ └── io │ │ └── vertx │ │ └── grpc │ │ └── context │ │ └── storage │ │ └── ContextStorageTest.java │ └── proto │ └── helloworld.proto └── vertx-grpcio-server ├── pom.xml └── src ├── main └── java │ └── io │ └── vertx │ └── grpcio │ └── server │ ├── GrpcIoServer.java │ ├── GrpcIoServiceBridge.java │ ├── impl │ ├── GrpcIoServerImpl.java │ ├── GrpcIoServiceBridgeImpl.java │ └── stub │ │ └── ServerCalls.java │ └── package-info.java └── test └── java └── io └── vertx └── tests └── server ├── ReflectionServiceV1Test.java └── ServerBridgeTest.java /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | trim_trailing_whitespace = true 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | [Makefile] 12 | indent_style = tab 13 | 14 | [**/examples/**.java] 15 | # 84 looks like a odd number, however 16 | # it accounts for 4 spaces (class and example method indentation) 17 | max_line_length = 84 18 | -------------------------------------------------------------------------------- /.github/maven-cd-settings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | false 20 | 21 | 22 | 23 | vertx-snapshots-repository 24 | ${env.VERTX_NEXUS_USERNAME} 25 | ${env.VERTX_NEXUS_PASSWORD} 26 | 27 | 28 | 29 | 30 | 31 | google-mirror 32 | 33 | true 34 | 35 | 36 | 37 | google-maven-central 38 | GCS Maven Central mirror EU 39 | https://maven-central.storage-download.googleapis.com/maven2/ 40 | 41 | true 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | google-maven-central 51 | GCS Maven Central mirror 52 | https://maven-central.storage-download.googleapis.com/maven2/ 53 | 54 | true 55 | 56 | 57 | false 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /.github/maven-ci-settings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | false 20 | 21 | 22 | 23 | google-mirror 24 | 25 | true 26 | 27 | 28 | 29 | google-maven-central 30 | GCS Maven Central mirror EU 31 | https://maven-central.storage-download.googleapis.com/maven2/ 32 | 33 | true 34 | 35 | 36 | false 37 | 38 | 39 | 40 | 41 | 42 | google-maven-central 43 | GCS Maven Central mirror 44 | https://maven-central.storage-download.googleapis.com/maven2/ 45 | 46 | true 47 | 48 | 49 | false 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /.github/workflows/ci-4.x.yml: -------------------------------------------------------------------------------- 1 | name: vertx-grpc (4.x) 2 | on: 3 | schedule: 4 | - cron: '0 4 * * *' 5 | jobs: 6 | CI: 7 | strategy: 8 | matrix: 9 | include: 10 | - os: ubuntu-latest 11 | jdk: 8 12 | - os: ubuntu-latest 13 | jdk: 17 14 | uses: ./.github/workflows/ci.yml 15 | with: 16 | branch: 4.x 17 | jdk: ${{ matrix.jdk }} 18 | os: ${{ matrix.os }} 19 | secrets: inherit 20 | Deploy: 21 | if: ${{ github.repository_owner == 'eclipse-vertx' && (github.event_name == 'push' || github.event_name == 'schedule') }} 22 | needs: CI 23 | uses: ./.github/workflows/deploy.yml 24 | with: 25 | branch: 4.x 26 | jdk: 8 27 | secrets: inherit 28 | -------------------------------------------------------------------------------- /.github/workflows/ci-5.x-stable.yml: -------------------------------------------------------------------------------- 1 | name: vertx-grpc (5.x-stable) 2 | on: 3 | push: 4 | branches: 5 | - '5.[0-9]+' 6 | pull_request: 7 | branches: 8 | - '5.[0-9]+' 9 | schedule: 10 | - cron: '0 6 * * *' 11 | jobs: 12 | CI-CD: 13 | uses: ./.github/workflows/ci-matrix-5.x.yml 14 | secrets: inherit 15 | with: 16 | branch: ${{ github.event_name == 'schedule' && vars.VERTX_5_STABLE_BRANCH || github.event.pull_request.head.sha || github.ref_name }} 17 | -------------------------------------------------------------------------------- /.github/workflows/ci-5.x.yml: -------------------------------------------------------------------------------- 1 | name: vertx-grpc (5.x) 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | schedule: 10 | - cron: '0 5 * * *' 11 | jobs: 12 | CI-CD: 13 | uses: ./.github/workflows/ci-matrix-5.x.yml 14 | secrets: inherit 15 | with: 16 | branch: ${{ github.event.pull_request.head.sha || github.ref_name }} 17 | -------------------------------------------------------------------------------- /.github/workflows/ci-matrix-5.x.yml: -------------------------------------------------------------------------------- 1 | name: CI matrix (5.x) 2 | on: 3 | workflow_call: 4 | inputs: 5 | branch: 6 | required: true 7 | type: string 8 | jobs: 9 | CI: 10 | strategy: 11 | matrix: 12 | include: 13 | - os: ubuntu-latest 14 | jdk: 11 15 | - os: ubuntu-latest 16 | jdk: 21 17 | uses: ./.github/workflows/ci.yml 18 | with: 19 | branch: ${{ inputs.branch }} 20 | jdk: ${{ matrix.jdk }} 21 | os: ${{ matrix.os }} 22 | secrets: inherit 23 | gRPC-Web-Interop: 24 | name: Run gRPC-Web interop tests 25 | runs-on: ubuntu-latest 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@v2 29 | with: 30 | ref: ${{ inputs.branch }} 31 | - name: Checkout gRPC-Web 32 | uses: actions/checkout@v2 33 | with: 34 | repository: grpc/grpc-web 35 | ref: master 36 | path: _grpc-web 37 | - name: Install JDK 38 | uses: actions/setup-java@v2 39 | with: 40 | java-version: 11 41 | distribution: temurin 42 | - name: Run tests 43 | run: mvn -s .github/maven-ci-settings.xml -q clean verify -B -pl :vertx-grpc-server -am -Dgrpc-web.repo.path="$GITHUB_WORKSPACE/_grpc-web" 44 | Deploy: 45 | if: ${{ github.repository_owner == 'eclipse-vertx' && (github.event_name == 'push' || github.event_name == 'schedule') }} 46 | needs: CI 47 | uses: ./.github/workflows/deploy.yml 48 | with: 49 | branch: ${{ inputs.branch }} 50 | jdk: 11 51 | secrets: inherit 52 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | workflow_call: 4 | inputs: 5 | branch: 6 | required: true 7 | type: string 8 | jdk: 9 | default: 8 10 | type: string 11 | os: 12 | default: ubuntu-latest 13 | type: string 14 | jobs: 15 | Test: 16 | name: Run tests 17 | runs-on: ${{ inputs.os }} 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v2 21 | with: 22 | ref: ${{ inputs.branch }} 23 | - name: Install JDK 24 | uses: actions/setup-java@v2 25 | with: 26 | java-version: ${{ inputs.jdk }} 27 | distribution: temurin 28 | - name: Install grpcurl (Linux only) 29 | if: runner.os == 'Linux' 30 | run: | 31 | curl -L https://github.com/fullstorydev/grpcurl/releases/download/v1.9.3/grpcurl_1.9.3_linux_x86_64.tar.gz | tar -xz 32 | sudo mv grpcurl /usr/local/bin/ 33 | - name: Run tests 34 | if: runner.os != 'Linux' 35 | run: mvn -s .github/maven-ci-settings.xml -q clean verify -B 36 | - name: Run tests with grpcurl profile (Linux only) 37 | if: runner.os == 'Linux' 38 | run: mvn -s .github/maven-ci-settings.xml -q clean verify -B -Pgrpcurl 39 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | on: 3 | workflow_call: 4 | inputs: 5 | branch: 6 | required: true 7 | type: string 8 | jdk: 9 | default: 8 10 | type: string 11 | jobs: 12 | Deploy: 13 | name: Deploy to OSSRH 14 | runs-on: ubuntu-latest 15 | env: 16 | VERTX_NEXUS_USERNAME: ${{ secrets.VERTX_NEXUS_USERNAME }} 17 | VERTX_NEXUS_PASSWORD: ${{ secrets.VERTX_NEXUS_PASSWORD }} 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v2 21 | with: 22 | ref: ${{ inputs.branch }} 23 | - name: Install JDK 24 | uses: actions/setup-java@v2 25 | with: 26 | java-version: ${{ inputs.jdk }} 27 | distribution: temurin 28 | - name: Get project version 29 | run: echo "PROJECT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:evaluate -Dexpression=project.version -q -DforceStdout | grep -v '\[')" >> $GITHUB_ENV 30 | - name: Maven deploy 31 | if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }} 32 | run: mvn deploy -s .github/maven-cd-settings.xml -DskipTests -B 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vertx 2 | .DS_Store 3 | .gradle 4 | .idea 5 | .classpath 6 | .project 7 | .settings 8 | .yardoc 9 | .yardopts 10 | build 11 | target 12 | out 13 | *.iml 14 | *.ipr 15 | *.iws 16 | test-output 17 | Scratch.java 18 | ScratchTest.java 19 | test-results 20 | test-tmp 21 | *.class 22 | ScratchPad.java 23 | src/main/resources/ext-js/*.js 24 | src/main/java/io/vertx/java/**/*.java 25 | *.swp 26 | .vscode 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status (5.x)](https://github.com/eclipse-vertx/vertx-grpc/actions/workflows/ci-5.x.yml/badge.svg)](https://github.com/eclipse-vertx/vertx-grpc/actions/workflows/ci-5.x.yml) 2 | [![Build Status (4.x)](https://github.com/eclipse-vertx/vertx-grpc/actions/workflows/ci-4.x.yml/badge.svg)](https://github.com/eclipse-vertx/vertx-grpc/actions/workflows/ci-4.x.yml) 3 | 4 | # Vert.x gRPC 5 | 6 | Vert.x gRPC is a gRPC implementation based on Vert.x, it aims to implement an application level API as well as a request/response oriented API 7 | to write gRPC middlewares like reverse proxies. 8 | 9 | # License 10 | 11 | Eclipse Public License - Version 1.0 / Apache License - Version 2.0 12 | -------------------------------------------------------------------------------- /vertx-grpc-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 4.0.0 20 | 21 | 22 | io.vertx 23 | vertx-grpc-aggregator 24 | 5.1.0-SNAPSHOT 25 | ../pom.xml 26 | 27 | 28 | vertx-grpc-client 29 | 30 | Vert.x gRPC Client 31 | 32 | 33 | 34 | io.vertx 35 | vertx-grpc-common 36 | 37 | 38 | 39 | io.vertx 40 | vertx-grpc-common 41 | ${project.version} 42 | test-jar 43 | test 44 | 45 | 46 | io.grpc 47 | grpc-protobuf 48 | test 49 | 50 | 51 | io.grpc 52 | grpc-stub 53 | test 54 | 55 | 56 | 57 | org.bouncycastle 58 | bcpkix-jdk15on 59 | test 60 | 61 | 62 | io.grpc 63 | grpc-netty-shaded 64 | test 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /vertx-grpc-client/src/main/java/io/vertx/grpc/client/GrpcClientBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.client; 12 | 13 | import io.vertx.codegen.annotations.Fluent; 14 | import io.vertx.codegen.annotations.GenIgnore; 15 | import io.vertx.codegen.annotations.VertxGen; 16 | import io.vertx.core.http.HttpClientOptions; 17 | import io.vertx.core.net.AddressResolver; 18 | import io.vertx.core.net.endpoint.LoadBalancer; 19 | 20 | /** 21 | * A builder for {@link GrpcClient}. 22 | * 23 | * @author Julien Viet 24 | */ 25 | @VertxGen 26 | public interface GrpcClientBuilder { 27 | 28 | /** 29 | * Configure the client options. 30 | * @param options the client options 31 | * @return a reference to this, so the API can be used fluently 32 | */ 33 | @Fluent 34 | GrpcClientBuilder with(GrpcClientOptions options); 35 | 36 | /** 37 | * Configure the client HTTP transport options. 38 | * @param transportOptions the client transport options 39 | * @return a reference to this, so the API can be used fluently 40 | */ 41 | @Fluent 42 | GrpcClientBuilder with(HttpClientOptions transportOptions); 43 | 44 | /** 45 | * Configure the client to use a specific address resolver. 46 | * 47 | * @param resolver the address resolver 48 | */ 49 | @GenIgnore({"permitted-type"}) 50 | GrpcClientBuilder withAddressResolver(AddressResolver resolver); 51 | 52 | /** 53 | * Configure the client to use a load balancer. 54 | * 55 | * @param loadBalancer the load balancer 56 | */ 57 | @GenIgnore({"permitted-type"}) 58 | GrpcClientBuilder withLoadBalancer(LoadBalancer loadBalancer); 59 | 60 | /** 61 | * Build and return the client. 62 | * @return the client as configured by this builder 63 | */ 64 | C build(); 65 | 66 | } 67 | -------------------------------------------------------------------------------- /vertx-grpc-client/src/main/java/io/vertx/grpc/client/GrpcClientResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.client; 12 | 13 | import io.vertx.codegen.annotations.CacheReturn; 14 | import io.vertx.codegen.annotations.Fluent; 15 | import io.vertx.codegen.annotations.Nullable; 16 | import io.vertx.codegen.annotations.VertxGen; 17 | import io.vertx.core.Handler; 18 | import io.vertx.core.MultiMap; 19 | import io.vertx.grpc.common.GrpcError; 20 | import io.vertx.grpc.common.GrpcMessage; 21 | import io.vertx.grpc.common.GrpcReadStream; 22 | import io.vertx.grpc.common.GrpcStatus; 23 | 24 | /** 25 | * A response from a gRPC server. 26 | * 27 | * You can set a {@link #messageHandler(Handler)} to receive {@link GrpcMessage} and a {@link #endHandler(Handler)} to be notified 28 | * of the end of the response. 29 | * 30 | */ 31 | @VertxGen 32 | public interface GrpcClientResponse extends GrpcReadStream { 33 | 34 | /** 35 | * @return the gRPC status or {@code null} when the status has not yet been received 36 | */ 37 | @CacheReturn 38 | GrpcStatus status(); 39 | 40 | /** 41 | * @return the gRPC status message of {@code null} when the status has not yet been received or not transmitted 42 | */ 43 | @CacheReturn 44 | String statusMessage(); 45 | 46 | /** 47 | * @return the {@link MultiMap} to write metadata trailers 48 | */ 49 | MultiMap trailers(); 50 | 51 | @Override 52 | @Fluent 53 | GrpcClientResponse messageHandler(@Nullable Handler handler); 54 | 55 | @Override 56 | @Fluent 57 | GrpcClientResponse errorHandler(@Nullable Handler handler); 58 | 59 | @Override 60 | GrpcClientResponse exceptionHandler(@Nullable Handler handler); 61 | 62 | @Override 63 | GrpcClientResponse handler(@Nullable Handler handler); 64 | 65 | @Override 66 | GrpcClientResponse endHandler(@Nullable Handler handler); 67 | 68 | @Override 69 | GrpcClientResponse pause(); 70 | 71 | @Override 72 | GrpcClientResponse resume(); 73 | 74 | @Override 75 | GrpcClientResponse fetch(long amount); 76 | } 77 | -------------------------------------------------------------------------------- /vertx-grpc-client/src/main/java/io/vertx/grpc/client/InvalidStatusException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.client; 12 | 13 | import io.vertx.core.VertxException; 14 | import io.vertx.grpc.common.GrpcStatus; 15 | 16 | /** 17 | * Denotes a failure due to an invalid status. 18 | */ 19 | public final class InvalidStatusException extends VertxException { 20 | 21 | private final GrpcStatus expected; 22 | private final GrpcStatus actual; 23 | 24 | public InvalidStatusException(GrpcStatus expected, GrpcStatus actual) { 25 | super("Invalid status: actual:" + actual.name() + ", expected:" + expected.name()); 26 | this.expected = expected; 27 | this.actual = actual; 28 | } 29 | 30 | /** 31 | * @return the expected status 32 | */ 33 | public GrpcStatus expectedStatus() { 34 | return expected; 35 | } 36 | 37 | /** 38 | * @return the actual status 39 | */ 40 | public GrpcStatus actualStatus() { 41 | return actual; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /vertx-grpc-client/src/main/java/io/vertx/grpc/client/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | @ModuleGen(name = "vertx-grpc-client", groupPackage = "io.vertx") 12 | package io.vertx.grpc.client; 13 | 14 | import io.vertx.codegen.annotations.ModuleGen; 15 | -------------------------------------------------------------------------------- /vertx-grpc-client/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module io.vertx.grpc.client{ 2 | requires io.netty.buffer; 3 | requires io.netty.codec.http; 4 | requires io.netty.codec; 5 | requires io.vertx.core.logging; 6 | requires io.vertx.core; 7 | requires io.vertx.grpc.common; 8 | requires static io.vertx.docgen; 9 | requires static io.vertx.codegen.api; 10 | requires static io.vertx.codegen.json; 11 | requires com.google.protobuf; 12 | requires com.google.common; 13 | exports io.vertx.grpc.client; 14 | exports io.vertx.grpc.client.impl to io.vertx.tests.client; 15 | } 16 | -------------------------------------------------------------------------------- /vertx-grpc-client/src/test/java/io/vertx/tests/client/HttpClientWrappingTest.java: -------------------------------------------------------------------------------- 1 | package io.vertx.tests.client; 2 | 3 | import io.grpc.*; 4 | import io.grpc.stub.ServerCallStreamObserver; 5 | import io.grpc.stub.StreamObserver; 6 | import io.vertx.core.http.HttpClientAgent; 7 | import io.vertx.core.http.HttpClientOptions; 8 | import io.vertx.core.http.HttpConnectOptions; 9 | import io.vertx.core.http.HttpVersion; 10 | import io.vertx.ext.unit.Async; 11 | import io.vertx.ext.unit.TestContext; 12 | import io.vertx.grpc.client.GrpcClient; 13 | import io.vertx.grpc.common.GrpcReadStream; 14 | import io.vertx.tests.common.grpc.Reply; 15 | import io.vertx.tests.common.grpc.Request; 16 | import io.vertx.tests.common.grpc.TestServiceGrpc; 17 | import org.junit.Test; 18 | 19 | import java.io.IOException; 20 | 21 | public class HttpClientWrappingTest extends ClientTestBase { 22 | 23 | @Test 24 | public void testUnary(TestContext should) throws IOException { 25 | TestServiceGrpc.TestServiceImplBase called = new TestServiceGrpc.TestServiceImplBase() { 26 | @Override 27 | public void unary(Request request, StreamObserver plainResponseObserver) { 28 | ServerCallStreamObserver responseObserver = 29 | (ServerCallStreamObserver) plainResponseObserver; 30 | responseObserver.onNext(Reply.newBuilder().setMessage("Hello " + request.getName()).build()); 31 | responseObserver.onCompleted(); 32 | } 33 | }; 34 | startServer(called, ServerBuilder.forPort(port)); 35 | Async async = should.async(); 36 | HttpClientAgent agent = vertx.createHttpClient(new HttpClientOptions() 37 | .setProtocolVersion(HttpVersion.HTTP_2) 38 | .setHttp2ClearTextUpgrade(false)); 39 | 40 | // Connect -> request -> response -> close 41 | agent.connect(new HttpConnectOptions() 42 | .setPort(port) 43 | .setHost("localhost") 44 | ).compose(conn -> { 45 | GrpcClient client = GrpcClient.client(vertx, conn); 46 | return client.request(UNARY) 47 | .compose(req -> { 48 | req.end(Request.newBuilder().setName("Julien").build()); 49 | return req.response().compose(GrpcReadStream::last); 50 | }).eventually(client::close); 51 | }).onComplete(should.asyncAssertSuccess(reply -> { 52 | should.assertEquals("Hello Julien", reply.getMessage()); 53 | async.complete(); 54 | })); 55 | async.await(20_000); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /vertx-grpc-client/src/test/java/io/vertx/tests/client/impl/TimeoutValueTest.java: -------------------------------------------------------------------------------- 1 | package io.vertx.tests.client.impl; 2 | 3 | import io.vertx.grpc.client.impl.GrpcClientRequestImpl; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class TimeoutValueTest { 12 | 13 | private static final long MAX = 99_999_999; 14 | 15 | @Test 16 | public void testValue() { 17 | Assert.assertEquals(MAX + "n", GrpcClientRequestImpl.toTimeoutHeader(MAX, TimeUnit.NANOSECONDS)); 18 | assertEquals((MAX + 1) / 1000 + "u", GrpcClientRequestImpl.toTimeoutHeader(MAX + 1, TimeUnit.NANOSECONDS)); 19 | assertEquals(MAX + "u", GrpcClientRequestImpl.toTimeoutHeader(MAX, TimeUnit.MICROSECONDS)); 20 | assertEquals((MAX + 1) / 1000 + "m", GrpcClientRequestImpl.toTimeoutHeader(MAX + 1, TimeUnit.MICROSECONDS)); 21 | assertEquals(MAX + "m", GrpcClientRequestImpl.toTimeoutHeader(MAX, TimeUnit.MILLISECONDS)); 22 | assertEquals((MAX + 1) / 1000 + "S", GrpcClientRequestImpl.toTimeoutHeader(MAX + 1, TimeUnit.MILLISECONDS)); 23 | assertEquals(MAX + "S", GrpcClientRequestImpl.toTimeoutHeader(MAX, TimeUnit.SECONDS)); 24 | assertEquals((MAX + 1) / 60 + "M", GrpcClientRequestImpl.toTimeoutHeader(MAX + 1, TimeUnit.SECONDS)); 25 | assertEquals(MAX + "M", GrpcClientRequestImpl.toTimeoutHeader(MAX, TimeUnit.MINUTES)); 26 | assertEquals((MAX + 1) / 60 + "H", GrpcClientRequestImpl.toTimeoutHeader(MAX + 1, TimeUnit.MINUTES)); 27 | assertEquals(MAX + "H", GrpcClientRequestImpl.toTimeoutHeader(MAX, TimeUnit.HOURS)); 28 | assertEquals(null, GrpcClientRequestImpl.toTimeoutHeader(MAX + 1, TimeUnit.HOURS)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vertx-grpc-client/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | open module io.vertx.tests.client { 2 | requires io.grpc; 3 | requires io.grpc.stub; 4 | requires io.grpc.util; 5 | requires io.grpc.protobuf; 6 | requires io.vertx.core; 7 | requires io.vertx.grpc.client; 8 | requires io.vertx.grpc.common; 9 | requires io.vertx.testing.unit; 10 | requires io.vertx.tests.common; 11 | requires junit; 12 | requires com.google.protobuf; 13 | requires com.google.common; 14 | } 15 | -------------------------------------------------------------------------------- /vertx-grpc-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 4.0.0 20 | 21 | 22 | io.vertx 23 | vertx-grpc-aggregator 24 | 5.1.0-SNAPSHOT 25 | ../pom.xml 26 | 27 | 28 | vertx-grpc-common 29 | 30 | Vert.x gRPC Common 31 | 32 | 33 | 34 | io.vertx 35 | vertx-core 36 | 37 | 38 | com.google.protobuf 39 | protobuf-java 40 | 41 | 42 | com.google.protobuf 43 | protobuf-java-util 44 | 45 | 46 | 47 | io.grpc 48 | grpc-protobuf 49 | test 50 | 51 | 52 | io.grpc 53 | grpc-stub 54 | test 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | org.xolstice.maven.plugins 63 | protobuf-maven-plugin 64 | 65 | 66 | test-compile 67 | 68 | test-compile 69 | test-compile-custom 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/CodecException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | /** 14 | * An encoding/decoding exception. 15 | */ 16 | public class CodecException extends RuntimeException { 17 | 18 | public CodecException() { 19 | } 20 | 21 | public CodecException(String message) { 22 | super(message); 23 | } 24 | 25 | public CodecException(String message, Throwable cause) { 26 | super(message, cause); 27 | } 28 | 29 | public CodecException(Throwable cause) { 30 | super(cause); 31 | } 32 | 33 | public CodecException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 34 | super(message, cause, enableSuppression, writableStackTrace); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/GrpcError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | import io.vertx.codegen.annotations.VertxGen; 14 | 15 | /** 16 | * gRPC error, a subset of {@link GrpcStatus} elements. 17 | *
    18 | *
  • The list of codes is taken from spec.
19 | *
  • And the list of http/2 codes is taken from spec. 20 | * 21 | */ 22 | @VertxGen 23 | public enum GrpcError { 24 | 25 | INTERNAL(GrpcStatus.INTERNAL, 0x02), 26 | 27 | UNAVAILABLE(GrpcStatus.UNAVAILABLE, 0x07), 28 | 29 | CANCELLED(GrpcStatus.CANCELLED, 0x08), 30 | 31 | RESOURCE_EXHAUSTED(GrpcStatus.RESOURCE_EXHAUSTED, 0x0B), 32 | 33 | PERMISSION_DENIED(GrpcStatus.PERMISSION_DENIED, 0x0C); 34 | 35 | public final GrpcStatus status; 36 | public final long http2ResetCode; 37 | 38 | GrpcError(GrpcStatus status, long http2ResetCode) { 39 | this.status = status; 40 | this.http2ResetCode = http2ResetCode; 41 | } 42 | 43 | /** 44 | * Map the HTTP/2 code to the gRPC error. 45 | * 46 | * @param code the HTTP/2 code 47 | * @return the gRPC error or {@code null} when none applies 48 | */ 49 | public static GrpcError mapHttp2ErrorCode(long code) { 50 | switch ((int)code) { 51 | case 0x00: 52 | // NO_ERROR 53 | case 0x01: 54 | // PROTOCOL_ERROR 55 | case 0x02: 56 | // INTERNAL_ERROR 57 | case 0x03: 58 | // FLOW_CONTROL_ERROR 59 | case 0x04: 60 | // FRAME_SIZE_ERROR 61 | case 0x06: 62 | // FRAME_SIZE_ERROR 63 | case 0x09: 64 | // COMPRESSION_ERROR 65 | return GrpcError.INTERNAL; 66 | case 0x07: 67 | // REFUSED_STREAM 68 | return GrpcError.UNAVAILABLE; 69 | case 0x0A: 70 | // CONNECT_ERROR 71 | case 0x08: 72 | // CANCEL 73 | return GrpcError.CANCELLED; 74 | case 0x0B: 75 | // ENHANCE_YOUR_CALM 76 | return GrpcError.RESOURCE_EXHAUSTED; 77 | case 0x0C: 78 | // INADEQUATE_SECURITY 79 | return GrpcError.PERMISSION_DENIED; 80 | default: 81 | // STREAM_CLOSED; 82 | // HTTP_1_1_REQUIRED 83 | return null; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/GrpcErrorException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | import io.vertx.core.VertxException; 14 | import io.vertx.core.http.StreamResetException; 15 | 16 | /** 17 | * Thrown when a failure happens before the response, and it could be interpreted to a gRPC failure, e.g. 18 | * in practice it means an HTTP/2 stream reset mapped to a gRPC code according to the 19 | * spec. 20 | */ 21 | public final class GrpcErrorException extends VertxException { 22 | 23 | public static GrpcErrorException create(StreamResetException sre) { 24 | GrpcError error = GrpcError.mapHttp2ErrorCode(sre.getCode()); 25 | GrpcStatus status = GrpcStatus.UNKNOWN; 26 | if (error != null) { 27 | status = error.status; 28 | } 29 | return new GrpcErrorException(error, status); 30 | } 31 | 32 | private final GrpcError error; 33 | private final GrpcStatus status; 34 | 35 | public GrpcErrorException(GrpcError error, GrpcStatus status) { 36 | super("gRPC error status: " + status.name()); 37 | 38 | this.error = error; 39 | this.status = status; 40 | } 41 | 42 | public GrpcError error() { 43 | return error; 44 | } 45 | 46 | public GrpcStatus status() { 47 | return status; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/GrpcHeaderNames.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.common; 2 | 3 | import io.netty.util.AsciiString; 4 | 5 | /** 6 | * Header names used by gRPC. 7 | * 8 | * @see gRPC HTTP/2 requests 9 | */ 10 | public final class GrpcHeaderNames { 11 | 12 | /** 13 | * Header for specifying the timeout for a gRPC call. 14 | * Format is an integer followed by a time unit: 'S', 'M', 'H' (seconds, minutes, hours). 15 | * Example: "10S" for a 10-second timeout. 16 | */ 17 | public static final AsciiString GRPC_TIMEOUT = AsciiString.cached("grpc-timeout"); 18 | 19 | /** 20 | * Header indicating the compression algorithm used for the message payload. 21 | * Common values include "gzip", "snappy", and "identity" (no compression). 22 | */ 23 | public static final AsciiString GRPC_ENCODING = AsciiString.cached("grpc-encoding"); 24 | 25 | /** 26 | * Header specifying which compression algorithms the client or server supports. 27 | * Multiple algorithms can be specified as a comma-separated list. 28 | */ 29 | public static final AsciiString GRPC_ACCEPT_ENCODING = AsciiString.cached("grpc-accept-encoding"); 30 | 31 | /** 32 | * Header specifying the type of the message being transmitted. 33 | */ 34 | public static final AsciiString GRPC_MESSAGE_TYPE = AsciiString.cached("grpc-message-type"); 35 | 36 | /** 37 | * Header containing the status code of a gRPC response. 38 | * This is used to communicate error conditions from the server to the client. 39 | * Values are defined in the gRPC protocol specification. 40 | */ 41 | public static final AsciiString GRPC_STATUS = AsciiString.cached("grpc-status"); 42 | 43 | /** 44 | * Header containing the error message when a request fails. 45 | * The message is percent-encoded. 46 | */ 47 | public static final AsciiString GRPC_MESSAGE = AsciiString.cached("grpc-message"); 48 | 49 | /** 50 | * Header containing additional error details when a request fails. 51 | * The value is base64 encoded. 52 | */ 53 | public static final AsciiString GRPC_STATUS_DETAILS_BIN = AsciiString.cached("grpc-status-details-bin"); 54 | } 55 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/GrpcLocal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | import io.vertx.core.Context; 14 | import io.vertx.core.Vertx; 15 | import io.vertx.core.internal.ContextInternal; 16 | import io.vertx.core.spi.context.storage.ContextLocal; 17 | import io.vertx.grpc.common.impl.GrpcRequestLocalRegistration; 18 | 19 | import java.time.Instant; 20 | 21 | /** 22 | * gRPC request local propagation. 23 | */ 24 | public class GrpcLocal { 25 | 26 | /** 27 | * Context local key. 28 | */ 29 | public static final ContextLocal CONTEXT_LOCAL_KEY = GrpcRequestLocalRegistration.CONTEXT_LOCAL; 30 | 31 | private final long deadlineMillis; 32 | private Instant deadline; 33 | 34 | public GrpcLocal(long deadlineMillis) { 35 | this.deadlineMillis = deadlineMillis; 36 | } 37 | 38 | /** 39 | * @return the local associated with the given {@code context} 40 | */ 41 | public static GrpcLocal of(Context context) { 42 | return ((ContextInternal)context).getLocal(CONTEXT_LOCAL_KEY); 43 | } 44 | 45 | /** 46 | * @return the current request local or {@code null} 47 | */ 48 | public static GrpcLocal current() { 49 | Context ctx = Vertx.currentContext(); 50 | return ctx != null ? of(ctx) : null; 51 | } 52 | 53 | /** 54 | * @return the deadline 55 | */ 56 | public Instant deadline() { 57 | if (deadline == null) { 58 | deadline = Instant.ofEpochMilli(deadlineMillis); 59 | } 60 | return deadline; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/GrpcMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | import io.vertx.codegen.annotations.DataObject; 14 | import io.vertx.codegen.annotations.VertxGen; 15 | import io.vertx.core.buffer.Buffer; 16 | import io.vertx.grpc.common.impl.GrpcMessageImpl; 17 | 18 | /** 19 | * A generic gRPC message 20 | * 21 | * @author Julien Viet 22 | */ 23 | @DataObject 24 | public interface GrpcMessage { 25 | 26 | /** 27 | * @return a new message 28 | */ 29 | static GrpcMessage message(String encoding, WireFormat format, Buffer payload) { 30 | return new GrpcMessageImpl(encoding, format, payload); 31 | } 32 | 33 | /** 34 | * @return a new message in proto format 35 | */ 36 | static GrpcMessage message(String encoding, Buffer payload) { 37 | return new GrpcMessageImpl(encoding, WireFormat.PROTOBUF, payload); 38 | } 39 | 40 | /** 41 | * @return the message encoding 42 | */ 43 | String encoding(); 44 | 45 | /** 46 | * @return the message format 47 | */ 48 | WireFormat format(); 49 | 50 | /** 51 | * @return the message payload, usually in Protobuf format encoded in the {@link #encoding()} format 52 | */ 53 | Buffer payload(); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/GrpcReadStream.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.common; 2 | 3 | import io.vertx.codegen.annotations.Fluent; 4 | import io.vertx.codegen.annotations.GenIgnore; 5 | import io.vertx.codegen.annotations.Nullable; 6 | import io.vertx.codegen.annotations.VertxGen; 7 | import io.vertx.core.Future; 8 | import io.vertx.core.Handler; 9 | import io.vertx.core.MultiMap; 10 | import io.vertx.core.streams.ReadStream; 11 | 12 | @VertxGen 13 | public interface GrpcReadStream extends ReadStream { 14 | 15 | /** 16 | * @return the {@link MultiMap} to read metadata headers 17 | */ 18 | MultiMap headers(); 19 | 20 | /** 21 | * @return the stream encoding, e.g. {@code identity} or {@code gzip} 22 | */ 23 | String encoding(); 24 | 25 | /** 26 | * @return the message format, e.g. {@code proto} or {@code json} 27 | */ 28 | WireFormat format(); 29 | 30 | /** 31 | * Set a handler to be notified with incoming encoded messages. The {@code handler} is 32 | * responsible for fully decoding incoming messages, including compression. 33 | * 34 | * @param handler the message handler 35 | * @return a reference to this, so the API can be used fluently 36 | */ 37 | @Fluent 38 | GrpcReadStream messageHandler(@Nullable Handler handler); 39 | 40 | /** 41 | * Set a message handler that is reported with invalid message errors. 42 | * 43 | *

    Warning: setting this handler overwrite the default handler which takes appropriate measure 44 | * when an invalid message is encountered such as cancelling the stream. This handler should be set 45 | * when control over invalid messages is required.

    46 | * 47 | * @param handler the invalid message handler 48 | * @return a reference to this, so the API can be used fluently 49 | */ 50 | @GenIgnore(GenIgnore.PERMITTED_TYPE) 51 | GrpcReadStream invalidMessageHandler(@Nullable Handler handler); 52 | 53 | /** 54 | * Set a handler to be notified with gRPC errors. 55 | * 56 | * @param handler the error handler 57 | * @return a reference to this, so the API can be used fluently 58 | */ 59 | @Fluent 60 | GrpcReadStream errorHandler(@Nullable Handler handler); 61 | 62 | @Override 63 | GrpcReadStream exceptionHandler(@Nullable Handler handler); 64 | 65 | @Override 66 | GrpcReadStream handler(@Nullable Handler handler); 67 | 68 | @Override 69 | GrpcReadStream pause(); 70 | 71 | @Override 72 | GrpcReadStream resume(); 73 | 74 | @Override 75 | GrpcReadStream fetch(long l); 76 | 77 | @Override 78 | GrpcReadStream endHandler(@Nullable Handler handler); 79 | 80 | /** 81 | * @return the last element of the stream 82 | */ 83 | Future last(); 84 | 85 | /** 86 | * @return a future signaling when the response has been fully received successfully or failed 87 | */ 88 | Future end(); 89 | 90 | } 91 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/GrpcStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | import io.netty.util.collection.IntObjectHashMap; 14 | import io.netty.util.collection.IntObjectMap; 15 | import io.vertx.codegen.annotations.VertxGen; 16 | 17 | /** 18 | * gRPC statuses. 19 | * 20 | * @author Julien Viet 21 | */ 22 | @VertxGen 23 | public enum GrpcStatus { 24 | 25 | OK(0), 26 | 27 | CANCELLED(1), 28 | 29 | UNKNOWN(2), 30 | 31 | INVALID_ARGUMENT(3), 32 | 33 | DEADLINE_EXCEEDED(4), 34 | 35 | NOT_FOUND(5), 36 | 37 | ALREADY_EXISTS(6), 38 | 39 | PERMISSION_DENIED(7), 40 | 41 | RESOURCE_EXHAUSTED(8), 42 | 43 | FAILED_PRECONDITION(9), 44 | 45 | ABORTED(10), 46 | 47 | OUT_OF_RANGE(11), 48 | 49 | UNIMPLEMENTED(12), 50 | 51 | INTERNAL(13), 52 | 53 | UNAVAILABLE(14), 54 | 55 | DATA_LOSS(15), 56 | 57 | UNAUTHENTICATED(16); 58 | 59 | private static final IntObjectMap codeMap = new IntObjectHashMap<>(); 60 | 61 | public static GrpcStatus valueOf(int code) { 62 | return codeMap.get(code); 63 | } 64 | 65 | static { 66 | for (GrpcStatus status : values()) { 67 | codeMap.put(status.code, status); 68 | } 69 | } 70 | 71 | public final int code; 72 | private final String string; 73 | 74 | GrpcStatus(int code) { 75 | this.code = code; 76 | this.string = Integer.toString(code); 77 | } 78 | 79 | 80 | @Override 81 | public String toString() { 82 | return string; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/GrpcWriteStream.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.common; 2 | 3 | import io.vertx.codegen.annotations.Fluent; 4 | import io.vertx.codegen.annotations.Nullable; 5 | import io.vertx.codegen.annotations.VertxGen; 6 | import io.vertx.core.Future; 7 | import io.vertx.core.Handler; 8 | import io.vertx.core.MultiMap; 9 | import io.vertx.core.streams.WriteStream; 10 | 11 | @VertxGen 12 | public interface GrpcWriteStream extends WriteStream { 13 | 14 | /** 15 | * @return the {@link MultiMap} to reader metadata headers 16 | */ 17 | MultiMap headers(); 18 | 19 | /** 20 | * Set the stream encoding, e.g. {@code identity} or {@code gzip}. 21 | * 22 | * It must be called before sending any message, otherwise {@code identity} will be used. 23 | * 24 | * @param encoding the target message encoding 25 | * @return a reference to this, so the API can be used fluently 26 | */ 27 | @Fluent 28 | GrpcWriteStream encoding(String encoding); 29 | 30 | /** 31 | * Set the stream format, e.g. {@code proto} or {@code json}. 32 | * 33 | * It must be called before sending any message, otherwise {@code proto} will be used. 34 | * 35 | * @param format the message format 36 | * @return a reference to this, so the API can be used fluently 37 | */ 38 | @Fluent 39 | GrpcWriteStream format(WireFormat format); 40 | 41 | @Override 42 | GrpcWriteStream exceptionHandler(@Nullable Handler handler); 43 | 44 | @Override 45 | GrpcWriteStream setWriteQueueMaxSize(int i); 46 | 47 | @Override 48 | GrpcWriteStream drainHandler(@Nullable Handler handler); 49 | 50 | /** 51 | * Write an encoded gRPC message. 52 | * 53 | * @param message the message 54 | * @return a future completed with the result 55 | */ 56 | Future writeMessage(GrpcMessage message); 57 | 58 | /** 59 | * End the stream with an encoded gRPC message. 60 | * 61 | * @param message the message 62 | * @return a future completed with the result 63 | */ 64 | Future endMessage(GrpcMessage message); 65 | 66 | /** 67 | * Cancel the stream. 68 | */ 69 | void cancel(); 70 | 71 | } 72 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/InvalidMessageException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | import io.vertx.core.VertxException; 14 | 15 | /** 16 | * Signals an invalid message. 17 | * 18 | * @author Julien Viet 19 | */ 20 | public abstract class InvalidMessageException extends VertxException { 21 | 22 | InvalidMessageException() { 23 | super((String) null, true); 24 | } 25 | 26 | InvalidMessageException(Throwable cause) { 27 | super(cause, true); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/InvalidMessagePayloadException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | /** 14 | * Signals a message with an invalid payload, i.e. that could not be decoded by the protobuf codec. 15 | * 16 | * @author Julien Viet 17 | */ 18 | public final class InvalidMessagePayloadException extends InvalidMessageException { 19 | 20 | private GrpcMessage message; 21 | 22 | public InvalidMessagePayloadException(GrpcMessage message, Throwable cause) { 23 | super(cause); 24 | this.message = message; 25 | } 26 | 27 | /** 28 | * @return the invalid message that could not be decoded. 29 | */ 30 | public GrpcMessage message() { 31 | return message; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/MessageSizeOverflowException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | /** 14 | * Signals a message that is longer than the maximum configured size. 15 | * 16 | * @author Julien Viet 17 | */ 18 | public final class MessageSizeOverflowException extends InvalidMessageException { 19 | 20 | private final long messageSize; 21 | 22 | public MessageSizeOverflowException(long messageSize) { 23 | this.messageSize = messageSize; 24 | } 25 | 26 | public long messageSize() { 27 | return messageSize; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/ServiceMethod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | import io.vertx.codegen.annotations.GenIgnore; 14 | 15 | /** 16 | * Bundle all the bits required to call or bind a grpc service method. 17 | */ 18 | @GenIgnore(GenIgnore.PERMITTED_TYPE) 19 | public interface ServiceMethod { 20 | 21 | static ServiceMethod client(ServiceName serviceName, String methodName, GrpcMessageEncoder encoder, GrpcMessageDecoder decoder) { 22 | return new ServiceMethod<>() { 23 | @Override 24 | public ServiceName serviceName() { 25 | return serviceName; 26 | } 27 | @Override 28 | public String methodName() { 29 | return methodName; 30 | } 31 | @Override 32 | public GrpcMessageDecoder decoder() { 33 | return decoder; 34 | } 35 | @Override 36 | public GrpcMessageEncoder encoder() { 37 | return encoder; 38 | } 39 | }; 40 | } 41 | 42 | static ServiceMethod server(ServiceName serviceName, String methodName, GrpcMessageEncoder encoder, GrpcMessageDecoder decoder) { 43 | return new ServiceMethod<>() { 44 | @Override 45 | public ServiceName serviceName() { 46 | return serviceName; 47 | } 48 | @Override 49 | public String methodName() { 50 | return methodName; 51 | } 52 | @Override 53 | public GrpcMessageDecoder decoder() { 54 | return decoder; 55 | } 56 | @Override 57 | public GrpcMessageEncoder encoder() { 58 | return encoder; 59 | } 60 | }; 61 | } 62 | 63 | /** 64 | * @return the service name. 65 | */ 66 | ServiceName serviceName(); 67 | 68 | /** 69 | * @return the method name 70 | */ 71 | String methodName(); 72 | 73 | default String fullMethodName() { 74 | return serviceName().fullyQualifiedName() + "/" + methodName(); 75 | } 76 | 77 | /** 78 | * @return the message decoder 79 | */ 80 | GrpcMessageDecoder decoder(); 81 | 82 | /** 83 | * @return the message encoder 84 | */ 85 | GrpcMessageEncoder encoder(); 86 | 87 | } 88 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/ServiceName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | import io.vertx.codegen.annotations.CacheReturn; 14 | import io.vertx.codegen.annotations.DataObject; 15 | import io.vertx.codegen.annotations.VertxGen; 16 | import io.vertx.grpc.common.impl.ServiceNameImpl; 17 | 18 | /** 19 | * A gRPC service name. 20 | */ 21 | @DataObject 22 | public interface ServiceName { 23 | 24 | /** 25 | * Create a service name from its fully qualified name, e.g {@code com.examples.MyService} 26 | * 27 | * @param fqn the fully qualified service name 28 | * @return the service name 29 | */ 30 | static ServiceName create(String fqn) { 31 | return new ServiceNameImpl(fqn); 32 | } 33 | 34 | /** 35 | * Create a service name from its package name and name 36 | * 37 | * @param packageName the package name 38 | * @param name the name 39 | * @return the service name 40 | */ 41 | static ServiceName create(String packageName, String name) { 42 | return new ServiceNameImpl(packageName, name); 43 | } 44 | 45 | /** 46 | * @return the name 47 | */ 48 | String name(); 49 | 50 | /** 51 | * @return the package name 52 | */ 53 | String packageName(); 54 | 55 | /** 56 | * @return the fully qualified name 57 | */ 58 | String fullyQualifiedName(); 59 | 60 | /** 61 | * Create the path of a given {@code method} to call. 62 | * @param method the method 63 | * @return the path, e.g {@code /com.examples.MyService/MyMethod} 64 | */ 65 | String pathOf(String method); 66 | 67 | } 68 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/WireFormat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common; 12 | 13 | /** 14 | * The serialization format as an enum. 15 | */ 16 | public enum WireFormat { 17 | 18 | /** 19 | * Protobuf wire format. 20 | */ 21 | PROTOBUF("proto"), 22 | 23 | /** 24 | * JSON wire format. 25 | */ 26 | JSON("json"); 27 | 28 | final String name; 29 | 30 | WireFormat(String name) { 31 | this.name = name; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/impl/GrpcMessageDeframer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common.impl; 12 | 13 | import io.vertx.core.buffer.Buffer; 14 | 15 | /** 16 | * State machine that handles slicing the input to a message. 17 | */ 18 | public interface GrpcMessageDeframer { 19 | 20 | void maxMessageSize(long maxMessageSize); 21 | 22 | void update(Buffer chunk); 23 | 24 | void end(); 25 | 26 | Object next(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/impl/GrpcMessageImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common.impl; 12 | 13 | import io.vertx.core.buffer.Buffer; 14 | import io.vertx.core.internal.buffer.BufferInternal; 15 | import io.vertx.grpc.common.WireFormat; 16 | import io.vertx.grpc.common.GrpcMessage; 17 | 18 | import java.util.Objects; 19 | 20 | public class GrpcMessageImpl implements GrpcMessage { 21 | 22 | private final String encoding; 23 | private final WireFormat format; 24 | private final Buffer payload; 25 | 26 | public GrpcMessageImpl(String encoding, WireFormat format, Buffer payload) { 27 | this.encoding = Objects.requireNonNull(encoding); 28 | this.format = Objects.requireNonNull(format); 29 | this.payload = Objects.requireNonNull(payload); 30 | } 31 | 32 | @Override 33 | public String encoding() { 34 | return encoding; 35 | } 36 | 37 | @Override 38 | public WireFormat format() { 39 | return format; 40 | } 41 | 42 | @Override 43 | public Buffer payload() { 44 | return payload; 45 | } 46 | 47 | public static Buffer encode(GrpcMessage message) { 48 | return encode(message, false); 49 | } 50 | 51 | /** 52 | * Encode a {@link GrpcMessage}. 53 | * 54 | * @param message the message 55 | * @param trailer whether this message is a gRPC-Web trailer 56 | * @return the encoded message 57 | */ 58 | public static BufferInternal encode(GrpcMessage message, boolean trailer) { 59 | boolean compressed = !message.encoding().equals("identity"); 60 | return encode(message.payload(), compressed, trailer); 61 | } 62 | 63 | /** 64 | * Encode a gRPC message; 65 | * 66 | * @param payload the message 67 | * @param compressed wether the message is compressed 68 | * @param trailer whether this message is a gRPC-Web trailer 69 | * @return the encoded message 70 | */ 71 | public static BufferInternal encode(Buffer payload, boolean compressed, boolean trailer) { 72 | int len = payload.length(); 73 | BufferInternal encoded = BufferInternal.buffer(5 + len); 74 | encoded.appendByte((byte) ((trailer ? 0x80 : 0x00) | (compressed ? 0x01 : 0x00))); 75 | encoded.appendInt(len); 76 | encoded.appendBuffer(payload); 77 | return encoded; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/impl/GrpcMethodCall.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common.impl; 12 | 13 | import io.vertx.grpc.common.ServiceName; 14 | 15 | public class GrpcMethodCall { 16 | 17 | private String path; 18 | private String fullMethodName; 19 | private ServiceName serviceName; 20 | private String methodName; 21 | 22 | public GrpcMethodCall(String path) { 23 | this.path = path; 24 | } 25 | 26 | public String fullMethodName() { 27 | if (fullMethodName == null) { 28 | fullMethodName = path.substring(1); 29 | } 30 | return fullMethodName; 31 | } 32 | 33 | public ServiceName serviceName() { 34 | if (serviceName == null) { 35 | int idx1 = path.lastIndexOf('.'); 36 | int idx2 = path.lastIndexOf('/'); 37 | if (idx1 < 1) { 38 | serviceName = ServiceName.create("", path.substring(1, idx2)); 39 | } else { 40 | serviceName = ServiceName.create(path.substring(1, idx1), path.substring(idx1 + 1, idx2)); 41 | } 42 | } 43 | return serviceName; 44 | } 45 | 46 | public String methodName() { 47 | if (methodName == null) { 48 | int idx = path.lastIndexOf('/'); 49 | methodName = path.substring(idx + 1); 50 | } 51 | return methodName; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/impl/GrpcRequestLocalRegistration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common.impl; 12 | 13 | import io.vertx.core.internal.VertxBootstrap; 14 | import io.vertx.core.spi.VertxServiceProvider; 15 | import io.vertx.core.spi.context.storage.ContextLocal; 16 | import io.vertx.grpc.common.GrpcLocal; 17 | 18 | /** 19 | * Registration of context local for {@link GrpcLocal}. 20 | */ 21 | public class GrpcRequestLocalRegistration implements VertxServiceProvider { 22 | 23 | public static final ContextLocal CONTEXT_LOCAL = ContextLocal.registerLocal(GrpcLocal.class); 24 | 25 | @Override 26 | public void init(VertxBootstrap builder) { 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/impl/ServiceNameImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common.impl; 12 | 13 | import io.vertx.grpc.common.ServiceName; 14 | 15 | import java.util.Objects; 16 | 17 | public class ServiceNameImpl implements ServiceName { 18 | 19 | private String name; 20 | private String packageName; 21 | private String fullyQualifiedName; 22 | 23 | public ServiceNameImpl(String packageName, String name) { 24 | this.name = name; 25 | this.packageName = packageName; 26 | } 27 | 28 | public ServiceNameImpl(String fullyQualifiedName) { 29 | this.fullyQualifiedName = fullyQualifiedName; 30 | } 31 | 32 | @Override 33 | public String name() { 34 | if (name == null) { 35 | int idx = fullyQualifiedName.lastIndexOf('.'); 36 | name = fullyQualifiedName.substring(idx + 1); 37 | } 38 | return name; 39 | } 40 | 41 | @Override 42 | public String packageName() { 43 | if (packageName == null) { 44 | if (fullyQualifiedName == null) { 45 | return ""; 46 | } 47 | int idx = fullyQualifiedName.lastIndexOf('.'); 48 | if (idx < 0) { 49 | packageName = ""; 50 | } else { 51 | packageName = fullyQualifiedName.substring(0, idx); 52 | } 53 | } 54 | return packageName; 55 | } 56 | 57 | @Override 58 | public String fullyQualifiedName() { 59 | if (fullyQualifiedName == null) { 60 | if (packageName == null || packageName.isEmpty()) { 61 | fullyQualifiedName = name; 62 | } else { 63 | fullyQualifiedName = packageName + '.' + name; 64 | } 65 | } 66 | return fullyQualifiedName; 67 | } 68 | 69 | @Override 70 | public String pathOf(String method) { 71 | if (fullyQualifiedName != null) { 72 | return '/' + fullyQualifiedName + '/' + method; 73 | } else { 74 | if (packageName == null || packageName.isEmpty()) { 75 | return '/' + name + '/' + method; 76 | } else { 77 | return '/' + packageName + '.' + name + '/' + method; 78 | } 79 | } 80 | } 81 | 82 | @Override 83 | public boolean equals(Object o) { 84 | if (this == o) { 85 | return true; 86 | } 87 | if (o == null || getClass() != o.getClass()) { 88 | return false; 89 | } 90 | ServiceNameImpl that = (ServiceNameImpl) o; 91 | return Objects.equals(fullyQualifiedName(), that.fullyQualifiedName()); 92 | } 93 | 94 | @Override 95 | public int hashCode() { 96 | return Objects.hash(fullyQualifiedName()); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/impl/VertxScheduledExecutorService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common.impl; 12 | 13 | import io.netty.channel.EventLoop; 14 | import io.vertx.core.internal.ContextInternal; 15 | 16 | import java.util.List; 17 | import java.util.concurrent.*; 18 | 19 | /** 20 | * Minimalistic scheduler for gRPC deadlines. 21 | */ 22 | public class VertxScheduledExecutorService extends AbstractExecutorService implements ScheduledExecutorService { 23 | 24 | private final ContextInternal vertxContext; 25 | 26 | public VertxScheduledExecutorService(io.vertx.core.Context vertxContext) { 27 | this.vertxContext = (ContextInternal) vertxContext; 28 | } 29 | 30 | @Override 31 | public void shutdown() { 32 | } 33 | 34 | @Override 35 | public List shutdownNow() { 36 | return null; 37 | } 38 | 39 | @Override 40 | public boolean isShutdown() { 41 | return false; 42 | } 43 | 44 | @Override 45 | public boolean isTerminated() { 46 | return false; 47 | } 48 | 49 | @Override 50 | public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { 51 | return false; 52 | } 53 | 54 | @Override 55 | public void execute(Runnable command) { 56 | } 57 | 58 | @Override 59 | public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { 60 | EventLoop el = vertxContext.nettyEventLoop(); 61 | return el.schedule(() -> { 62 | vertxContext.dispatch(command); 63 | }, delay, unit); 64 | } 65 | 66 | @Override 67 | public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { 68 | throw new UnsupportedOperationException(); 69 | } 70 | 71 | @Override 72 | public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { 73 | throw new UnsupportedOperationException(); 74 | } 75 | 76 | @Override 77 | public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { 78 | throw new UnsupportedOperationException(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/impl/WriteStreamAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.common.impl; 12 | 13 | import io.vertx.grpc.common.GrpcWriteStream; 14 | import io.vertx.grpc.common.GrpcMessageEncoder; 15 | import io.vertx.grpc.common.WireFormat; 16 | 17 | /** 18 | * An adapter between gRPC and Vert.x back-pressure. 19 | */ 20 | public class WriteStreamAdapter { 21 | 22 | private WireFormat wireFormat; 23 | private GrpcWriteStream stream; 24 | private boolean ready; 25 | private GrpcMessageEncoder encoder; 26 | 27 | /** 28 | * Override this method to call gRPC {@code onReady} 29 | */ 30 | protected void handleReady() { 31 | } 32 | 33 | public final void init(GrpcWriteStream stream, WireFormat wireFormat, GrpcMessageEncoder encoder) { 34 | synchronized (this) { 35 | this.stream = stream; 36 | this.wireFormat = wireFormat; 37 | this.encoder = encoder; 38 | } 39 | stream.drainHandler(v -> { 40 | checkReady(); 41 | }); 42 | checkReady(); 43 | } 44 | 45 | public final synchronized boolean isReady() { 46 | return ready; 47 | } 48 | 49 | public final void write(T msg) { 50 | stream.writeMessage(encoder.encode(msg, wireFormat)); 51 | synchronized (this) { 52 | ready = !stream.writeQueueFull(); 53 | } 54 | } 55 | 56 | private void checkReady() { 57 | synchronized (this) { 58 | if (ready || stream.writeQueueFull()) { 59 | return; 60 | } 61 | ready = true; 62 | } 63 | handleReady(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/io/vertx/grpc/common/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | @ModuleGen(name = "vertx-grpc-common", groupPackage = "io.vertx") 12 | package io.vertx.grpc.common; 13 | 14 | import io.vertx.codegen.annotations.ModuleGen; 15 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module io.vertx.grpc.common { 2 | 3 | requires static io.vertx.codegen.api; 4 | 5 | requires io.vertx.core; 6 | requires io.netty.common; 7 | requires io.netty.buffer; 8 | requires io.netty.codec; 9 | requires io.netty.codec.compression; 10 | requires io.netty.transport; 11 | requires com.google.protobuf; 12 | requires com.google.protobuf.util; 13 | 14 | exports io.vertx.grpc.common; 15 | exports io.vertx.grpc.common.impl to io.vertx.tests.common, io.vertx.grpc.server, io.vertx.grpc.client, io.vertx.grpc.transcoding, io.vertx.tests.server, io.vertx.tests.client; 16 | 17 | provides io.vertx.core.spi.VertxServiceProvider with io.vertx.grpc.common.impl.GrpcRequestLocalRegistration; 18 | } 19 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/main/resources/META-INF/services/io.vertx.core.spi.VertxServiceProvider: -------------------------------------------------------------------------------- 1 | io.vertx.grpc.common.impl.GrpcRequestLocalRegistration 2 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/test/java/io/vertx/tests/common/GrpcMethodCallTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.tests.common; 12 | 13 | import io.vertx.grpc.common.impl.GrpcMethodCall; 14 | import org.junit.Before; 15 | import org.junit.Test; 16 | 17 | import static org.junit.Assert.assertEquals; 18 | 19 | public class GrpcMethodCallTest { 20 | 21 | private GrpcMethodCall grpcMethodCall0; 22 | private GrpcMethodCall grpcMethodCall1; 23 | private GrpcMethodCall grpcMethodCall2; 24 | 25 | @Before 26 | public void setUp() { 27 | grpcMethodCall0 = new GrpcMethodCall("/com.examples.MyService/Method1"); 28 | grpcMethodCall1 = new GrpcMethodCall("/com.examples/MyService/Method2"); 29 | grpcMethodCall2 = new GrpcMethodCall("/MyService/Method3"); 30 | } 31 | 32 | @Test 33 | public void testFullMethodName() { 34 | assertEquals("com.examples.MyService/Method1", grpcMethodCall0.fullMethodName()); 35 | assertEquals("com.examples/MyService/Method2", grpcMethodCall1.fullMethodName()); 36 | assertEquals("MyService/Method3", grpcMethodCall2.fullMethodName()); 37 | } 38 | 39 | @Test 40 | public void testServiceName() { 41 | assertEquals("com.examples.MyService", grpcMethodCall0.serviceName().fullyQualifiedName()); 42 | assertEquals("com.examples/MyService", grpcMethodCall1.serviceName().fullyQualifiedName()); 43 | assertEquals("MyService", grpcMethodCall2.serviceName().fullyQualifiedName()); 44 | } 45 | 46 | @Test 47 | public void testMethodName() { 48 | assertEquals("Method1", grpcMethodCall0.methodName()); 49 | assertEquals("Method2", grpcMethodCall1.methodName()); 50 | assertEquals("Method3", grpcMethodCall2.methodName()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/test/java/io/vertx/tests/common/GrpcTestBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.tests.common; 12 | 13 | import io.vertx.core.Vertx; 14 | import io.vertx.core.VertxOptions; 15 | import io.vertx.core.buffer.Buffer; 16 | import io.vertx.ext.unit.TestContext; 17 | import io.vertx.ext.unit.junit.VertxUnitRunner; 18 | import org.junit.After; 19 | import org.junit.Before; 20 | import org.junit.runner.RunWith; 21 | 22 | import java.io.ByteArrayInputStream; 23 | import java.io.ByteArrayOutputStream; 24 | import java.io.IOException; 25 | import java.util.zip.GZIPInputStream; 26 | import java.util.zip.GZIPOutputStream; 27 | 28 | /** 29 | * @author Julien Viet 30 | */ 31 | @RunWith(VertxUnitRunner.class) 32 | public abstract class GrpcTestBase { 33 | 34 | /* The port on which the server should run */ 35 | protected Vertx vertx; 36 | protected int port; 37 | 38 | @Before 39 | public void setUp(TestContext should) { 40 | port = 8080; 41 | vertx = Vertx.vertx(); 42 | } 43 | 44 | @After 45 | public void tearDown(TestContext should) { 46 | vertx.close().onComplete(should.asyncAssertSuccess()); 47 | } 48 | 49 | public static Buffer unzip(Buffer buffer) { 50 | Buffer ret = Buffer.buffer(); 51 | try { 52 | GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(buffer.getBytes())); 53 | byte[] tmp = new byte[256]; 54 | for (int l = 0;l != -1;l = in.read(tmp)) { 55 | ret.appendBytes(tmp, 0, l); 56 | } 57 | } catch (IOException e) { 58 | e.printStackTrace(); 59 | } 60 | return ret; 61 | } 62 | 63 | public static Buffer zip(Buffer buffer) { 64 | ByteArrayOutputStream ret = new ByteArrayOutputStream(); 65 | try { 66 | GZIPOutputStream in = new GZIPOutputStream(ret); 67 | in.write(buffer.getBytes()); 68 | in.flush(); 69 | in.close(); 70 | } catch (IOException e) { 71 | e.printStackTrace(); 72 | } 73 | return Buffer.buffer(ret.toByteArray()); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/test/java/io/vertx/tests/common/grpc/TestConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.tests.common.grpc; 12 | 13 | import io.vertx.grpc.common.GrpcMessageDecoder; 14 | import io.vertx.grpc.common.GrpcMessageEncoder; 15 | import io.vertx.grpc.common.ServiceName; 16 | 17 | import static io.vertx.grpc.common.GrpcMessageDecoder.decoder; 18 | import static io.vertx.grpc.common.GrpcMessageEncoder.encoder; 19 | 20 | public final class TestConstants { 21 | 22 | public static final ServiceName TEST_SERVICE = ServiceName.create("io.vertx.tests.common.grpc.tests.TestService"); 23 | public static final GrpcMessageEncoder EMPTY_ENC = encoder(); 24 | public static final GrpcMessageDecoder EMPTY_DEC = decoder(Empty.newBuilder()); 25 | public static final GrpcMessageEncoder REQUEST_ENC = encoder(); 26 | public static final GrpcMessageDecoder REQUEST_DEC = decoder(Request.newBuilder()); 27 | public static final GrpcMessageEncoder REPLY_ENC = encoder(); 28 | public static final GrpcMessageDecoder REPLY_DEC = decoder(Reply.newBuilder()); 29 | 30 | private TestConstants() { 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | open module io.vertx.tests.common { 2 | requires io.vertx.core; 3 | requires io.vertx.grpc.common; 4 | requires io.vertx.testing.unit; 5 | requires junit; 6 | requires com.google.common; 7 | requires com.google.protobuf; 8 | requires io.grpc; 9 | requires io.grpc.protobuf; 10 | requires io.grpc.stub; 11 | exports io.vertx.tests.common; 12 | exports io.vertx.tests.common.grpc; 13 | } 14 | -------------------------------------------------------------------------------- /vertx-grpc-common/src/test/proto/tests.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution.fs 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | syntax = "proto3"; 31 | 32 | option java_multiple_files = true; 33 | option java_package = "io.vertx.tests.common.grpc"; 34 | 35 | // grpc.testing ? 36 | package io.vertx.tests.common.grpc.tests; 37 | 38 | // Interface exported by the server. 39 | service TestService { 40 | rpc Unary (Request) returns (Reply) {} 41 | rpc Source(Empty) returns (stream Reply) {} 42 | rpc Sink(stream Request) returns (Empty) {} 43 | rpc Pipe(stream Request) returns (stream Reply) {} 44 | } 45 | 46 | message Empty { 47 | } 48 | 49 | message Request { 50 | string name = 1; 51 | } 52 | 53 | message Reply { 54 | string message = 1; 55 | } 56 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/asciidoc/index.adoc: -------------------------------------------------------------------------------- 1 | = Vert.x gRPC 2 | 3 | The best description of gRPC can be seen at wikipedia. 4 | 5 | [quote, Wikipedia] 6 | ____ 7 | gRPC is an open source remote procedure call (RPC) system initially developed at Google. It uses HTTP/2 for 8 | transport, Protocol Buffers as the interface description language, and provides features such as authentication, 9 | bidirectional streaming and flow control, blocking or nonblocking bindings, and cancellation and timeouts. It 10 | generates cross-platform client and server bindings for many languages. 11 | ____ 12 | 13 | Vert.x gRPC is a module that will align the programming style of gRPC with Vert.x style. As a user of this 14 | module you will be more familiar with the code style using Vert.x Streams and Futures while benefiting from all the 15 | benefits of gRPC. 16 | 17 | For more information related to gRPC please consult the official documentation site http://www.grpc.io/. 18 | 19 | Vert.x gRPC is split into several parts: 20 | 21 | - Vert.x gRPC Server 22 | - Vert.x gRPC Client 23 | - Vert.x gRPC/IO Server 24 | - Vert.x gRPC/IO Client 25 | - Vert.x gRPC/IO Context Storage 26 | 27 | include::plugin.adoc[] 28 | 29 | include::server.adoc[] 30 | 31 | include::client.adoc[] 32 | 33 | include::transcoding.adoc[] 34 | 35 | include::ioserver.adoc[] 36 | 37 | include::ioclient.adoc[] 38 | 39 | include::iostorage.adoc[] 40 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/asciidoc/ioclient.adoc: -------------------------------------------------------------------------------- 1 | == Vert.x gRPC/IO Client 2 | 3 | Vert.x gRPC/IO Client extends the Vert.x gRPC client with _grpc-java_ integration. 4 | 5 | This client provides a generated stub approach with a gRPC Channel 6 | 7 | === Using Vert.x gRPC/IO Client 8 | 9 | To use Vert.x gRPC/IO Client, add the following dependency to the _dependencies_ section of your build descriptor: 10 | 11 | * Maven (in your `pom.xml`): 12 | 13 | [source,xml,subs="+attributes"] 14 | ---- 15 | 16 | io.vertx 17 | vertx-grpcio-client 18 | ${maven.version} 19 | 20 | ---- 21 | 22 | * Gradle (in your `build.gradle` file): 23 | 24 | [source,groovy,subs="+attributes"] 25 | ---- 26 | dependencies { 27 | compile 'io.vertx:vertx-grpcio-client:${maven.version}' 28 | } 29 | ---- 30 | 31 | === gRPC channel 32 | 33 | The Vert.x gRPC/IO Client provides a gRPC channel to use with _grpc-java_ generated client classes. 34 | 35 | [source,java] 36 | ---- 37 | {@link examples.GrpcIoClientExamples#stub} 38 | ---- 39 | 40 | Timeout and deadlines are supported through the usual gRPC API. 41 | 42 | [source,java] 43 | ---- 44 | {@link examples.GrpcIoClientExamples#stubWithDeadline} 45 | ---- 46 | 47 | Deadline are cascaded, e.g. when the current `io.grpc.Context` carries a deadline and the stub has no explicit deadline 48 | set, the client automatically inherits the implicit deadline. Such deadline can be set when using a stub within a gRPC server 49 | call. 50 | 51 | === Idiomatic gRPC/IO client 52 | 53 | The <> supports the generation of gRPC/IO client code: 54 | 55 | - `examples/Greeter.java` 56 | - `examples/GreeterClient.java` 57 | - `examples/GreeterGrpcIo.java` 58 | 59 | By default, `GreeterGrpcIo` is not generated, to activate it you need to tell the Vert.x gRPC protoc plugin to generate it: 60 | 61 | [source,xml] 62 | ---- 63 | 64 | vertx-grpc-protoc-plugin2 65 | io.vertx 66 | vertx-grpc-protoc-plugin2 67 | ${stack.version} 68 | io.vertx.grpc.plugin.VertxGrpcGenerator 69 | 70 | grpc-io 71 | 72 | 73 | ---- 74 | 75 | The `GreeterGrpcIo` provides a client stub that uses the Vert.x gRPC/IO Client to interact with a service: 76 | 77 | [source,java] 78 | ---- 79 | {@link examples.GrpcIoClientExamples#idiomaticStub} 80 | ---- 81 | 82 | You can read the <> section to learn more about it. 83 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/asciidoc/iostorage.adoc: -------------------------------------------------------------------------------- 1 | == Vert.x gRPC Context Storage 2 | 3 | Vert.x gRPC Context Storage overrides the default `io.grpc.Context.Storage` implementation. 4 | 5 | The default implementation always stores the gRPC context in a _thread-local_ variable. 6 | This implementation stores the gRPC context the same way as Vert.x core stores request tracing data. 7 | 8 | This means, for example, that when you implement a service method, the gRPC context is propagated across Vert.x async API calls: 9 | 10 | [source,java] 11 | ---- 12 | {@link examples.GrpcContextStorageExamples#example} 13 | ---- 14 | 15 | [CAUTION] 16 | ==== 17 | The gRPC context is propagated across Vert.x async API calls only when the current Vert.x {@link io.vertx.core.Context} is bound to a Vert.x HTTP server request. 18 | 19 | It is not propagated if, for example, you invoke a stub on a non-Vert.x thread or from a verticle {@link io.vertx.core.Verticle#start} method. 20 | ==== 21 | 22 | === Using Vert.x gRPC Context Storage 23 | 24 | To use Vert.x gRPC Context Storage, add the following dependency to the _dependencies_ section of your build descriptor: 25 | 26 | * Maven (in your `pom.xml`): 27 | 28 | [source,xml,subs="+attributes"] 29 | ---- 30 | 31 | io.vertx 32 | vertx-grpc-context-storage 33 | ${maven.version} 34 | 35 | ---- 36 | 37 | * Gradle (in your `build.gradle` file): 38 | 39 | [source,groovy,subs="+attributes"] 40 | ---- 41 | dependencies { 42 | compile 'io.vertx:vertx-grpc-context-storage:${maven.version}' 43 | } 44 | ---- 45 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/com/google/api/CustomHttpPatternOrBuilder.java: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // NO CHECKED-IN PROTOBUF GENCODE 3 | // source: google/api/http.proto 4 | // Protobuf Java Version: 4.29.3 5 | 6 | package com.google.api; 7 | 8 | public interface CustomHttpPatternOrBuilder extends 9 | // @@protoc_insertion_point(interface_extends:google.api.CustomHttpPattern) 10 | com.google.protobuf.MessageOrBuilder { 11 | 12 | /** 13 | *
    14 |    * The name of this custom HTTP verb.
    15 |    * 
    16 | * 17 | * string kind = 1; 18 | * @return The kind. 19 | */ 20 | java.lang.String getKind(); 21 | /** 22 | *
    23 |    * The name of this custom HTTP verb.
    24 |    * 
    25 | * 26 | * string kind = 1; 27 | * @return The bytes for kind. 28 | */ 29 | com.google.protobuf.ByteString 30 | getKindBytes(); 31 | 32 | /** 33 | *
    34 |    * The path matched by this custom verb.
    35 |    * 
    36 | * 37 | * string path = 2; 38 | * @return The path. 39 | */ 40 | java.lang.String getPath(); 41 | /** 42 | *
    43 |    * The path matched by this custom verb.
    44 |    * 
    45 | * 46 | * string path = 2; 47 | * @return The bytes for path. 48 | */ 49 | com.google.protobuf.ByteString 50 | getPathBytes(); 51 | } 52 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/com/google/api/HttpOrBuilder.java: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // NO CHECKED-IN PROTOBUF GENCODE 3 | // source: google/api/http.proto 4 | // Protobuf Java Version: 4.29.3 5 | 6 | package com.google.api; 7 | 8 | public interface HttpOrBuilder extends 9 | // @@protoc_insertion_point(interface_extends:google.api.Http) 10 | com.google.protobuf.MessageOrBuilder { 11 | 12 | /** 13 | *
    14 |    * A list of HTTP configuration rules that apply to individual API methods.
    15 |    *
    16 |    * **NOTE:** All service configuration rules follow "last one wins" order.
    17 |    * 
    18 | * 19 | * repeated .google.api.HttpRule rules = 1; 20 | */ 21 | java.util.List 22 | getRulesList(); 23 | /** 24 | *
    25 |    * A list of HTTP configuration rules that apply to individual API methods.
    26 |    *
    27 |    * **NOTE:** All service configuration rules follow "last one wins" order.
    28 |    * 
    29 | * 30 | * repeated .google.api.HttpRule rules = 1; 31 | */ 32 | com.google.api.HttpRule getRules(int index); 33 | /** 34 | *
    35 |    * A list of HTTP configuration rules that apply to individual API methods.
    36 |    *
    37 |    * **NOTE:** All service configuration rules follow "last one wins" order.
    38 |    * 
    39 | * 40 | * repeated .google.api.HttpRule rules = 1; 41 | */ 42 | int getRulesCount(); 43 | /** 44 | *
    45 |    * A list of HTTP configuration rules that apply to individual API methods.
    46 |    *
    47 |    * **NOTE:** All service configuration rules follow "last one wins" order.
    48 |    * 
    49 | * 50 | * repeated .google.api.HttpRule rules = 1; 51 | */ 52 | java.util.List 53 | getRulesOrBuilderList(); 54 | /** 55 | *
    56 |    * A list of HTTP configuration rules that apply to individual API methods.
    57 |    *
    58 |    * **NOTE:** All service configuration rules follow "last one wins" order.
    59 |    * 
    60 | * 61 | * repeated .google.api.HttpRule rules = 1; 62 | */ 63 | com.google.api.HttpRuleOrBuilder getRulesOrBuilder( 64 | int index); 65 | 66 | /** 67 | *
    68 |    * When set to true, URL path parameters will be fully URI-decoded except in
    69 |    * cases of single segment matches in reserved expansion, where "%2F" will be
    70 |    * left encoded.
    71 |    *
    72 |    * The default behavior is to not decode RFC 6570 reserved characters in multi
    73 |    * segment matches.
    74 |    * 
    75 | * 76 | * bool fully_decode_reserved_expansion = 2; 77 | * @return The fullyDecodeReservedExpansion. 78 | */ 79 | boolean getFullyDecodeReservedExpansion(); 80 | } 81 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/GrpcContextStorageExamples.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import io.grpc.Context; 4 | import io.vertx.core.Vertx; 5 | import io.vertx.docgen.Source; 6 | 7 | @Source 8 | @SuppressWarnings("unused") 9 | public class GrpcContextStorageExamples { 10 | 11 | public void example(Vertx vertx) { 12 | Context grpcCtx1 = Context.current(); 13 | 14 | vertx.executeBlocking(() -> { 15 | 16 | // Same as grpcCtx1 17 | Context grpcCtx2 = Context.current(); 18 | 19 | return doSomething(); 20 | 21 | }).onComplete(ar -> { 22 | 23 | // Same as grpcCtx1 and grpcCtx2 24 | Context grpcCtx3 = Context.current(); 25 | 26 | }); 27 | } 28 | 29 | private String doSomething() { 30 | return null; 31 | } 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/GrpcIoClientExamples.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import examples.grpc.GreeterGrpc; 4 | import examples.grpc.GreeterGrpcIo; 5 | import examples.grpc.HelloReply; 6 | import examples.grpc.HelloRequest; 7 | import io.grpc.stub.StreamObserver; 8 | import io.vertx.core.Future; 9 | import io.vertx.core.Vertx; 10 | import io.vertx.core.net.SocketAddress; 11 | import io.vertx.docgen.Source; 12 | import io.vertx.grpcio.client.GrpcIoClient; 13 | import io.vertx.grpcio.client.GrpcIoClientChannel; 14 | 15 | import java.util.concurrent.TimeUnit; 16 | 17 | @Source 18 | public class GrpcIoClientExamples { 19 | 20 | public void createClient(Vertx vertx) { 21 | GrpcIoClient client = GrpcIoClient.client(vertx); 22 | } 23 | 24 | public void stub(GrpcIoClient client) { 25 | 26 | GrpcIoClientChannel channel = new GrpcIoClientChannel(client, SocketAddress.inetSocketAddress(443, "example.com")); 27 | 28 | GreeterGrpc.GreeterStub greeter = GreeterGrpc.newStub(channel); 29 | 30 | StreamObserver observer = new StreamObserver() { 31 | @Override 32 | public void onNext(HelloReply value) { 33 | // Process response 34 | } 35 | 36 | @Override 37 | public void onCompleted() { 38 | // Done 39 | } 40 | 41 | @Override 42 | public void onError(Throwable t) { 43 | // Something went bad 44 | } 45 | }; 46 | 47 | greeter.sayHello(HelloRequest.newBuilder().setName("Bob").build(), observer); 48 | } 49 | 50 | public void stubWithDeadline(GrpcIoClientChannel channel, StreamObserver observer) { 51 | 52 | GreeterGrpc.GreeterStub greeter = GreeterGrpc.newStub(channel).withDeadlineAfter(10, TimeUnit.SECONDS); 53 | 54 | greeter.sayHello(HelloRequest.newBuilder().setName("Bob").build(), observer); 55 | } 56 | 57 | public void idiomaticStub(Vertx vertx, GrpcIoClient client) { 58 | 59 | GrpcIoClientChannel channel = new GrpcIoClientChannel(client, SocketAddress.inetSocketAddress(443, "example.com")); 60 | 61 | GreeterGrpcIo.GreeterStub greeter = GreeterGrpcIo.newStub(vertx, channel); 62 | 63 | Future future = greeter.sayHello(HelloRequest.newBuilder().setName("Bob").build()); 64 | 65 | future 66 | .onSuccess(reply -> { 67 | // Process response 68 | }) 69 | .onFailure(err -> { 70 | // Something went bad 71 | }); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/GrpcTranscodingExamples.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import examples.grpc.GreeterGrpcService; 4 | import examples.grpc.HelloReply; 5 | import examples.grpc.HelloRequest; 6 | import io.vertx.core.Future; 7 | import io.vertx.docgen.Source; 8 | import io.vertx.grpc.server.GrpcServer; 9 | import io.vertx.grpc.server.Service; 10 | 11 | @Source 12 | public class GrpcTranscodingExamples { 13 | 14 | public void transcodingRequestResponse(GrpcServer server) { 15 | Service service = new GreeterGrpcService() { 16 | @Override 17 | public Future sayHello(HelloRequest request) { 18 | return Future.succeededFuture(HelloReply.newBuilder().setMessage("Hello " + request.getName()).build()); 19 | } 20 | }; 21 | 22 | server.addService(service); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/grpc/EmptyOrBuilder.java: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // NO CHECKED-IN PROTOBUF GENCODE 3 | // source: docs.proto 4 | // Protobuf Java Version: 4.29.3 5 | 6 | package examples.grpc; 7 | 8 | public interface EmptyOrBuilder extends 9 | // @@protoc_insertion_point(interface_extends:examples.grpc.Empty) 10 | com.google.protobuf.MessageOrBuilder { 11 | } 12 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/grpc/Greeter.java: -------------------------------------------------------------------------------- 1 | package examples.grpc; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.Promise; 5 | import io.vertx.core.Handler; 6 | import io.vertx.core.http.HttpMethod; 7 | import io.vertx.core.streams.ReadStream; 8 | import io.vertx.core.streams.WriteStream; 9 | import io.vertx.grpc.common.GrpcStatus; 10 | import io.vertx.grpc.common.ServiceName; 11 | import io.vertx.grpc.common.ServiceMethod; 12 | import io.vertx.grpc.common.GrpcMessageDecoder; 13 | import io.vertx.grpc.common.GrpcMessageEncoder; 14 | import io.vertx.grpc.server.GrpcServerRequest; 15 | import io.vertx.grpc.server.GrpcServer; 16 | import io.vertx.grpc.server.Service; 17 | import io.vertx.grpc.server.ServiceBuilder; 18 | 19 | import com.google.protobuf.Descriptors; 20 | 21 | import java.util.LinkedList; 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | /** 26 | *

    Contract definition Greeter service.

    27 | */ 28 | public interface Greeter { 29 | 30 | Future sayHello(examples.grpc.HelloRequest request); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/grpc/GreeterClient.java: -------------------------------------------------------------------------------- 1 | package examples.grpc; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.Completable; 5 | import io.vertx.core.Handler; 6 | import io.vertx.core.net.SocketAddress; 7 | import io.vertx.grpc.client.GrpcClient; 8 | import io.vertx.core.streams.ReadStream; 9 | import io.vertx.core.streams.WriteStream; 10 | import io.vertx.grpc.common.GrpcStatus; 11 | import io.vertx.grpc.common.ServiceName; 12 | import io.vertx.grpc.common.ServiceMethod; 13 | import io.vertx.grpc.common.GrpcMessageDecoder; 14 | import io.vertx.grpc.common.GrpcMessageEncoder; 15 | 16 | /** 17 | *

    A client for invoking the Greeter gRPC service.

    18 | */ 19 | public interface GreeterClient extends Greeter { 20 | 21 | /** 22 | * Calls the SayHello RPC service method. 23 | * 24 | * @param request the examples.grpc.HelloRequest request message 25 | * @return a future of the examples.grpc.HelloReply response message 26 | */ 27 | Future sayHello(examples.grpc.HelloRequest request); 28 | } 29 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/grpc/GreeterService.java: -------------------------------------------------------------------------------- 1 | package examples.grpc; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.Completable; 5 | import io.vertx.core.Handler; 6 | import io.vertx.core.http.HttpMethod; 7 | import io.vertx.core.streams.ReadStream; 8 | import io.vertx.core.streams.WriteStream; 9 | import io.vertx.grpc.common.GrpcStatus; 10 | import io.vertx.grpc.common.ServiceName; 11 | import io.vertx.grpc.common.ServiceMethod; 12 | import io.vertx.grpc.common.GrpcMessageDecoder; 13 | import io.vertx.grpc.common.GrpcMessageEncoder; 14 | import io.vertx.grpc.server.GrpcServerRequest; 15 | import io.vertx.grpc.server.GrpcServer; 16 | import io.vertx.grpc.server.Service; 17 | import io.vertx.grpc.server.ServiceBuilder; 18 | 19 | import com.google.protobuf.Descriptors; 20 | 21 | import java.util.LinkedList; 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | /** 26 | *

    Provides support for RPC methods implementations of the Greeter gRPC service.

    27 | * 28 | *

    The following methods of this class should be overridden to provide an implementation of the service:

    29 | *
      30 | *
    • SayHello
    • 31 | *
    32 | */ 33 | public class GreeterService implements Greeter { 34 | 35 | /** 36 | * Override this method to implement the SayHello RPC. 37 | */ 38 | public Future sayHello(examples.grpc.HelloRequest request) { 39 | throw new UnsupportedOperationException("Not implemented"); 40 | } 41 | 42 | protected void sayHello(examples.grpc.HelloRequest request, Completable response) { 43 | sayHello(request).onComplete(response); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/grpc/HelloReplyOrBuilder.java: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // NO CHECKED-IN PROTOBUF GENCODE 3 | // source: docs.proto 4 | // Protobuf Java Version: 4.29.3 5 | 6 | package examples.grpc; 7 | 8 | public interface HelloReplyOrBuilder extends 9 | // @@protoc_insertion_point(interface_extends:examples.grpc.HelloReply) 10 | com.google.protobuf.MessageOrBuilder { 11 | 12 | /** 13 | * string message = 1; 14 | * @return The message. 15 | */ 16 | java.lang.String getMessage(); 17 | /** 18 | * string message = 1; 19 | * @return The bytes for message. 20 | */ 21 | com.google.protobuf.ByteString 22 | getMessageBytes(); 23 | } 24 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/grpc/HelloRequestOrBuilder.java: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // NO CHECKED-IN PROTOBUF GENCODE 3 | // source: docs.proto 4 | // Protobuf Java Version: 4.29.3 5 | 6 | package examples.grpc; 7 | 8 | public interface HelloRequestOrBuilder extends 9 | // @@protoc_insertion_point(interface_extends:examples.grpc.HelloRequest) 10 | com.google.protobuf.MessageOrBuilder { 11 | 12 | /** 13 | * string name = 1; 14 | * @return The name. 15 | */ 16 | java.lang.String getName(); 17 | /** 18 | * string name = 1; 19 | * @return The bytes for name. 20 | */ 21 | com.google.protobuf.ByteString 22 | getNameBytes(); 23 | } 24 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/grpc/ItemOrBuilder.java: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // NO CHECKED-IN PROTOBUF GENCODE 3 | // source: docs.proto 4 | // Protobuf Java Version: 4.29.3 5 | 6 | package examples.grpc; 7 | 8 | public interface ItemOrBuilder extends 9 | // @@protoc_insertion_point(interface_extends:examples.grpc.Item) 10 | com.google.protobuf.MessageOrBuilder { 11 | 12 | /** 13 | * string value = 1; 14 | * @return The value. 15 | */ 16 | java.lang.String getValue(); 17 | /** 18 | * string value = 1; 19 | * @return The bytes for value. 20 | */ 21 | com.google.protobuf.ByteString 22 | getValueBytes(); 23 | } 24 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/grpc/Streaming.java: -------------------------------------------------------------------------------- 1 | package examples.grpc; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.Promise; 5 | import io.vertx.core.Handler; 6 | import io.vertx.core.http.HttpMethod; 7 | import io.vertx.core.streams.ReadStream; 8 | import io.vertx.core.streams.WriteStream; 9 | import io.vertx.grpc.common.GrpcStatus; 10 | import io.vertx.grpc.common.ServiceName; 11 | import io.vertx.grpc.common.ServiceMethod; 12 | import io.vertx.grpc.common.GrpcMessageDecoder; 13 | import io.vertx.grpc.common.GrpcMessageEncoder; 14 | import io.vertx.grpc.server.GrpcServerRequest; 15 | import io.vertx.grpc.server.GrpcServer; 16 | import io.vertx.grpc.server.Service; 17 | import io.vertx.grpc.server.ServiceBuilder; 18 | 19 | import com.google.protobuf.Descriptors; 20 | 21 | import java.util.LinkedList; 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | /** 26 | *

    Contract definition Streaming service.

    27 | */ 28 | public interface Streaming { 29 | 30 | Future> source(examples.grpc.Empty request); 31 | 32 | Future sink(ReadStream request); 33 | 34 | Future> pipe(ReadStream request); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/examples/grpc/StreamingService.java: -------------------------------------------------------------------------------- 1 | package examples.grpc; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.Completable; 5 | import io.vertx.core.Handler; 6 | import io.vertx.core.http.HttpMethod; 7 | import io.vertx.core.streams.ReadStream; 8 | import io.vertx.core.streams.WriteStream; 9 | import io.vertx.grpc.common.GrpcStatus; 10 | import io.vertx.grpc.common.ServiceName; 11 | import io.vertx.grpc.common.ServiceMethod; 12 | import io.vertx.grpc.common.GrpcMessageDecoder; 13 | import io.vertx.grpc.common.GrpcMessageEncoder; 14 | import io.vertx.grpc.server.GrpcServerRequest; 15 | import io.vertx.grpc.server.GrpcServer; 16 | import io.vertx.grpc.server.Service; 17 | import io.vertx.grpc.server.ServiceBuilder; 18 | 19 | import com.google.protobuf.Descriptors; 20 | 21 | import java.util.LinkedList; 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | /** 26 | *

    Provides support for RPC methods implementations of the Streaming gRPC service.

    27 | * 28 | *

    The following methods of this class should be overridden to provide an implementation of the service:

    29 | *
      30 | *
    • Source
    • 31 | *
    • Sink
    • 32 | *
    • Pipe
    • 33 | *
    34 | */ 35 | public class StreamingService implements Streaming { 36 | 37 | /** 38 | * Override this method to implement the Source RPC. 39 | */ 40 | public Future> source(examples.grpc.Empty request) { 41 | throw new UnsupportedOperationException("Not implemented"); 42 | } 43 | 44 | protected void source(examples.grpc.Empty request, WriteStream response) { 45 | source(request) 46 | .onComplete(ar -> { 47 | if (ar.succeeded()) { 48 | ReadStream stream = ar.result(); 49 | stream.pipeTo(response); 50 | } else { 51 | // Todo 52 | } 53 | }); 54 | } 55 | 56 | /** 57 | * Override this method to implement the Sink RPC. 58 | */ 59 | public Future sink(ReadStream request) { 60 | throw new UnsupportedOperationException("Not implemented"); 61 | } 62 | 63 | protected void sink(ReadStream request, Completable response) { 64 | sink(request).onComplete(response); 65 | } 66 | 67 | /** 68 | * Override this method to implement the Pipe RPC. 69 | */ 70 | public Future> pipe(ReadStream request) { 71 | throw new UnsupportedOperationException("Not implemented"); 72 | } 73 | 74 | protected void pipe(ReadStream request, WriteStream response) { 75 | pipe(request) 76 | .onComplete(ar -> { 77 | if (ar.succeeded()) { 78 | ReadStream stream = ar.result(); 79 | stream.pipeTo(response); 80 | } else { 81 | // Todo 82 | } 83 | }); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/java/io/vertx/dummy/Dummy.java: -------------------------------------------------------------------------------- 1 | package io.vertx.dummy; 2 | 3 | // Trigger javadoc generation 4 | public class Dummy { 5 | } 6 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/proto/docs.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "google/api/annotations.proto"; 4 | 5 | option java_multiple_files = true; 6 | option java_package = "examples.grpc"; 7 | 8 | package examples.grpc; 9 | 10 | service Greeter { 11 | rpc SayHello (HelloRequest) returns (HelloReply) { 12 | option (google.api.http) = { 13 | get: "/v1/hello/{name}" 14 | }; 15 | } 16 | } 17 | 18 | message HelloRequest { 19 | string name = 1; 20 | } 21 | 22 | message HelloReply { 23 | string message = 1; 24 | } 25 | 26 | service Streaming { 27 | rpc Source(Empty) returns (stream Item) {} 28 | rpc Sink(stream Item) returns (Empty) {} 29 | rpc Pipe(stream Item) returns (stream Item) {} 30 | } 31 | 32 | message Item { 33 | string value = 1; 34 | } 35 | 36 | message Empty { 37 | } 38 | -------------------------------------------------------------------------------- /vertx-grpc-docs/src/main/proto/google/api/annotations.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/api/http.proto"; 20 | import "google/protobuf/descriptor.proto"; 21 | 22 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "AnnotationsProto"; 25 | option java_package = "com.google.api"; 26 | option objc_class_prefix = "GAPI"; 27 | 28 | extend google.protobuf.MethodOptions { 29 | // See `HttpRule`. 30 | HttpRule http = 72295728; 31 | } 32 | -------------------------------------------------------------------------------- /vertx-grpc-health/src/main/java/io/vertx/grpc/health/HealthServiceOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.health; 12 | 13 | import io.vertx.codegen.annotations.DataObject; 14 | import io.vertx.codegen.annotations.Unstable; 15 | 16 | import java.time.Duration; 17 | 18 | /** 19 | * Configuration for a {@link HealthService}. 20 | */ 21 | @Unstable 22 | @DataObject 23 | public class HealthServiceOptions { 24 | 25 | /** 26 | * The health check interval in milliseconds, by default = {@code 2500} milliseconds. 27 | */ 28 | public static final Duration HEALTH_CHECK_INTERVAL = Duration.ofMillis(2500); 29 | 30 | private Duration healthCheckInterval; 31 | 32 | /** 33 | * Default options. 34 | */ 35 | public HealthServiceOptions() { 36 | healthCheckInterval = HEALTH_CHECK_INTERVAL; 37 | } 38 | 39 | /** 40 | * Copy constructor. 41 | */ 42 | public HealthServiceOptions(HealthServiceOptions other) { 43 | healthCheckInterval = other.healthCheckInterval; 44 | } 45 | 46 | /** 47 | * @return the health check interval in {@link Duration} 48 | */ 49 | public Duration getHealthCheckInterval() { 50 | return healthCheckInterval; 51 | } 52 | 53 | /** 54 | * Set the health check interval in milliseconds 55 | * 56 | * @param healthCheckInterval the interval in milliseconds 57 | * @return a reference to this, so the API can be used fluently 58 | */ 59 | public HealthServiceOptions setHealthCheckInterval(Duration healthCheckInterval) { 60 | if (healthCheckInterval == null || healthCheckInterval.toMillis() <= 0) { 61 | throw new IllegalArgumentException("Health check interval must be > 0 milliseconds. Provided: " + healthCheckInterval + " milliseconds."); 62 | } 63 | this.healthCheckInterval = healthCheckInterval; 64 | return this; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /vertx-grpc-health/src/main/java/io/vertx/grpc/health/handler/GrpcHealthCheckV1Handler.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.health.handler; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.Handler; 5 | import io.vertx.grpc.common.*; 6 | import io.vertx.grpc.health.v1.HealthCheckRequest; 7 | import io.vertx.grpc.health.v1.HealthCheckResponse; 8 | import io.vertx.grpc.server.GrpcServer; 9 | import io.vertx.grpc.server.GrpcServerRequest; 10 | 11 | import java.util.Map; 12 | import java.util.function.Supplier; 13 | 14 | public class GrpcHealthCheckV1Handler extends GrpcHealthV1HandlerBase implements Handler> { 15 | 16 | public static final ServiceMethod SERVICE_METHOD = ServiceMethod.server( 17 | ServiceName.create("grpc.health.v1.Health"), 18 | "Check", 19 | GrpcMessageEncoder.encoder(), 20 | GrpcMessageDecoder.decoder(HealthCheckRequest.newBuilder())); 21 | 22 | public GrpcHealthCheckV1Handler(GrpcServer server, Map>> healthChecks) { 23 | super(server, healthChecks); 24 | } 25 | 26 | @Override 27 | public void handle(GrpcServerRequest request) { 28 | request.handler(check -> checkStatus(check.getService()).compose(result -> { 29 | if (result == HealthCheckResponse.ServingStatus.SERVICE_UNKNOWN) { 30 | return request.response().status(GrpcStatus.NOT_FOUND).end(); 31 | } 32 | 33 | HealthCheckResponse.Builder builder = HealthCheckResponse.newBuilder(); 34 | builder.setStatus(result); 35 | return request.response().end(builder.build()); 36 | }).onFailure(failure -> request.response().status(GrpcStatus.INTERNAL).end())); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vertx-grpc-health/src/main/java/io/vertx/grpc/health/handler/GrpcHealthListV1Handler.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.health.handler; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.Handler; 5 | import io.vertx.grpc.common.GrpcMessageDecoder; 6 | import io.vertx.grpc.common.GrpcMessageEncoder; 7 | import io.vertx.grpc.common.ServiceMethod; 8 | import io.vertx.grpc.common.ServiceName; 9 | import io.vertx.grpc.health.v1.HealthCheckResponse; 10 | import io.vertx.grpc.health.v1.HealthListRequest; 11 | import io.vertx.grpc.health.v1.HealthListResponse; 12 | import io.vertx.grpc.server.GrpcServer; 13 | import io.vertx.grpc.server.GrpcServerRequest; 14 | 15 | import java.util.Map; 16 | import java.util.function.Supplier; 17 | 18 | public class GrpcHealthListV1Handler extends GrpcHealthV1HandlerBase implements Handler> { 19 | 20 | public static final ServiceMethod SERVICE_METHOD = ServiceMethod.server( 21 | ServiceName.create("grpc.health.v1.Health"), 22 | "List", 23 | GrpcMessageEncoder.encoder(), 24 | GrpcMessageDecoder.decoder(HealthListRequest.newBuilder())); 25 | 26 | public GrpcHealthListV1Handler(GrpcServer server, Map>> healthChecks) { 27 | super(server, healthChecks); 28 | } 29 | 30 | @Override 31 | public void handle(GrpcServerRequest event) { 32 | event.handler(request -> { 33 | HealthListResponse.Builder builder = HealthListResponse.newBuilder(); 34 | healthChecks().forEach((name, check) -> { 35 | HealthCheckResponse.Builder responseBuilder = HealthCheckResponse.newBuilder(); 36 | checkStatus(name).onSuccess(result -> { 37 | responseBuilder.setStatus(result); 38 | builder.putStatuses(name, responseBuilder.build()); 39 | }).onFailure(failure -> { 40 | responseBuilder.setStatus(HealthCheckResponse.ServingStatus.NOT_SERVING); 41 | builder.putStatuses(name, responseBuilder.build()); 42 | }); 43 | }); 44 | event.response().end(builder.build()); 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /vertx-grpc-health/src/main/java/io/vertx/grpc/health/handler/GrpcHealthV1HandlerBase.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.health.handler; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.grpc.health.v1.HealthCheckResponse; 5 | import io.vertx.grpc.server.GrpcServer; 6 | 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | import java.util.function.Supplier; 10 | 11 | public abstract class GrpcHealthV1HandlerBase { 12 | 13 | protected final GrpcServer server; 14 | protected final Map>> healthChecks; 15 | 16 | protected GrpcHealthV1HandlerBase(GrpcServer server, Map>> healthChecks) { 17 | this.server = server; 18 | this.healthChecks = healthChecks; 19 | } 20 | 21 | protected Map>> healthChecks() { 22 | Map>> checks = new ConcurrentHashMap<>(healthChecks); 23 | server.services().forEach(service -> { 24 | if (!checks.containsKey(service.name().fullyQualifiedName())) { 25 | checks.put(service.name().fullyQualifiedName(), () -> Future.succeededFuture(true)); 26 | } 27 | }); 28 | return checks; 29 | } 30 | 31 | protected Future checkStatus(String name) { 32 | // Default server status 33 | if (name == null || name.isBlank()) { 34 | return Future.succeededFuture(HealthCheckResponse.ServingStatus.SERVING); 35 | } 36 | 37 | Supplier> check = healthChecks.get(name); 38 | if (check != null) { 39 | return check.get().map(this::statusToProto); 40 | } else { 41 | if (server.services().stream().anyMatch(service -> service.name().fullyQualifiedName().equals(name))) { 42 | return Future.succeededFuture(HealthCheckResponse.ServingStatus.SERVING); 43 | } 44 | 45 | return Future.succeededFuture(HealthCheckResponse.ServingStatus.SERVICE_UNKNOWN); 46 | } 47 | } 48 | 49 | private HealthCheckResponse.ServingStatus statusToProto(boolean status) { 50 | return status ? HealthCheckResponse.ServingStatus.SERVING : HealthCheckResponse.ServingStatus.NOT_SERVING; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /vertx-grpc-health/src/main/java/io/vertx/grpc/health/impl/HealthServiceImpl.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.health.impl; 2 | 3 | import com.google.protobuf.Descriptors; 4 | import io.vertx.core.Future; 5 | import io.vertx.core.Promise; 6 | import io.vertx.core.Vertx; 7 | import io.vertx.grpc.common.ServiceName; 8 | import io.vertx.grpc.health.HealthService; 9 | import io.vertx.grpc.health.HealthServiceOptions; 10 | import io.vertx.grpc.health.handler.GrpcHealthCheckV1Handler; 11 | import io.vertx.grpc.health.handler.GrpcHealthListV1Handler; 12 | import io.vertx.grpc.health.handler.GrpcHealthWatchV1Handler; 13 | import io.vertx.grpc.health.v1.HealthProto; 14 | import io.vertx.grpc.server.GrpcServer; 15 | 16 | import java.util.Map; 17 | import java.util.concurrent.ConcurrentHashMap; 18 | import java.util.function.Supplier; 19 | 20 | public class HealthServiceImpl implements HealthService { 21 | 22 | private static final ServiceName V1_SERVICE_NAME = ServiceName.create("grpc.health.v1.Health"); 23 | private static final Descriptors.ServiceDescriptor V1_SERVICE_DESCRIPTOR = HealthProto.getDescriptor().findServiceByName("Health"); 24 | 25 | private final Vertx vertx; 26 | private final HealthServiceOptions options; 27 | private final Map>> checks = new ConcurrentHashMap<>(); 28 | 29 | public HealthServiceImpl(Vertx vertx) { 30 | this(vertx, new HealthServiceOptions()); 31 | } 32 | 33 | public HealthServiceImpl(Vertx vertx, HealthServiceOptions options) { 34 | this.vertx = vertx; 35 | this.options = options; 36 | this.register(V1_SERVICE_NAME, () -> Future.succeededFuture(true)); 37 | } 38 | 39 | @Override 40 | public ServiceName name() { 41 | return V1_SERVICE_NAME; 42 | } 43 | 44 | @Override 45 | public Descriptors.ServiceDescriptor descriptor() { 46 | return V1_SERVICE_DESCRIPTOR; 47 | } 48 | 49 | @Override 50 | public void bind(GrpcServer server) { 51 | server.callHandler(GrpcHealthCheckV1Handler.SERVICE_METHOD, new GrpcHealthCheckV1Handler(server, checks)); 52 | server.callHandler(GrpcHealthListV1Handler.SERVICE_METHOD, new GrpcHealthListV1Handler(server, checks)); 53 | server.callHandler(GrpcHealthWatchV1Handler.SERVICE_METHOD, new GrpcHealthWatchV1Handler(vertx, server, checks, options)); 54 | } 55 | 56 | @Override 57 | public HealthService register(String name, Supplier> check) { 58 | checks.put(name, check); 59 | return this; 60 | } 61 | 62 | @Override 63 | public HealthService unregister(String name) { 64 | checks.remove(name); 65 | return this; 66 | } 67 | 68 | @Override 69 | public Future checkStatus(String name) { 70 | Promise promise = Promise.promise(); 71 | Supplier> check = checks.get(name); 72 | if (check != null) { 73 | check.get().onComplete(promise); 74 | } else { 75 | promise.fail("Unknown service " + name); 76 | } 77 | return promise.future(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /vertx-grpc-health/src/main/java/io/vertx/grpc/health/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | @ModuleGen(name = "vertx-grpc-health", groupPackage = "io.vertx") 12 | package io.vertx.grpc.health; 13 | 14 | import io.vertx.codegen.annotations.ModuleGen; 15 | -------------------------------------------------------------------------------- /vertx-grpc-health/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module io.vertx.grpc.health { 2 | requires io.vertx.core; 3 | requires io.vertx.grpc.common; 4 | requires io.vertx.grpc.server; 5 | requires static io.vertx.docgen; 6 | requires static io.vertx.codegen.json; 7 | requires io.vertx.codegen.api; 8 | requires com.google.protobuf; 9 | requires java.logging; 10 | exports io.vertx.grpc.health; 11 | } 12 | -------------------------------------------------------------------------------- /vertx-grpc-health/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | open module io.vertx.tests.health { 2 | requires com.google.common; 3 | requires com.google.protobuf; 4 | requires com.google.protobuf.util; 5 | requires io.grpc; 6 | requires io.grpc.stub; 7 | requires io.grpc.util; 8 | requires io.grpc.protobuf; 9 | requires io.vertx.grpc.common; 10 | requires io.vertx.grpc.server; 11 | requires io.vertx.grpc.health; 12 | requires io.vertx.testing.unit; 13 | requires io.vertx.tests.common; 14 | requires io.vertx.tests.server; 15 | requires junit; 16 | requires testcontainers; 17 | requires io.vertx.core; 18 | requires io.vertx.codegen.api; 19 | exports io.vertx.tests.health.grpc; 20 | } 21 | -------------------------------------------------------------------------------- /vertx-grpc-it/src/main/java/io/vertx/grpc/it/Noop.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.it; 2 | 3 | public class Noop { 4 | private Noop() { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /vertx-grpc-it/src/test/java/io/grpc/examples/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | 12 | @ModuleGen(name = "grpc-examples", groupPackage = "io.grpc.examples") 13 | package io.grpc.examples; 14 | 15 | import io.vertx.codegen.annotations.ModuleGen; 16 | -------------------------------------------------------------------------------- /vertx-grpc-it/src/test/java/io/grpc/testing/integration/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | 12 | @ModuleGen(name = "grpc-test", groupPackage = "io.grpc.testing.integration") 13 | package io.grpc.testing.integration; 14 | 15 | import io.vertx.codegen.annotations.ModuleGen; 16 | -------------------------------------------------------------------------------- /vertx-grpc-it/src/test/java/io/vertx/grpc/it/ProtocPluginTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.it; 12 | 13 | import io.grpc.examples.helloworld.*; 14 | import io.grpc.testing.integration.*; 15 | import io.vertx.core.net.SocketAddress; 16 | import io.vertx.grpc.server.GrpcServer; 17 | import io.vertx.grpc.client.GrpcClient; 18 | import io.vertx.grpc.server.Service; 19 | 20 | public class ProtocPluginTest extends ProtocPluginTestBase { 21 | 22 | @Override 23 | protected GrpcServer grpcServer() { 24 | return GrpcServer.server(vertx); 25 | } 26 | 27 | @Override 28 | protected GrpcClient grpcClient() { 29 | return GrpcClient.client(vertx); 30 | } 31 | 32 | @Override 33 | protected Service greeterService(GreeterService service) { 34 | return GreeterGrpcService.of(service); 35 | } 36 | 37 | @Override 38 | protected GreeterClient greeterClient(GrpcClient grpcClient, SocketAddress socketAddress) { 39 | return GreeterGrpcClient.create(grpcClient, socketAddress); 40 | } 41 | 42 | @Override 43 | protected Service testService(TestServiceService service) { 44 | return TestServiceGrpcService.of(service); 45 | } 46 | 47 | @Override 48 | protected TestServiceClient testClient(GrpcClient client, SocketAddress socketAddress) { 49 | return TestServiceGrpcClient.create(client, socketAddress); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /vertx-grpc-it/src/test/java/io/vertx/grpc/it/ProxyTestBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.it; 12 | 13 | import io.vertx.ext.unit.junit.VertxUnitRunner; 14 | import io.vertx.tests.common.GrpcTestBase; 15 | import org.junit.runner.RunWith; 16 | 17 | /** 18 | * @author Julien Viet 19 | */ 20 | @RunWith(VertxUnitRunner.class) 21 | public abstract class ProxyTestBase extends GrpcTestBase { 22 | } 23 | -------------------------------------------------------------------------------- /vertx-grpc-it/src/test/proto/empty.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | syntax = "proto2"; 31 | 32 | package grpc.testing; 33 | 34 | option java_package = "com.google.protobuf"; 35 | option java_outer_classname = "EmptyProtos"; 36 | 37 | // An empty message that you can re-use to avoid defining duplicated empty 38 | // messages in your project. A typical example is to use it as argument or the 39 | // return value of a service API. For instance: 40 | // 41 | // service Foo { 42 | // rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; 43 | // }; 44 | // 45 | message Empty {} 46 | -------------------------------------------------------------------------------- /vertx-grpc-it/src/test/proto/google/api/annotations.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/api/http.proto"; 20 | import "google/protobuf/descriptor.proto"; 21 | 22 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "AnnotationsProto"; 25 | option java_package = "com.google.api"; 26 | option objc_class_prefix = "GAPI"; 27 | 28 | extend google.protobuf.MethodOptions { 29 | // See `HttpRule`. 30 | HttpRule http = 72295728; 31 | } 32 | -------------------------------------------------------------------------------- /vertx-grpc-it/src/test/proto/hello_streaming.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The gRPC Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | syntax = "proto3"; 15 | 16 | option java_multiple_files = true; 17 | option java_package = "io.grpc.examples.manualflowcontrol"; 18 | option java_outer_classname = "HelloStreamingProto"; 19 | option objc_class_prefix = "HLWS"; 20 | 21 | package manualflowcontrol; 22 | 23 | // The greeting service definition. 24 | service StreamingGreeter { 25 | // Streams a many greetings 26 | rpc SayHelloStreaming (stream HelloRequest) returns (stream HelloReply) {} 27 | } 28 | 29 | // The request message containing the user's name. 30 | message HelloRequest { 31 | string name = 1; 32 | } 33 | 34 | // The response message containing the greetings 35 | message HelloReply { 36 | string message = 1; 37 | } 38 | -------------------------------------------------------------------------------- /vertx-grpc-it/src/test/proto/optionals.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_multiple_files = true; 4 | option java_package = "io.grpc.examples.optionals"; 5 | option java_outer_classname = "OptionalsProto"; 6 | 7 | package optionals; 8 | 9 | // The greeting service definition. 10 | service Greeter { 11 | // Sends a greeting 12 | rpc SayHello (HelloRequest) returns (HelloReply) {} 13 | } 14 | 15 | // The request message containing the user's name. 16 | message HelloRequest { 17 | string name = 1; 18 | optional int32 age = 2; 19 | } 20 | 21 | // The response message containing the greetings 22 | message HelloReply { 23 | string message = 1; 24 | } 25 | -------------------------------------------------------------------------------- /vertx-grpc-it/src/test/proto/streaming.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_multiple_files = true; 4 | option java_package = "io.grpc.examples.streaming"; 5 | option java_outer_classname = "StreamingProto"; 6 | option objc_class_prefix = "RTG"; 7 | 8 | package streaming; 9 | 10 | // Interface exported by the server. 11 | service Streaming { 12 | rpc Source(Empty) returns (stream Item) {} 13 | rpc Sink(stream Item) returns (Empty) {} 14 | rpc Pipe(stream Item) returns (stream Item) {} 15 | } 16 | 17 | message Item { 18 | string value = 1; 19 | } 20 | 21 | message Empty { 22 | } -------------------------------------------------------------------------------- /vertx-grpc-protoc-plugin2/src/main/java/io/vertx/grpc/plugin/VertxGrpcGenerator.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.plugin; 2 | 3 | import com.google.api.AnnotationsProto; 4 | import com.salesforce.jprotoc.ProtocPlugin; 5 | import picocli.CommandLine; 6 | import picocli.CommandLine.Command; 7 | import picocli.CommandLine.Option; 8 | 9 | import java.util.*; 10 | import java.util.concurrent.Callable; 11 | 12 | @Command( 13 | name = "vertx-grpc-generator", 14 | mixinStandardHelpOptions = true, 15 | version = "vertx-grpc-generator 1.0", 16 | description = "Generates Vert.x gRPC code from proto files." 17 | ) 18 | public class VertxGrpcGenerator implements Callable { 19 | 20 | @Option(names = { "--grpc-client" }, description = "Generate gRPC client code") 21 | boolean generateClient = false; 22 | 23 | @Option(names = { "--grpc-service" }, description = "Generate gRPC service code") 24 | boolean generateService = false; 25 | 26 | @Option(names = { "--grpc-io" }, description = "Generate gRPC IO code") 27 | boolean generateIo = false; 28 | 29 | @Option(names = { "--grpc-transcoding" }, description = "Whether to generate transcoding options for methods with HTTP annotations") 30 | boolean generateTranscoding = true; 31 | 32 | @Option(names = { "--vertx-codegen" }, description = "Whether to generate vertx generator annotations") 33 | boolean generateVertxGeneratorAnnotations = false; 34 | 35 | @Option( 36 | names = { "--service-prefix" }, 37 | description = "Generate service classes with a prefix. For example, if you set it to `MyService`, the generated service class will be `MyServiceGreeterService` instead of `GreeterService`." 38 | ) 39 | String servicePrefix = ""; 40 | 41 | @Override 42 | public Integer call() { 43 | if (!generateClient && !generateService && !generateIo) { 44 | generateClient = true; 45 | generateService = true; 46 | } 47 | 48 | VertxGrpcGeneratorImpl generator = new VertxGrpcGeneratorImpl(this); 49 | ProtocPlugin.generate(List.of(generator), List.of(AnnotationsProto.http)); 50 | 51 | return 0; 52 | } 53 | 54 | public static void main(String[] args) { 55 | int exitCode = new CommandLine(new VertxGrpcGenerator()).execute(args); 56 | System.exit(exitCode); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /vertx-grpc-protoc-plugin2/src/main/resources/contract.mustache: -------------------------------------------------------------------------------- 1 | {{#javaPackageFqn}} 2 | package {{javaPackageFqn}}; 3 | {{/javaPackageFqn}} 4 | 5 | import io.vertx.core.Future; 6 | import io.vertx.core.Promise; 7 | import io.vertx.core.Handler; 8 | import io.vertx.core.http.HttpMethod; 9 | import io.vertx.core.streams.ReadStream; 10 | import io.vertx.core.streams.WriteStream; 11 | import io.vertx.grpc.common.GrpcStatus; 12 | import io.vertx.grpc.common.ServiceName; 13 | import io.vertx.grpc.common.ServiceMethod; 14 | import io.vertx.grpc.common.GrpcMessageDecoder; 15 | import io.vertx.grpc.common.GrpcMessageEncoder; 16 | import io.vertx.grpc.server.GrpcServerRequest; 17 | import io.vertx.grpc.server.GrpcServer; 18 | import io.vertx.grpc.server.Service; 19 | import io.vertx.grpc.server.ServiceBuilder; 20 | 21 | import com.google.protobuf.Descriptors; 22 | 23 | import java.util.LinkedList; 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | /** 28 | *

    Contract definition {{serviceName}} service.

    29 | */ 30 | public interface {{contractFqn}} { 31 | {{#unaryUnaryMethods}} 32 | 33 | Future<{{outputType}}> {{vertxMethodName}}({{inputType}} request); 34 | {{/unaryUnaryMethods}} 35 | {{#unaryManyMethods}} 36 | 37 | Future> {{vertxMethodName}}({{inputType}} request); 38 | {{/unaryManyMethods}} 39 | {{#manyUnaryMethods}} 40 | 41 | Future<{{outputType}}> {{vertxMethodName}}(ReadStream<{{inputType}}> request); 42 | {{/manyUnaryMethods}} 43 | {{#manyManyMethods}} 44 | 45 | Future> {{vertxMethodName}}(ReadStream<{{inputType}}> request); 46 | {{/manyManyMethods}} 47 | 48 | } 49 | -------------------------------------------------------------------------------- /vertx-grpc-reflection/src/main/java/io/vertx/grpc/reflection/ReflectionService.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.reflection; 2 | 3 | import com.google.protobuf.Descriptors; 4 | import io.vertx.grpc.reflection.v1.ServerReflectionProto; 5 | import io.vertx.grpc.common.ServiceName; 6 | import io.vertx.grpc.server.GrpcServer; 7 | import io.vertx.grpc.server.Service; 8 | 9 | /** 10 | * Reflection service implementing Reflection. 11 | */ 12 | public class ReflectionService implements Service { 13 | 14 | private static final ServiceName V1_SERVICE_NAME = ServiceName.create("grpc.reflection.v1.ServerReflection"); 15 | private static final Descriptors.ServiceDescriptor V1_SERVICE_DESCRIPTOR = ServerReflectionProto.getDescriptor().findServiceByName("ServerReflection"); 16 | 17 | /** 18 | * V1 singleton instance. 19 | */ 20 | private static final ReflectionService V1_INSTANCE = new ReflectionService(); 21 | 22 | /** 23 | * @return a v1 reflection service 24 | */ 25 | public static ReflectionService v1() { 26 | return V1_INSTANCE; 27 | } 28 | 29 | private ReflectionService() { 30 | } 31 | 32 | @Override 33 | public ServiceName name() { 34 | return V1_SERVICE_NAME; 35 | } 36 | 37 | @Override 38 | public Descriptors.ServiceDescriptor descriptor() { 39 | return V1_SERVICE_DESCRIPTOR; 40 | } 41 | 42 | @Override 43 | public void bind(GrpcServer server) { 44 | server.callHandler(GrpcServerReflectionV1Handler.SERVICE_METHOD, new GrpcServerReflectionV1Handler(server)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vertx-grpc-reflection/src/main/java/io/vertx/grpc/reflection/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | @ModuleGen(name = "vertx-grpc-reflection", groupPackage = "io.vertx") 12 | package io.vertx.grpc.reflection; 13 | 14 | import io.vertx.codegen.annotations.ModuleGen; 15 | -------------------------------------------------------------------------------- /vertx-grpc-reflection/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module io.vertx.grpc.reflection { 2 | requires io.vertx.core; 3 | requires io.vertx.grpc.common; 4 | requires io.vertx.grpc.server; 5 | requires static io.vertx.docgen; 6 | requires static io.vertx.codegen.json; 7 | requires io.vertx.codegen.api; 8 | requires com.google.protobuf; 9 | exports io.vertx.grpc.reflection; 10 | } 11 | -------------------------------------------------------------------------------- /vertx-grpc-reflection/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | open module io.vertx.tests.reflection { 2 | requires com.google.common; 3 | requires com.google.protobuf; 4 | requires com.google.protobuf.util; 5 | requires io.grpc; 6 | requires io.grpc.stub; 7 | requires io.grpc.util; 8 | requires io.grpc.protobuf; 9 | requires io.vertx.core; 10 | requires io.vertx.grpc.common; 11 | requires io.vertx.grpc.server; 12 | requires io.vertx.grpc.reflection; 13 | requires io.vertx.testing.unit; 14 | requires io.vertx.tests.common; 15 | requires io.vertx.tests.server; 16 | requires junit; 17 | requires testcontainers; 18 | exports io.vertx.tests.reflection.grpc; 19 | } 20 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/generated/io/vertx/grpc/server/GrpcServerOptionsConverter.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.server; 2 | 3 | import io.vertx.core.json.JsonObject; 4 | import io.vertx.core.json.JsonArray; 5 | import java.time.Instant; 6 | import java.time.format.DateTimeFormatter; 7 | 8 | /** 9 | * Converter and mapper for {@link io.vertx.grpc.server.GrpcServerOptions}. 10 | * NOTE: This class has been automatically generated from the {@link io.vertx.grpc.server.GrpcServerOptions} original class using Vert.x codegen. 11 | */ 12 | public class GrpcServerOptionsConverter { 13 | 14 | static void fromJson(Iterable> json, GrpcServerOptions obj) { 15 | for (java.util.Map.Entry member : json) { 16 | switch (member.getKey()) { 17 | case "enabledProtocols": 18 | if (member.getValue() instanceof JsonArray) { 19 | ((Iterable)member.getValue()).forEach( item -> { 20 | if (item instanceof String) 21 | obj.addEnabledProtocol(io.vertx.grpc.server.GrpcProtocol.valueOf((String)item)); 22 | }); 23 | } 24 | break; 25 | case "scheduleDeadlineAutomatically": 26 | if (member.getValue() instanceof Boolean) { 27 | obj.setScheduleDeadlineAutomatically((Boolean)member.getValue()); 28 | } 29 | break; 30 | case "deadlinePropagation": 31 | if (member.getValue() instanceof Boolean) { 32 | obj.setDeadlinePropagation((Boolean)member.getValue()); 33 | } 34 | break; 35 | case "maxMessageSize": 36 | if (member.getValue() instanceof Number) { 37 | obj.setMaxMessageSize(((Number)member.getValue()).longValue()); 38 | } 39 | break; 40 | } 41 | } 42 | } 43 | 44 | static void toJson(GrpcServerOptions obj, JsonObject json) { 45 | toJson(obj, json.getMap()); 46 | } 47 | 48 | static void toJson(GrpcServerOptions obj, java.util.Map json) { 49 | if (obj.getEnabledProtocols() != null) { 50 | JsonArray array = new JsonArray(); 51 | obj.getEnabledProtocols().forEach(item -> array.add(item.name())); 52 | json.put("enabledProtocols", array); 53 | } 54 | json.put("scheduleDeadlineAutomatically", obj.getScheduleDeadlineAutomatically()); 55 | json.put("deadlinePropagation", obj.getDeadlinePropagation()); 56 | json.put("maxMessageSize", obj.getMaxMessageSize()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/GrpcProtocol.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.server; 2 | 3 | import io.vertx.core.http.HttpVersion; 4 | 5 | import java.util.EnumSet; 6 | 7 | /** 8 | * Describe the underlying gRPC protocol. 9 | */ 10 | public enum GrpcProtocol { 11 | 12 | /** 13 | * gRPC over HTTP/2 14 | */ 15 | HTTP_2("application/grpc", EnumSet.of(HttpVersion.HTTP_2)), 16 | 17 | /** 18 | * gRPC transcoding HTTP/1 19 | */ 20 | TRANSCODING("application/json", EnumSet.allOf(HttpVersion.class)), 21 | 22 | /** 23 | * gRPC Web 24 | */ 25 | WEB("application/grpc-web", EnumSet.allOf(HttpVersion.class)), 26 | 27 | /** 28 | * gRPC Web text 29 | */ 30 | WEB_TEXT("application/grpc-web-text", EnumSet.allOf(HttpVersion.class)); 31 | 32 | private final String mediaType; 33 | private final EnumSet acceptedVersions; 34 | 35 | GrpcProtocol(String mediaType, EnumSet acceptedVersions) { 36 | this.mediaType = mediaType; 37 | this.acceptedVersions = acceptedVersions; 38 | } 39 | 40 | /** 41 | * @return whether the protocol accepts the HTTP {@code version} 42 | */ 43 | public boolean accepts(HttpVersion version) { 44 | return acceptedVersions.contains(version); 45 | } 46 | 47 | /** 48 | * @return the HTTP media type 49 | */ 50 | public String mediaType() { 51 | return mediaType; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/GrpcServerRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.server; 12 | 13 | import io.vertx.codegen.annotations.CacheReturn; 14 | import io.vertx.codegen.annotations.Fluent; 15 | import io.vertx.codegen.annotations.Nullable; 16 | import io.vertx.codegen.annotations.VertxGen; 17 | import io.vertx.core.Handler; 18 | import io.vertx.core.Timer; 19 | import io.vertx.core.http.HttpConnection; 20 | import io.vertx.grpc.common.GrpcError; 21 | import io.vertx.grpc.common.GrpcMessage; 22 | import io.vertx.grpc.common.GrpcReadStream; 23 | import io.vertx.grpc.common.ServiceName; 24 | 25 | import java.time.Instant; 26 | 27 | @VertxGen 28 | public interface GrpcServerRequest extends GrpcReadStream { 29 | 30 | /** 31 | * @return the service name 32 | */ 33 | @CacheReturn 34 | ServiceName serviceName(); 35 | 36 | /** 37 | * @return the method name 38 | */ 39 | @CacheReturn 40 | String methodName(); 41 | 42 | /** 43 | * @return the full method name sent by the client 44 | */ 45 | @CacheReturn 46 | String fullMethodName(); 47 | 48 | /** 49 | * @return the response 50 | */ 51 | @CacheReturn 52 | GrpcServerResponse response(); 53 | 54 | @Override 55 | @Fluent 56 | GrpcServerRequest messageHandler(@Nullable Handler handler); 57 | 58 | @Override 59 | @Fluent 60 | GrpcServerRequest errorHandler(@Nullable Handler handler); 61 | 62 | @Override 63 | GrpcServerRequest exceptionHandler(@Nullable Handler handler); 64 | 65 | @Override 66 | GrpcServerRequest handler(@Nullable Handler handler); 67 | 68 | @Override 69 | GrpcServerRequest pause(); 70 | 71 | @Override 72 | GrpcServerRequest resume(); 73 | 74 | @Override 75 | GrpcServerRequest fetch(long amount); 76 | 77 | @Override 78 | GrpcServerRequest endHandler(@Nullable Handler endHandler); 79 | 80 | /** 81 | * @return the underlying HTTP connection 82 | */ 83 | HttpConnection connection(); 84 | 85 | /** 86 | * @return the request timeout sent by the client or {@code 0L} if none. 87 | */ 88 | long timeout(); 89 | 90 | /** 91 | * @return the request deadline or {@code null} when no deadline has been scheduled 92 | */ 93 | Timer deadline(); 94 | 95 | } 96 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/GrpcServerResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.server; 12 | 13 | import io.vertx.codegen.annotations.Fluent; 14 | import io.vertx.codegen.annotations.Nullable; 15 | import io.vertx.codegen.annotations.VertxGen; 16 | import io.vertx.core.Future; 17 | import io.vertx.core.Handler; 18 | import io.vertx.core.MultiMap; 19 | import io.vertx.core.streams.ReadStream; 20 | import io.vertx.grpc.common.GrpcStatus; 21 | import io.vertx.grpc.common.GrpcWriteStream; 22 | import io.vertx.grpc.common.WireFormat; 23 | 24 | @VertxGen 25 | public interface GrpcServerResponse extends GrpcWriteStream { 26 | 27 | /** 28 | * Set the grpc status response 29 | * 30 | * @param status the status 31 | * @return a reference to this, so the API can be used fluently 32 | */ 33 | @Fluent 34 | GrpcServerResponse status(GrpcStatus status); 35 | 36 | /** 37 | * Set the grpc status response message 38 | * 39 | * @param msg the message 40 | * @return a reference to this, so the API can be used fluently 41 | */ 42 | @Fluent 43 | GrpcServerResponse statusMessage(String msg); 44 | 45 | @Fluent 46 | GrpcServerResponse encoding(String encoding); 47 | 48 | @Fluent 49 | GrpcServerResponse format(WireFormat format); 50 | 51 | /** 52 | * @return the {@link MultiMap} to write metadata trailers 53 | */ 54 | MultiMap trailers(); 55 | 56 | @Override 57 | GrpcServerResponse exceptionHandler(@Nullable Handler handler); 58 | 59 | @Override 60 | GrpcServerResponse setWriteQueueMaxSize(int maxSize); 61 | 62 | @Override 63 | GrpcServerResponse drainHandler(@Nullable Handler handler); 64 | 65 | default Future send(Resp item) { 66 | return end(item); 67 | } 68 | 69 | default Future send(ReadStream body) { 70 | return body.pipeTo(this); 71 | } 72 | 73 | /** 74 | * End the stream with an appropriate status message, when {@code failure} is 75 | * 76 | *
      77 | *
    • {@link StatusException}, set status to {@link StatusException#status()} and status message to {@link StatusException#message()}
    • 78 | *
    • {@link UnsupportedOperationException} returns {@link GrpcStatus#UNIMPLEMENTED}
    • 79 | *
    • otherwise returns {@link GrpcStatus#UNKNOWN}
    • 80 | *
    81 | * 82 | * @param failure the failure 83 | */ 84 | void fail(Throwable failure); 85 | 86 | } 87 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/ServiceBuilder.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.server; 2 | 3 | import io.vertx.core.Handler; 4 | import io.vertx.grpc.common.ServiceMethod; 5 | 6 | /** 7 | * A builder for creating and configuring a {@link Service}. This interface allows you to bind 8 | * service methods to their respective handlers, which define how requests to those methods 9 | * are processed. 10 | */ 11 | public interface ServiceBuilder { 12 | 13 | /** 14 | * Bind a service method call handler that handles any call made to the server for the {@code fullMethodName} method. 15 | * 16 | * @param handler the service method call handler 17 | * @param serviceMethod the service method 18 | * @return a reference to this, so the API can be used fluently 19 | */ 20 | ServiceBuilder bind(ServiceMethod serviceMethod, Handler> handler); 21 | 22 | /** 23 | * Constructs and returns a {@link Service} instance based on the current configuration of the builder. 24 | * 25 | * @return a configured {@link Service} instance 26 | */ 27 | Service build(); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/StatusException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.server; 12 | 13 | import io.vertx.core.VertxException; 14 | import io.vertx.grpc.common.GrpcStatus; 15 | 16 | /** 17 | * A glorified GOTO forcing a response status. 18 | */ 19 | public final class StatusException extends VertxException { 20 | 21 | private final GrpcStatus status; 22 | private final String message; 23 | 24 | public StatusException(GrpcStatus status) { 25 | super("Grpc status " + status.name()); 26 | this.status = status; 27 | this.message = null; 28 | } 29 | 30 | public StatusException(GrpcStatus status, String message) { 31 | super("Grpc status " + status.name()); 32 | this.status = status; 33 | this.message = message; 34 | } 35 | 36 | /** 37 | * @return the status 38 | */ 39 | public GrpcStatus status() { 40 | return status; 41 | } 42 | 43 | /** 44 | * @return the status message 45 | */ 46 | public String message() { 47 | return message; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/impl/GrpcHttpInvoker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.server.impl; 12 | 13 | import io.vertx.core.http.HttpServerRequest; 14 | import io.vertx.grpc.common.ServiceMethod; 15 | 16 | /** 17 | * An interface that defines the behavior for invoking gRPC services based on an incoming HTTP request. This is designed to bridge HTTP requests to corresponding gRPC service 18 | * methods by creating a {@link GrpcInvocation} instance that facilitates the interaction. 19 | */ 20 | public interface GrpcHttpInvoker { 21 | 22 | /** 23 | * Accepts an incoming HTTP server request and associates it with a gRPC service method. This method creates a {@code GrpcInvocation} instance to facilitate communication between 24 | * the HTTP request and the specified gRPC service method. 25 | * 26 | * @param the type of the request message for the gRPC service method 27 | * @param the type of the response message for the gRPC service method 28 | * @param request the HTTP server request to be processed 29 | * @param serviceMethod the gRPC service method that corresponds to the incoming request 30 | * @return an instance of {@code GrpcInvocation} that represents the invocation of the gRPC service method 31 | */ 32 | GrpcInvocation accept(HttpServerRequest request, ServiceMethod serviceMethod); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/impl/GrpcInvocation.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.server.impl; 2 | 3 | /** 4 | * A class representing a gRPC invocation that connects a gRPC server request with a gRPC server response. 5 | */ 6 | public class GrpcInvocation { 7 | 8 | final GrpcServerRequestImpl grpcRequest; 9 | final GrpcServerResponseImpl grpcResponse; 10 | 11 | public GrpcInvocation(GrpcServerRequestImpl grpcRequest, GrpcServerResponseImpl grpcResponse) { 12 | this.grpcRequest = grpcRequest; 13 | this.grpcResponse = grpcResponse; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/impl/Http2GrpcServerRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.server.impl; 12 | 13 | import io.vertx.core.http.HttpServerRequest; 14 | import io.vertx.core.internal.ContextInternal; 15 | import io.vertx.grpc.common.GrpcHeaderNames; 16 | import io.vertx.grpc.common.GrpcMessageDecoder; 17 | import io.vertx.grpc.common.WireFormat; 18 | import io.vertx.grpc.common.impl.GrpcMethodCall; 19 | import io.vertx.grpc.common.impl.Http2GrpcMessageDeframer; 20 | import io.vertx.grpc.server.GrpcProtocol; 21 | 22 | public class Http2GrpcServerRequest extends GrpcServerRequestImpl { 23 | 24 | public Http2GrpcServerRequest(ContextInternal context, GrpcProtocol protocol, WireFormat format, HttpServerRequest httpRequest, GrpcMessageDecoder messageDecoder, GrpcMethodCall methodCall) { 25 | super(context, protocol, format, httpRequest, new Http2GrpcMessageDeframer(httpRequest.headers().get(GrpcHeaderNames.GRPC_ENCODING), format), messageDecoder, methodCall); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/impl/Http2GrpcServerResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.server.impl; 12 | 13 | import io.vertx.core.MultiMap; 14 | import io.vertx.core.http.HttpServerResponse; 15 | import io.vertx.core.internal.ContextInternal; 16 | import io.vertx.grpc.common.GrpcHeaderNames; 17 | import io.vertx.grpc.common.GrpcMessageEncoder; 18 | import io.vertx.grpc.server.GrpcProtocol; 19 | 20 | public class Http2GrpcServerResponse extends GrpcServerResponseImpl { 21 | 22 | private final HttpServerResponse httpResponse; 23 | 24 | public Http2GrpcServerResponse(ContextInternal context, GrpcServerRequestImpl request, GrpcProtocol protocol, HttpServerResponse httpResponse, GrpcMessageEncoder encoder) { 25 | super(context, request, protocol, httpResponse, encoder); 26 | 27 | this.httpResponse = httpResponse; 28 | } 29 | 30 | @Override 31 | protected void encodeGrpcHeaders(MultiMap grpcHeaders, MultiMap httpHeaders) { 32 | super.encodeGrpcHeaders(grpcHeaders, httpHeaders); 33 | httpHeaders.set(GrpcHeaderNames.GRPC_ENCODING, encoding); 34 | httpHeaders.set(GrpcHeaderNames.GRPC_ACCEPT_ENCODING, "gzip"); 35 | } 36 | 37 | @Override 38 | protected void setTrailers(MultiMap grpcTrailers) { 39 | MultiMap httpTrailers; 40 | if (isTrailersOnly()) { 41 | httpTrailers = httpResponse.headers(); 42 | } else { 43 | httpTrailers = httpResponse.trailers(); 44 | } 45 | encodeGrpcTrailers(grpcTrailers, httpTrailers); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/impl/MountPoint.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.server.impl; 2 | 3 | import java.util.List; 4 | 5 | public interface MountPoint { 6 | 7 | List paths(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/io/vertx/grpc/server/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | @ModuleGen(name = "vertx-grpc-server", groupPackage = "io.vertx") 12 | package io.vertx.grpc.server; 13 | 14 | import io.vertx.codegen.annotations.ModuleGen; 15 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module io.vertx.grpc.server { 2 | 3 | requires static io.vertx.docgen; 4 | requires static io.vertx.codegen.json; 5 | 6 | requires io.vertx.core.logging; 7 | requires io.vertx.core; 8 | requires io.vertx.grpc.common; 9 | requires io.vertx.codegen.api; 10 | requires io.netty.codec; 11 | requires io.netty.buffer; 12 | requires com.google.protobuf; 13 | 14 | uses io.vertx.grpc.server.impl.GrpcHttpInvoker; 15 | 16 | exports io.vertx.grpc.server; 17 | exports io.vertx.grpc.server.impl to io.vertx.grpc.transcoding; 18 | } 19 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/test/java/io/vertx/tests/server/ProtocolSupportTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.tests.server; 12 | 13 | import io.vertx.core.http.*; 14 | import io.vertx.ext.unit.TestContext; 15 | import io.vertx.grpc.common.GrpcHeaderNames; 16 | import io.vertx.grpc.server.GrpcProtocol; 17 | import io.vertx.grpc.server.GrpcServer; 18 | import io.vertx.grpc.server.GrpcServerOptions; 19 | import org.junit.Test; 20 | 21 | public class ProtocolSupportTest extends ServerTestBase { 22 | 23 | private HttpClient client; 24 | 25 | @Test 26 | public void testDisableHTTP2(TestContext should) { 27 | testDisableProtocol(should, "application/grpc", GrpcProtocol.HTTP_2); 28 | } 29 | 30 | @Test 31 | public void testDisableWeb(TestContext should) { 32 | testDisableProtocol(should, "application/grpc-web", GrpcProtocol.WEB); 33 | } 34 | 35 | private void testDisableProtocol(TestContext should, String contentType, GrpcProtocol protocol) { 36 | 37 | startServer(GrpcServer.server(vertx, new GrpcServerOptions().removeEnabledProtocol(protocol))); 38 | 39 | client = vertx.createHttpClient(new HttpClientOptions() 40 | .setProtocolVersion(HttpVersion.HTTP_2) 41 | .setHttp2ClearTextUpgrade(true) 42 | ); 43 | 44 | client 45 | .request(HttpMethod.POST, 8080, "localhost", "/") 46 | .compose(request -> { 47 | request.putHeader(GrpcHeaderNames.GRPC_ENCODING, "identity"); 48 | request.putHeader(HttpHeaders.CONTENT_TYPE, contentType); 49 | request.send(); 50 | return request.response() 51 | .map(resp -> resp.statusCode()); 52 | }).onComplete(should.asyncAssertSuccess(status -> { 53 | should.assertEquals(415, status); 54 | })); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/test/java/io/vertx/tests/server/WorkerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.tests.server; 12 | 13 | import io.grpc.*; 14 | import io.vertx.core.http.HttpServer; 15 | import io.vertx.core.internal.ContextInternal; 16 | import io.vertx.core.internal.VertxInternal; 17 | import io.vertx.ext.unit.Async; 18 | import io.vertx.ext.unit.TestContext; 19 | import io.vertx.grpc.server.GrpcServer; 20 | import io.vertx.grpc.server.GrpcServerResponse; 21 | import io.vertx.tests.common.grpc.Reply; 22 | import io.vertx.tests.common.grpc.Request; 23 | import io.vertx.tests.common.grpc.TestServiceGrpc; 24 | import org.junit.Test; 25 | 26 | public class WorkerTest extends ServerTestBase { 27 | 28 | @Test 29 | public void testWorker(TestContext should) throws Exception { 30 | ContextInternal worker = ((VertxInternal) vertx).createWorkerContext(); 31 | Async latch = should.async(); 32 | worker.runOnContext(v -> { 33 | HttpServer httpServer = createServer(GrpcServer 34 | .server(vertx) 35 | .callHandler(UNARY, call -> { 36 | call.handler(helloRequest -> { 37 | Reply helloReply = Reply.newBuilder().setMessage("Hello " + helloRequest.getName()).build(); 38 | GrpcServerResponse response = call.response(); 39 | response.end(helloReply); 40 | }); 41 | })); 42 | httpServer.listen().onComplete(should.asyncAssertSuccess(v2 -> latch.complete())); 43 | }); 44 | latch.awaitSuccess(); 45 | 46 | channel = ManagedChannelBuilder.forAddress("localhost", port) 47 | .usePlaintext() 48 | .build(); 49 | 50 | TestServiceGrpc.TestServiceBlockingStub stub = TestServiceGrpc.newBlockingStub(channel); 51 | 52 | Request request = Request.newBuilder().setName("Julien").build(); 53 | Reply res = stub.unary(request); 54 | should.assertEquals("Hello Julien", res.getMessage()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/test/java/io/vertx/tests/server/web/BinaryServerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | 12 | package io.vertx.tests.server.web; 13 | 14 | import io.vertx.core.MultiMap; 15 | import io.vertx.core.buffer.Buffer; 16 | import io.vertx.core.http.HttpHeaders; 17 | 18 | import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; 19 | import static io.vertx.grpc.common.GrpcMediaType.GRPC_WEB_PROTO; 20 | 21 | /** 22 | * Tests for gRPC-Web server using the binary protocol. 23 | */ 24 | public class BinaryServerTest extends ServerTestBase { 25 | 26 | @Override 27 | protected MultiMap requestHeaders() { 28 | return HttpHeaders.headers() 29 | .add(CONTENT_TYPE, GRPC_WEB_PROTO) 30 | .add(USER_AGENT, GRPC_WEB_JAVASCRIPT_0_1) 31 | .add(GRPC_WEB, TRUE); 32 | } 33 | 34 | @Override 35 | protected CharSequence responseContentType() { 36 | return "application/grpc-web"; 37 | } 38 | 39 | @Override 40 | protected Buffer decodeBody(Buffer buffer) { 41 | return buffer; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/test/java/io/vertx/tests/server/web/TextServerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | 12 | package io.vertx.tests.server.web; 13 | 14 | import com.google.protobuf.Message; 15 | import io.vertx.core.MultiMap; 16 | import io.vertx.core.buffer.Buffer; 17 | import io.vertx.core.http.HttpHeaders; 18 | 19 | import java.util.Base64; 20 | 21 | import static io.vertx.core.http.HttpHeaders.ACCEPT; 22 | import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; 23 | import static io.vertx.grpc.common.GrpcMediaType.GRPC_WEB_TEXT; 24 | import static io.vertx.grpc.common.GrpcMediaType.GRPC_WEB_TEXT_PROTO; 25 | import static org.junit.Assert.assertEquals; 26 | 27 | /** 28 | * Tests for gRPC-Web server using the text (base64) protocol. 29 | */ 30 | public class TextServerTest extends ServerTestBase { 31 | 32 | private static final Base64.Encoder ENCODER = Base64.getEncoder(); 33 | private static final Base64.Decoder DECODER = Base64.getDecoder(); 34 | 35 | @Override 36 | protected MultiMap requestHeaders() { 37 | return HttpHeaders.headers() 38 | .add(ACCEPT, GRPC_WEB_TEXT) 39 | .add(CONTENT_TYPE, GRPC_WEB_TEXT) 40 | .add(USER_AGENT, GRPC_WEB_JAVASCRIPT_0_1) 41 | .add(GRPC_WEB, TRUE); 42 | } 43 | 44 | @Override 45 | protected CharSequence responseContentType() { 46 | return "application/grpc-web-text"; 47 | } 48 | 49 | @Override 50 | protected Buffer encode(Message message) { 51 | Buffer buffer = super.encode(message); 52 | // The whole message must be encoded at once when sending 53 | return Buffer.buffer(ENCODER.encode(buffer.getBytes())); 54 | } 55 | 56 | @Override 57 | protected Buffer decodeBody(Buffer buffer) { 58 | // The server sends base64 encoded chunks of arbitrary size 59 | // All we know is that a 4-bytes block is always a valid base64 payload 60 | assertEquals(0, buffer.length() % 4); 61 | Buffer res = Buffer.buffer(); 62 | for (int i = 0; i < buffer.length(); i += 4) { 63 | byte[] block = buffer.getBytes(i, i + 4); 64 | res.appendBytes(DECODER.decode(block)); 65 | } 66 | return res; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | open module io.vertx.tests.server { 2 | requires com.google.common; 3 | requires com.google.protobuf; 4 | requires com.google.protobuf.util; 5 | requires io.grpc; 6 | requires io.grpc.stub; 7 | requires io.grpc.util; 8 | requires io.grpc.protobuf; 9 | requires io.vertx.core; 10 | requires io.vertx.grpc.common; 11 | requires io.vertx.grpc.server; 12 | requires io.vertx.testing.unit; 13 | requires io.vertx.tests.common; 14 | requires junit; 15 | requires testcontainers; 16 | exports io.vertx.tests.server.grpc.web; 17 | exports io.vertx.tests.server; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/test/proto/empty.proto: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2015 gRPC authors. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | syntax = "proto3"; 17 | 18 | option java_multiple_files = true; 19 | option java_package = "io.vertx.tests.server.grpc.empty"; 20 | 21 | package grpc.testing; 22 | 23 | // An empty message that you canre-use to avoid defining duplicated empty 24 | // messages in your project. A typical example is to use it as argument or the 25 | // return value of a service API. For instance: 26 | // 27 | // service Foo { 28 | // rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; 29 | // }; 30 | // 31 | message Empty {} 32 | -------------------------------------------------------------------------------- /vertx-grpc-server/src/test/proto/web.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_multiple_files = true; 4 | option java_package = "io.vertx.tests.server.grpc.web"; 5 | 6 | package io.vertx.tests.server.grpc.web; 7 | 8 | service TestService { 9 | rpc EmptyCall(Empty) returns (Empty); 10 | rpc UnaryCall(EchoRequest) returns (EchoResponse); 11 | rpc UnaryCallBody(EchoRequestBody) returns (EchoResponse); 12 | rpc UnaryCallResponseBody(EchoRequest) returns (EchoResponseBody); 13 | rpc StreamingCall(StreamingRequest) returns (stream StreamingResponse); 14 | } 15 | 16 | service UnimplementedService { 17 | rpc UnimplementedCall(Empty) returns (Empty); // Do not implement 18 | } 19 | 20 | message Empty {} 21 | 22 | message EchoRequest { 23 | string payload = 1; 24 | } 25 | 26 | message EchoRequestBody { 27 | EchoRequest request = 1; 28 | } 29 | 30 | message EchoResponse { 31 | string payload = 1; 32 | } 33 | 34 | message EchoResponseBody { 35 | EchoResponse response = 1; 36 | } 37 | 38 | message StreamingRequest { 39 | repeated int32 response_size = 1; 40 | } 41 | 42 | message StreamingResponse { 43 | string payload = 1; 44 | } 45 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/java/io/vertx/grpc/transcoding/TranscodingServiceMethod.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.transcoding; 2 | 3 | import io.vertx.codegen.annotations.GenIgnore; 4 | import io.vertx.codegen.annotations.Unstable; 5 | import io.vertx.grpc.common.GrpcMessageDecoder; 6 | import io.vertx.grpc.common.GrpcMessageEncoder; 7 | import io.vertx.grpc.common.ServiceMethod; 8 | import io.vertx.grpc.common.ServiceName; 9 | import io.vertx.grpc.transcoding.impl.TranscodingServiceMethodImpl; 10 | 11 | @GenIgnore(GenIgnore.PERMITTED_TYPE) 12 | @Unstable("Transcoding is in tech preview") 13 | public interface TranscodingServiceMethod extends ServiceMethod { 14 | 15 | static TranscodingServiceMethod server(ServiceName serviceName, 16 | String methodName, 17 | GrpcMessageEncoder encoder, 18 | GrpcMessageDecoder decoder) { 19 | return new TranscodingServiceMethodImpl<>(serviceName, methodName, encoder, decoder); 20 | } 21 | 22 | static TranscodingServiceMethod server(ServiceName serviceName, 23 | String methodName, 24 | GrpcMessageEncoder encoder, 25 | GrpcMessageDecoder decoder, 26 | MethodTranscodingOptions options) { 27 | return new TranscodingServiceMethodImpl<>(serviceName, methodName, encoder, decoder, options); 28 | } 29 | 30 | static TranscodingServiceMethod server(ServiceMethod serviceMethod, 31 | MethodTranscodingOptions options) { 32 | return server(serviceMethod.serviceName(), serviceMethod.methodName(), serviceMethod.encoder(), serviceMethod.decoder(), options); 33 | } 34 | 35 | MethodTranscodingOptions options(); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/java/io/vertx/grpc/transcoding/impl/GrpcTranscodingError.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.transcoding.impl; 2 | 3 | public enum GrpcTranscodingError { 4 | 5 | CANCELLED(0x01, 408, "Request timeout"), 6 | UNKNOWN(0x02, 500, "Internal Server Error"), 7 | INVALID_ARGUMENT(0x03, 400, "Invalid Argument"), 8 | DEADLINE_EXCEEDED(0x04, 504, "Deadline Exceeded"), 9 | NOT_FOUND(0x05, 404, "Not Found"), 10 | ALREADY_EXISTS(0x06, 409, "Already Exists"), 11 | PERMISSION_DENIED(0x07, 403, "Permission Denied"), 12 | RESOURCE_EXHAUSTED(0x08, 429, "Resource Exhausted"), 13 | FAILED_PRECONDITION(0x09, 400, "Failed Precondition"), 14 | ABORTED(0x0a, 409, "Aborted"), 15 | OUT_OF_RANGE(0x0b, 400, "Out of Range"), 16 | UNIMPLEMENTED(0x0c, 501, "Unimplemented"), 17 | INTERNAL(0x0d, 500, "Internal Server Error"), 18 | UNAVAILABLE(0x0e, 503, "Service Unavailable"), 19 | DATA_LOSS(0x0f, 500, "Data Loss"), 20 | UNAUTHENTICATED(0x10, 401, "Unauthenticated"); 21 | 22 | private final int http2StatusCode; 23 | private final int httpStatusCode; 24 | private final String message; 25 | 26 | GrpcTranscodingError(int http2StatusCode, int httpStatusCode, String message) { 27 | this.http2StatusCode = http2StatusCode; 28 | this.httpStatusCode = httpStatusCode; 29 | this.message = message; 30 | } 31 | 32 | public static GrpcTranscodingError fromHttp2Code(int code) { 33 | for (GrpcTranscodingError error : values()) { 34 | if (error.http2StatusCode == code) { 35 | return error; 36 | } 37 | } 38 | return UNKNOWN; 39 | } 40 | 41 | public int getHttp2StatusCode() { 42 | return http2StatusCode; 43 | } 44 | 45 | public int getHttpStatusCode() { 46 | return httpStatusCode; 47 | } 48 | 49 | public String getMessage() { 50 | return message; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/java/io/vertx/grpc/transcoding/impl/PathMatcherLookupResult.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.transcoding.impl; 2 | 3 | import io.vertx.grpc.transcoding.impl.config.HttpVariableBinding; 4 | 5 | import java.util.List; 6 | 7 | public class PathMatcherLookupResult { 8 | 9 | private final String method; 10 | private final List variableBindings; 11 | private final String bodyFieldPath; 12 | 13 | public PathMatcherLookupResult(String method, List variableBindings, String bodyFieldPath) { 14 | this.method = method; 15 | this.variableBindings = variableBindings; 16 | this.bodyFieldPath = bodyFieldPath; 17 | } 18 | 19 | public String getMethod() { 20 | return method; 21 | } 22 | 23 | public List getVariableBindings() { 24 | return variableBindings; 25 | } 26 | 27 | public String getBodyFieldPath() { 28 | return bodyFieldPath; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/java/io/vertx/grpc/transcoding/impl/PathMatcherMethodData.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.transcoding.impl; 2 | 3 | import io.vertx.grpc.transcoding.impl.config.HttpTemplateVariable; 4 | 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | public class PathMatcherMethodData { 9 | 10 | private String method; 11 | private List variables; 12 | private String bodyFieldPath; 13 | private Set systemQueryParameterNames; 14 | 15 | public String getMethod() { 16 | return method; 17 | } 18 | 19 | public void setMethod(String method) { 20 | this.method = method; 21 | } 22 | 23 | public List getVariables() { 24 | return variables; 25 | } 26 | 27 | public void setVariables(List variables) { 28 | this.variables = variables; 29 | } 30 | 31 | public String getBodyFieldPath() { 32 | return bodyFieldPath; 33 | } 34 | 35 | public void setBodyFieldPath(String bodyFieldPath) { 36 | this.bodyFieldPath = bodyFieldPath; 37 | } 38 | 39 | public Set getSystemQueryParameterNames() { 40 | return systemQueryParameterNames; 41 | } 42 | 43 | public void setSystemQueryParameterNames(Set systemQueryParameterNames) { 44 | this.systemQueryParameterNames = systemQueryParameterNames; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/java/io/vertx/grpc/transcoding/impl/TranscodingGrpcServerRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.transcoding.impl; 12 | 13 | import io.vertx.core.buffer.Buffer; 14 | import io.vertx.core.http.HttpServerRequest; 15 | import io.vertx.core.internal.ContextInternal; 16 | import io.vertx.core.json.DecodeException; 17 | import io.vertx.grpc.common.CodecException; 18 | import io.vertx.grpc.common.GrpcMessage; 19 | import io.vertx.grpc.common.GrpcMessageDecoder; 20 | import io.vertx.grpc.common.WireFormat; 21 | import io.vertx.grpc.common.impl.GrpcMethodCall; 22 | import io.vertx.grpc.server.GrpcProtocol; 23 | import io.vertx.grpc.server.impl.GrpcServerRequestImpl; 24 | import io.vertx.grpc.transcoding.impl.config.HttpVariableBinding; 25 | 26 | import java.util.List; 27 | 28 | public class TranscodingGrpcServerRequest extends GrpcServerRequestImpl { 29 | 30 | final String transcodingRequestBody; 31 | final List bindings; 32 | 33 | public TranscodingGrpcServerRequest(ContextInternal context, 34 | HttpServerRequest httpRequest, 35 | String transcodingRequestBody, 36 | List bindings, GrpcMessageDecoder messageDecoder, 37 | GrpcMethodCall methodCall) { 38 | super(context, GrpcProtocol.TRANSCODING, WireFormat.JSON, httpRequest, new TranscodingMessageDeframer(), new GrpcMessageDecoder<>() { 39 | @Override 40 | public Req decode(GrpcMessage msg) throws CodecException { 41 | Buffer transcoded; 42 | try { 43 | transcoded = MessageWeaver.weaveRequestMessage(msg.payload(), bindings, transcodingRequestBody); 44 | } catch (DecodeException e) { 45 | throw new CodecException(e); 46 | } 47 | return messageDecoder.decode(GrpcMessage.message("identity", WireFormat.JSON, transcoded)); 48 | } 49 | @Override 50 | public boolean accepts(WireFormat format) { 51 | return messageDecoder.accepts(format); 52 | } 53 | }, methodCall); 54 | 55 | this.transcodingRequestBody = transcodingRequestBody; 56 | this.bindings = bindings; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/java/io/vertx/grpc/transcoding/impl/TranscodingInvoker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2025 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpc.transcoding.impl; 12 | 13 | import io.vertx.core.http.HttpServerRequest; 14 | import io.vertx.grpc.common.ServiceMethod; 15 | import io.vertx.grpc.server.impl.GrpcHttpInvoker; 16 | import io.vertx.grpc.server.impl.GrpcInvocation; 17 | 18 | public class TranscodingInvoker implements GrpcHttpInvoker { 19 | 20 | @Override 21 | public GrpcInvocation accept(HttpServerRequest request, ServiceMethod serviceMethod) { 22 | TranscodingServiceMethodImpl transcodingServiceMethod; 23 | 24 | if (serviceMethod instanceof TranscodingServiceMethodImpl) { 25 | transcodingServiceMethod = (TranscodingServiceMethodImpl) serviceMethod; 26 | } else { 27 | transcodingServiceMethod = new TranscodingServiceMethodImpl<>( 28 | serviceMethod.serviceName(), 29 | serviceMethod.methodName(), 30 | serviceMethod.encoder(), 31 | serviceMethod.decoder() 32 | ); 33 | } 34 | 35 | return transcodingServiceMethod.accept(request); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/java/io/vertx/grpc/transcoding/impl/config/HttpTemplate.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.transcoding.impl.config; 2 | 3 | import io.vertx.codegen.annotations.DataObject; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Represents an HTTP template used in gRPC transcoding. 10 | *

    11 | * This interface defines methods for accessing the components of a parsed HTTP template string, including the segments, verb, and variables. 12 | * 13 | * @author Based on grpc-httpjson-transcoding 14 | */ 15 | @DataObject 16 | public class HttpTemplate { 17 | 18 | private final List segments; 19 | private final String verb; 20 | private final List variables; 21 | 22 | public HttpTemplate(List segments, String verb, List variables) { 23 | this.segments = segments; 24 | this.verb = verb; 25 | this.variables = variables; 26 | } 27 | 28 | /** 29 | * Parses the given HTTP template string. 30 | * 31 | * @param template The HTTP template string to parse. 32 | * @return The parsed {@code HttpTemplate}, or {@code null} if the parsing failed. 33 | */ 34 | public static HttpTemplate parse(String template) { 35 | if (template.equals("/")) { 36 | return new HttpTemplate(new ArrayList<>(), "", new ArrayList<>()); 37 | } 38 | 39 | HttpTemplateParser parser = new HttpTemplateParser(template); 40 | if (!parser.parse() || !parser.validateParts()) { 41 | return null; 42 | } 43 | 44 | return new HttpTemplate(parser.segments(), parser.verb(), parser.variables()); 45 | } 46 | 47 | /** 48 | * Returns the list of segments in the parsed template. 49 | * 50 | * @return The list of segments. 51 | */ 52 | public List getSegments() { 53 | return segments; 54 | } 55 | 56 | /** 57 | * Returns the verb in the parsed template. 58 | * 59 | * @return The verb. 60 | */ 61 | public String getVerb() { 62 | return verb; 63 | } 64 | 65 | /** 66 | * Returns the list of variables in the parsed template. 67 | * 68 | * @return The list of variables. 69 | */ 70 | public List getVariables() { 71 | return variables; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/java/io/vertx/grpc/transcoding/impl/config/HttpVariableBinding.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.transcoding.impl.config; 2 | 3 | import io.vertx.codegen.annotations.DataObject; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Represents a binding between an HTTP request variable (from path or query parameters) and its corresponding gRPC message field path. This interface is used during HTTP-to-gRPC 9 | * transcoding to map HTTP request variables to their appropriate locations in the gRPC message. 10 | *

    11 | * The binding consists of: - A field path representing the location in the gRPC message where the value should be placed - The actual value extracted from the HTTP request 12 | * 13 | * @author Based on grpc-httpjson-transcoding 14 | */ 15 | @DataObject 16 | public class HttpVariableBinding { 17 | 18 | private List fieldPath; 19 | private String value; 20 | 21 | public HttpVariableBinding() { 22 | } 23 | 24 | public HttpVariableBinding(List fieldPath, String value) { 25 | this.fieldPath = fieldPath; 26 | this.value = value; 27 | } 28 | 29 | /** 30 | * Gets the field path that describes where in the gRPC message the value should be placed. 31 | * 32 | * @return A list of field names representing the path in the gRPC message 33 | */ 34 | public List getFieldPath() { 35 | return fieldPath; 36 | } 37 | 38 | /** 39 | * Sets the field path that describes where in the gRPC message the value should be placed. 40 | * 41 | * @param fieldPath A list of field names representing the path in the gRPC message 42 | */ 43 | public void setFieldPath(List fieldPath) { 44 | this.fieldPath = fieldPath; 45 | } 46 | 47 | /** 48 | * Gets the value that was extracted from the HTTP request. 49 | * 50 | * @return The string value to be bound to the specified field path 51 | */ 52 | public String getValue() { 53 | return value; 54 | } 55 | 56 | /** 57 | * Sets the value that should be bound to the specified field path. 58 | * 59 | * @param value The string value to be bound to the specified field path 60 | */ 61 | public void setValue(String value) { 62 | this.value = value; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/java/io/vertx/grpc/transcoding/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | @ModuleGen(name = "vertx-grpc-transcoding", groupPackage = "io.vertx") 12 | package io.vertx.grpc.transcoding; 13 | 14 | import io.vertx.codegen.annotations.ModuleGen; 15 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | import io.vertx.grpc.server.impl.GrpcHttpInvoker; 2 | 3 | module io.vertx.grpc.transcoding { 4 | requires com.google.protobuf; 5 | requires com.google.protobuf.util; 6 | requires com.google.common; 7 | requires io.vertx.core; 8 | requires io.vertx.grpc.common; 9 | requires io.vertx.grpc.server; 10 | requires static io.vertx.codegen.api; 11 | requires io.netty.codec; 12 | exports io.vertx.grpc.transcoding; 13 | exports io.vertx.grpc.transcoding.impl.config to io.vertx.tests.transcoding; 14 | exports io.vertx.grpc.transcoding.impl to io.vertx.tests.transcoding; 15 | provides GrpcHttpInvoker with io.vertx.grpc.transcoding.impl.TranscodingInvoker; 16 | } 17 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/main/resources/META-INF/services/io.vertx.grpc.server.impl.GrpcHttpInvoker: -------------------------------------------------------------------------------- 1 | io.vertx.grpc.transcoding.impl.TranscodingInvoker 2 | -------------------------------------------------------------------------------- /vertx-grpc-transcoding/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | open module io.vertx.tests.transcoding { 2 | requires io.vertx.testing.unit; 3 | requires junit; 4 | requires io.grpc; 5 | requires io.grpc.stub; 6 | requires io.grpc.util; 7 | requires io.grpc.protobuf; 8 | requires io.vertx.core; 9 | requires io.vertx.grpc.transcoding; 10 | requires io.vertx.grpc.common; 11 | requires io.vertx.grpc.server; 12 | requires io.vertx.tests.common; 13 | requires io.vertx.tests.server; 14 | requires com.google.protobuf; 15 | requires com.google.protobuf.util; 16 | exports io.vertx.tests.transcoding; 17 | } 18 | -------------------------------------------------------------------------------- /vertx-grpcio-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 4.0.0 20 | 21 | 22 | io.vertx 23 | vertx-grpc-aggregator 24 | 5.1.0-SNAPSHOT 25 | ../pom.xml 26 | 27 | 28 | vertx-grpcio-client 29 | 30 | Vert.x gRPC/IO Client 31 | 32 | 33 | 34 | io.vertx 35 | vertx-grpc-client 36 | 37 | 38 | io.vertx 39 | vertx-grpcio-common 40 | ${project.version} 41 | 42 | 43 | io.grpc 44 | grpc-stub 45 | 46 | 47 | io.grpc 48 | grpc-api 49 | 50 | 51 | 52 | io.vertx 53 | vertx-grpc-common 54 | ${project.version} 55 | test-jar 56 | test 57 | 58 | 59 | io.vertx 60 | vertx-grpc-client 61 | ${project.version} 62 | test-jar 63 | test 64 | 65 | 66 | 67 | org.bouncycastle 68 | bcpkix-jdk15on 69 | test 70 | 71 | 72 | io.grpc 73 | grpc-netty-shaded 74 | test 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /vertx-grpcio-client/src/main/java/io/vertx/grpcio/client/GrpcIoClientChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpcio.client; 12 | 13 | import io.grpc.*; 14 | import io.vertx.core.net.SocketAddress; 15 | import io.vertx.grpc.client.GrpcClient; 16 | 17 | import java.util.concurrent.Executor; 18 | 19 | /** 20 | * Bridge a gRPC service with a {@link io.vertx.grpc.client.GrpcClient}. 21 | */ 22 | public class GrpcIoClientChannel extends io.grpc.Channel { 23 | 24 | private GrpcIoClient client; 25 | private SocketAddress server; 26 | 27 | public GrpcIoClientChannel(GrpcClient client, SocketAddress server) { 28 | this.client = (GrpcIoClient) client; 29 | this.server = server; 30 | } 31 | 32 | @Override 33 | public ClientCall newCall(MethodDescriptor methodDescriptor, CallOptions callOptions) { 34 | String encoding = callOptions.getCompressor(); 35 | Compressor compressor; 36 | if (encoding != null) { 37 | compressor = CompressorRegistry.getDefaultInstance().lookupCompressor(encoding); 38 | } else { 39 | compressor = null; 40 | } 41 | Executor exec = callOptions.getExecutor(); 42 | Context ctx = Context.current(); 43 | Deadline deadline = callOptions.getDeadline(); 44 | Deadline contextDeadline = ctx.getDeadline(); 45 | if (contextDeadline != null && (deadline == null || contextDeadline.isBefore(deadline))) { 46 | deadline = contextDeadline; 47 | } 48 | return new VertxClientCall<>(client, server, exec, methodDescriptor, encoding, compressor, deadline); 49 | } 50 | 51 | @Override 52 | public String authority() { 53 | return null; 54 | } 55 | 56 | public GrpcIoClient client() { 57 | return client; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /vertx-grpcio-client/src/main/java/io/vertx/grpcio/client/impl/GrpcIoClientBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpcio.client.impl; 12 | 13 | import io.vertx.core.Vertx; 14 | import io.vertx.core.http.HttpClient; 15 | import io.vertx.grpc.client.GrpcClientOptions; 16 | import io.vertx.grpc.client.impl.GrpcClientBuilderImpl; 17 | import io.vertx.grpcio.client.GrpcIoClient; 18 | 19 | public class GrpcIoClientBuilder extends GrpcClientBuilderImpl { 20 | 21 | public GrpcIoClientBuilder(Vertx vertx) { 22 | super(vertx); 23 | } 24 | 25 | @Override 26 | protected GrpcIoClient create(Vertx vertx, GrpcClientOptions options, HttpClient transport) { 27 | return new GrpcIoClientImpl(vertx, options, transport, true); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vertx-grpcio-client/src/main/java/io/vertx/grpcio/client/impl/GrpcIoClientImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpcio.client.impl; 12 | 13 | import io.grpc.MethodDescriptor; 14 | import io.vertx.core.Future; 15 | import io.vertx.core.Vertx; 16 | import io.vertx.core.http.*; 17 | import io.vertx.core.net.Address; 18 | import io.vertx.grpc.client.GrpcClientOptions; 19 | import io.vertx.grpc.client.GrpcClientRequest; 20 | import io.vertx.grpc.common.ServiceMethod; 21 | import io.vertx.grpc.client.impl.GrpcClientImpl; 22 | import io.vertx.grpc.common.GrpcMessageDecoder; 23 | import io.vertx.grpc.common.GrpcMessageEncoder; 24 | import io.vertx.grpc.common.ServiceName; 25 | import io.vertx.grpcio.client.GrpcIoClient; 26 | import io.vertx.grpcio.common.impl.BridgeMessageDecoder; 27 | import io.vertx.grpcio.common.impl.BridgeMessageEncoder; 28 | 29 | /** 30 | * @author Julien Viet 31 | */ 32 | public class GrpcIoClientImpl extends GrpcClientImpl implements GrpcIoClient { 33 | 34 | public GrpcIoClientImpl(Vertx vertx, HttpClient client) { 35 | super(vertx, client); 36 | } 37 | 38 | public GrpcIoClientImpl(Vertx vertx, GrpcClientOptions grpcOptions, HttpClient client, boolean close) { 39 | super(vertx, grpcOptions, client, close); 40 | } 41 | 42 | @Override 43 | public Future> request(MethodDescriptor service) { 44 | GrpcMessageDecoder messageDecoder = new BridgeMessageDecoder<>(service.getResponseMarshaller(), null); 45 | GrpcMessageEncoder messageEncoder = new BridgeMessageEncoder<>(service.getRequestMarshaller(), null); 46 | ServiceMethod serviceMethod = ServiceMethod.client(ServiceName.create(service.getServiceName()), service.getBareMethodName(), messageEncoder, messageDecoder); 47 | return request(serviceMethod); 48 | } 49 | 50 | @Override public Future> request(Address server, MethodDescriptor service) { 51 | GrpcMessageDecoder messageDecoder = new BridgeMessageDecoder<>(service.getResponseMarshaller(), null); 52 | GrpcMessageEncoder messageEncoder = new BridgeMessageEncoder<>(service.getRequestMarshaller(), null); 53 | ServiceMethod serviceMethod = ServiceMethod.client(ServiceName.create(service.getServiceName()), service.getBareMethodName(), messageEncoder, messageDecoder); 54 | return request(server, serviceMethod); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /vertx-grpcio-client/src/main/java/io/vertx/grpcio/client/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | @ModuleGen(name = "vertx-iogrpc-client", groupPackage = "io.vertx") 12 | package io.vertx.grpcio.client; 13 | 14 | import io.vertx.codegen.annotations.ModuleGen; 15 | -------------------------------------------------------------------------------- /vertx-grpcio-common/src/main/java/io/vertx/grpcio/common/Dummy.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpcio.common; 2 | 3 | /** 4 | * Triggers javadoc plugin 5 | */ 6 | public class Dummy { 7 | } 8 | -------------------------------------------------------------------------------- /vertx-grpcio-common/src/main/java/io/vertx/grpcio/common/impl/ReadStreamAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpcio.common.impl; 12 | 13 | import io.vertx.grpc.common.GrpcReadStream; 14 | 15 | /** 16 | * An adapter between gRPC and Vert.x back-pressure. 17 | */ 18 | public class ReadStreamAdapter { 19 | 20 | private GrpcReadStream stream; 21 | private int request = 0; 22 | 23 | /** 24 | * Init the adapter with the stream. 25 | */ 26 | public final void init(GrpcReadStream stream, BridgeMessageDecoder decoder) { 27 | stream.messageHandler(msg -> { 28 | handleMessage(decoder.decode(msg)); 29 | }); 30 | stream.endHandler(v -> { 31 | handleClose(); 32 | }); 33 | this.stream = stream; 34 | stream.pause(); 35 | if (request > 0) { 36 | stream.fetch(request); 37 | } 38 | } 39 | 40 | /** 41 | * Override this to handle close event 42 | */ 43 | protected void handleClose() { 44 | 45 | } 46 | 47 | /** 48 | * Override this to handle message event 49 | */ 50 | protected void handleMessage(T msg) { 51 | 52 | } 53 | 54 | /** 55 | * Request {@code num} messages 56 | */ 57 | public final void request(int num) { 58 | if (stream != null) { 59 | stream.fetch(num); 60 | } else { 61 | request += num; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /vertx-grpcio-common/src/main/java/io/vertx/grpcio/common/package-info.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpcio.common; 2 | -------------------------------------------------------------------------------- /vertx-grpcio-common/src/main/resources/META-INF/services/io.vertx.core.spi.VertxServiceProvider: -------------------------------------------------------------------------------- 1 | io.vertx.grpc.common.impl.GrpcRequestLocalRegistration 2 | -------------------------------------------------------------------------------- /vertx-grpcio-common/src/test/java/io/vertx/tests/common/UtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2023 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.tests.common; 12 | 13 | import io.grpc.Metadata; 14 | import io.vertx.core.MultiMap; 15 | import io.vertx.grpcio.common.impl.Utils; 16 | import org.junit.Test; 17 | 18 | import java.util.List; 19 | import java.util.stream.Collectors; 20 | import java.util.stream.StreamSupport; 21 | 22 | import static org.junit.Assert.assertEquals; 23 | import static org.junit.Assert.assertTrue; 24 | 25 | public class UtilsTest { 26 | 27 | /** 28 | * Reproduce #35 29 | */ 30 | @Test 31 | public void testReadMetadata() { 32 | MultiMap headers = MultiMap.caseInsensitiveMultiMap(); 33 | 34 | headers.add("key0", "value0"); 35 | headers.add("key1", "value1"); 36 | headers.add("key0", "value2"); 37 | 38 | Metadata metadata = Utils.readMetadata(headers); 39 | assertEquals(2, metadata.keys().size()); 40 | 41 | List l = StreamSupport.stream(metadata.getAll(Metadata.Key.of("key0", Metadata.ASCII_STRING_MARSHALLER)).spliterator(), false) 42 | .collect(Collectors.toList()); 43 | assertEquals(2, l.size()); 44 | assertTrue(l.contains("value0")); 45 | assertTrue(l.contains("value2")); 46 | 47 | l = StreamSupport.stream(metadata.getAll(Metadata.Key.of("key1", Metadata.ASCII_STRING_MARSHALLER)).spliterator(), false) 48 | .collect(Collectors.toList()); 49 | assertEquals(1, l.size()); 50 | assertTrue(l.contains("value1")); 51 | } 52 | 53 | @Test 54 | public void lowercaseMetadata() { 55 | MultiMap headers = MultiMap.caseInsensitiveMultiMap(); 56 | 57 | headers.add("Authorization", "test"); 58 | 59 | Metadata metadata = Utils.readMetadata(headers); 60 | assertEquals(1, metadata.keys().size()); 61 | 62 | String authorization = metadata.get(Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER)); 63 | 64 | assertEquals("test", authorization); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /vertx-grpcio-context-storage/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | 9 | io.vertx 10 | vertx-grpc-aggregator 11 | 5.1.0-SNAPSHOT 12 | ../pom.xml 13 | 14 | 15 | vertx-grpcio-context-storage 16 | 17 | Vert.x gRPC/IO Context Storage implementation 18 | This modules provides an io.grpc.override.ContextStorageOverride implementation which uses Vert.x local 19 | context data maps. 20 | 21 | 22 | 23 | 24 | io.vertx 25 | vertx-grpc-common 26 | 27 | 28 | io.grpc 29 | grpc-api 30 | 31 | 32 | 33 | io.vertx 34 | vertx-unit 35 | test 36 | 37 | 38 | io.vertx 39 | vertx-grpcio-client 40 | ${project.version} 41 | test 42 | 43 | 44 | io.vertx 45 | vertx-grpcio-server 46 | ${project.version} 47 | test 48 | 49 | 50 | io.grpc 51 | grpc-netty-shaded 52 | test 53 | 54 | 55 | 56 | 57 | 58 | 59 | org.xolstice.maven.plugins 60 | protobuf-maven-plugin 61 | 62 | 63 | test-compile 64 | 65 | test-compile 66 | test-compile-custom 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /vertx-grpcio-context-storage/src/main/java/io/vertx/grpc/contextstorage/ContextStorageService.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.contextstorage; 2 | 3 | import io.vertx.core.internal.VertxBootstrap; 4 | import io.vertx.core.spi.VertxServiceProvider; 5 | import io.vertx.core.spi.context.storage.ContextLocal; 6 | 7 | /** 8 | * Register the local storage. 9 | */ 10 | public class ContextStorageService implements VertxServiceProvider { 11 | 12 | public static final ContextLocal CONTEXT_LOCAL = ContextLocal.registerLocal(GrpcStorage.class); 13 | 14 | @Override 15 | public void init(VertxBootstrap builder) { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /vertx-grpcio-context-storage/src/main/java/io/vertx/grpc/contextstorage/GrpcStorage.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpc.contextstorage; 2 | 3 | import io.grpc.Context; 4 | import io.vertx.core.internal.ContextInternal; 5 | 6 | /** 7 | * gRPC context storage. 8 | */ 9 | public class GrpcStorage { 10 | 11 | public final io.grpc.Context currentGrpcContext; 12 | public final io.vertx.core.internal.ContextInternal prevVertxContext; 13 | 14 | public GrpcStorage(Context currentGrpcContext, ContextInternal prevVertxContext) { 15 | this.currentGrpcContext = currentGrpcContext; 16 | this.prevVertxContext = prevVertxContext; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vertx-grpcio-context-storage/src/main/resources/META-INF/services/io.vertx.core.spi.VertxServiceProvider: -------------------------------------------------------------------------------- 1 | io.vertx.grpc.contextstorage.ContextStorageService 2 | -------------------------------------------------------------------------------- /vertx-grpcio-context-storage/src/test/proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | syntax = "proto3"; 31 | 32 | option java_multiple_files = true; 33 | option java_package = "io.grpc.examples.helloworld"; 34 | option java_outer_classname = "HelloWorldProto"; 35 | option objc_class_prefix = "HLW"; 36 | 37 | package helloworld; 38 | 39 | // The greeting service definition. 40 | service Greeter { 41 | // Sends a greeting 42 | rpc SayHello (HelloRequest) returns (HelloReply) {} 43 | } 44 | 45 | // The request message containing the user's name. 46 | message HelloRequest { 47 | string name = 1; 48 | } 49 | 50 | // The response message containing the greetings 51 | message HelloReply { 52 | string message = 1; 53 | } 54 | -------------------------------------------------------------------------------- /vertx-grpcio-server/src/main/java/io/vertx/grpcio/server/GrpcIoServer.java: -------------------------------------------------------------------------------- 1 | package io.vertx.grpcio.server; 2 | 3 | import io.grpc.BindableService; 4 | import io.grpc.MethodDescriptor; 5 | import io.grpc.ServerServiceDefinition; 6 | import io.vertx.codegen.annotations.GenIgnore; 7 | import io.vertx.codegen.annotations.VertxGen; 8 | import io.vertx.core.Handler; 9 | import io.vertx.core.Vertx; 10 | import io.vertx.core.buffer.Buffer; 11 | import io.vertx.grpc.server.*; 12 | import io.vertx.grpcio.server.impl.GrpcIoServerImpl; 13 | 14 | /** 15 | * A gRPC server based on Vert.x HTTP server. 16 | * 17 | * This server extends the {@link GrpcServer} to encode/decode messages in protobuf format using {@link io.grpc.MethodDescriptor}. 18 | * 19 | * This server exposes 2 levels of handlers 20 | * 21 | *

      22 | *
    • a Protobuf message {@link #callHandler(Handler) handler}: {@link GrpcServerRequest}/{@link GrpcServerResponse} with Protobuf message that handles any method call in a generic way
    • 23 | *
    • a gRPC message {@link #callHandler(MethodDescriptor, Handler) handler}: {@link GrpcServerRequest}/{@link GrpcServerRequest} with gRPC messages that handles specific service method calls
    • 24 | *
    25 | */ 26 | @VertxGen 27 | public interface GrpcIoServer extends GrpcServer { 28 | 29 | /** 30 | * Create a blank gRPC server with default options. 31 | * 32 | * @return the created server 33 | */ 34 | static GrpcIoServer server(Vertx vertx) { 35 | return server(vertx, new GrpcServerOptions()); 36 | } 37 | 38 | /** 39 | * Create a blank gRPC server with specified options. 40 | * 41 | * @param options the gRPC server options 42 | * @return the created server 43 | */ 44 | static GrpcIoServer server(Vertx vertx, GrpcServerOptions options) { 45 | return new GrpcIoServerImpl(vertx, options); 46 | } 47 | 48 | @Override 49 | GrpcIoServer callHandler(Handler> handler); 50 | 51 | /** 52 | * Set a service method call handler that handles any call made to the server for the {@link MethodDescriptor} service method. 53 | * 54 | * @param handler the service method call handler 55 | * @return a reference to this, so the API can be used fluently 56 | */ 57 | @GenIgnore(GenIgnore.PERMITTED_TYPE) 58 | GrpcIoServer callHandler(MethodDescriptor methodDesc, Handler> handler); 59 | 60 | /** 61 | * Like {@link #addService(Service)} with a gRPC/IO {@link BindableService}. 62 | */ 63 | @GenIgnore(GenIgnore.PERMITTED_TYPE) 64 | default GrpcIoServer addService(BindableService bindableService) { 65 | return (GrpcIoServer) addService(GrpcIoServiceBridge.bridge(bindableService)); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /vertx-grpcio-server/src/main/java/io/vertx/grpcio/server/GrpcIoServiceBridge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpcio.server; 12 | 13 | import io.grpc.BindableService; 14 | import io.grpc.ServerServiceDefinition; 15 | import io.vertx.grpc.server.GrpcServer; 16 | import io.vertx.grpc.server.Service; 17 | import io.vertx.grpcio.server.impl.GrpcIoServiceBridgeImpl; 18 | 19 | /** 20 | * Bridge a gRPC service with a {@link GrpcServer}. 21 | */ 22 | public interface GrpcIoServiceBridge extends Service { 23 | 24 | /** 25 | * Create a stub for a given {@code service}. 26 | * 27 | * @param service the service 28 | * @return the stub 29 | */ 30 | static GrpcIoServiceBridge bridge(ServerServiceDefinition service) { 31 | return new GrpcIoServiceBridgeImpl(service); 32 | } 33 | 34 | /** 35 | * Create a stub for a given {@code service}. 36 | * 37 | * @param service the service 38 | * @return the stub 39 | */ 40 | static GrpcIoServiceBridge bridge(BindableService service) { 41 | return bridge(service.bindService()); 42 | } 43 | 44 | /** 45 | * Bind all service methods to the @{code server}. 46 | * 47 | * @param server the server to bind to 48 | */ 49 | void bind(GrpcIoServer server); 50 | 51 | @Override 52 | default void bind(GrpcServer server) { 53 | bind((GrpcIoServer) server); 54 | } 55 | 56 | /** 57 | * Unbind all service methods from the @{code server}. 58 | * 59 | * @param server the server to unbind from 60 | */ 61 | void unbind(GrpcIoServer server); 62 | 63 | } 64 | -------------------------------------------------------------------------------- /vertx-grpcio-server/src/main/java/io/vertx/grpcio/server/impl/GrpcIoServerImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2024 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | package io.vertx.grpcio.server.impl; 12 | 13 | import io.grpc.MethodDescriptor; 14 | import io.vertx.core.Handler; 15 | import io.vertx.core.Vertx; 16 | import io.vertx.core.buffer.Buffer; 17 | import io.vertx.grpc.common.*; 18 | import io.vertx.grpc.server.*; 19 | import io.vertx.grpc.server.impl.GrpcServerImpl; 20 | import io.vertx.grpcio.common.impl.BridgeMessageDecoder; 21 | import io.vertx.grpcio.common.impl.BridgeMessageEncoder; 22 | import io.vertx.grpcio.common.impl.Utils; 23 | import io.vertx.grpcio.server.GrpcIoServer; 24 | 25 | /** 26 | * @author Julien Viet 27 | */ 28 | public class GrpcIoServerImpl extends GrpcServerImpl implements GrpcIoServer { 29 | 30 | public GrpcIoServerImpl(Vertx vertx, GrpcServerOptions options) { 31 | super(vertx, options); 32 | } 33 | 34 | @Override 35 | public GrpcIoServerImpl callHandler(Handler> handler) { 36 | return (GrpcIoServerImpl) super.callHandler(handler); 37 | } 38 | 39 | public GrpcIoServerImpl callHandler(MethodDescriptor methodDesc, Handler> handler) { 40 | ServiceMethod serviceMethod = ServiceMethod.server(ServiceName.create( 41 | methodDesc.getServiceName()), 42 | methodDesc.getBareMethodName(), 43 | new BridgeMessageEncoder<>(methodDesc.getResponseMarshaller(), null), 44 | new BridgeMessageDecoder<>(methodDesc.getRequestMarshaller(), null) 45 | ); 46 | return (GrpcIoServerImpl) callHandler(serviceMethod, handler); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /vertx-grpcio-server/src/main/java/io/vertx/grpcio/server/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2022 Contributors to the Eclipse Foundation 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Eclipse Public License 2.0 which is available at 6 | * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 7 | * which is available at https://www.apache.org/licenses/LICENSE-2.0. 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 10 | */ 11 | @ModuleGen(name = "vertx-iogrpc-server", groupPackage = "io.vertx") 12 | package io.vertx.grpcio.server; 13 | 14 | import io.vertx.codegen.annotations.ModuleGen; 15 | --------------------------------------------------------------------------------